gpt4 book ai didi

javascript - 如何将 requestAnimationFrame 与 setInterval 一起使用?

转载 作者:行者123 更新时间:2023-11-28 14:46:22 24 4
gpt4 key购买 nike

请参阅以下代码片段。

它会在单击按钮时创建加载程序。但是动画并不流畅。

我最近读到有关requestAnimationFrame 函数的内容,它可以完成这项工作。但是我如何使用它来完全替换 setInterval,因为无法在 requestAnimationFrame 函数中指定时间。

可以和setInterval一起使用吗?

let idx = 1;
const timetoEnd = 5000;

function ProgressBar(width){
this.width = width || 0;
this.id = `pBar-${idx++}`;
this.create = () => {
let pBar = document.createElement('div');
pBar.id = this.id;
pBar.className = `p-bar`;
pBar.innerHTML = `<div class="loader"></div>`;
return pBar;
};
this.animator = () => {
let element = document.querySelector(`#${(this.id)} div`);
if(this.width < 100){
this.width++;
element.style.width = `${this.width}%`;
} else {
clearInterval(this.interval);
}
};
this.animate = () => {
this.interval = setInterval(this.animator, timetoEnd/100);
}
}

function addLoader (){
let bar1 = new ProgressBar(40);
let container = document.querySelector("#container");
container.appendChild(bar1.create());
bar1.animate();
}
.p-bar{
width: 400px;
height: 20px;
background: 1px solid #ccc;
margin: 10px;
overflow:hidden;
border-radius: 4px;
}
.p-bar .loader{
width: 0;
background: #1565C0;
height: 100%;
}
<input type="button" value="Add loader" onclick="addLoader()" />
<div id="container"></div>

最佳答案

你是对的,requestAnimationFrame 是在做动画时避免 UI 堵塞的推荐方法。

您可以记住开始时的绝对开始时间,而不是尝试在每一帧都这样做。然后,只需根据开始时间和当前时间之间的增量时间计算宽度即可。

此外,document.querySelector 被认为是一个相对“繁重”的操作,因此我添加了 this.element 以避免在每一帧执行它。

这里是如何计算新的宽度:((100 - this.startWidth)/timetoEnd) * deltaT + this.startWidth

  1. 100 - this.startWidth 是我们必须设置动画的总宽度
  2. (100 - this.startWidth)/timetoEnd 是每秒必须添加到 (1) 的宽度
  3. ((100 - this.startWidth)/timetoEnd) * deltaT 是我们必须添加到 (1) 的宽度
  4. 我们只需将整个 this.startWidth px 移动到框架的宽度

另请注意,其中一些计算是恒定的,不必在每一帧上计算,我将其留作练习:)

这是您稍微修改过的代码:

let idx = 1;
const timetoEnd = 5000;

function ProgressBar(startWidth){
this.startWidth = startWidth || 0;
this.id = `pBar-${idx++}`;
this.create = () => {
let pBar = document.createElement('div');
pBar.id = this.id;
pBar.className = `p-bar`;
pBar.innerHTML = `<div class="loader"></div>`;
return pBar;
};
this.animator = () => {
const deltaT = Math.min(new Date().getTime() - this.start, timetoEnd);
if(deltaT < timetoEnd){
const width = ((100 - this.startWidth) / timetoEnd) * deltaT + this.startWidth;
this.element.style.width = `${width}%`;
requestAnimationFrame(this.animator.bind(this))
}
};
this.animate = () => {
this.element = document.querySelector(`#${(this.id)} div`);
this.start = new Date().getTime();
this.animator();
}
}

function addLoader (){
let bar1 = new ProgressBar(40);
let container = document.querySelector("#container");
container.appendChild(bar1.create());
bar1.animate();
}
.p-bar{
width: 400px;
height: 20px;
background: 1px solid #ccc;
margin: 10px;
overflow:hidden;
border-radius: 4px;
}
.p-bar .loader{
width: 0;
background: #1565C0;
height: 100%;
}
<input type="button" value="Add loader" onclick="addLoader()" />
<div id="container"></div>

关于javascript - 如何将 requestAnimationFrame 与 setInterval 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52270477/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com