Javascript 如何将requestAnimationFrame与setInterval一起使用?

Javascript 如何将requestAnimationFrame与setInterval一起使用?,javascript,html,css,animation,Javascript,Html,Css,Animation,请参阅下面的代码片段 它会在单击按钮时创建一个加载器。但动画并不平滑 我最近读到了requestAnimationFrame函数,它可以完成这项工作。但是,由于在requestAnimationFrame函数中无法指定时间,我如何使用它来完全替换setInterval 它可以与setInterval一起使用吗 设idx=1; 常数timetoEnd=5000; 功能进度条(宽度){ this.width=宽度| | 0; this.id=`pBar-${idx++}`; this.create

请参阅下面的代码片段

它会在单击按钮时创建一个加载器。但动画并不平滑


我最近读到了
requestAnimationFrame
函数,它可以完成这项工作。但是,由于在
requestAnimationFrame
函数中无法指定时间,我如何使用它来完全替换
setInterval

它可以与
setInterval
一起使用吗

设idx=1;
常数timetoEnd=5000;
功能进度条(宽度){
this.width=宽度| | 0;
this.id=`pBar-${idx++}`;
this.create=()=>{
让pBar=document.createElement('div');
pBar.id=this.id;
pBar.className=`p-bar`;
pBar.innerHTML=`;
返回pBar;
};
this.animator=()=>{
let element=document.querySelector(`${(this.id)}div`);
如果(此宽度小于100){
这个.width++;
element.style.width=`${this.width}%`;
}否则{
clearInterval(这个.interval);
}
};
this.animate=()=>{
this.interval=setInterval(this.animator,timetoEnd/100);
}
}
函数addLoader(){
设bar1=新进度条(40);
let container=document.querySelector(“容器”);
container.appendChild(bar1.create());
bar1.animate();
}
.p-bar{
宽度:400px;
高度:20px;
背景:1px固体#ccc;
利润率:10px;
溢出:隐藏;
边界半径:4px;
}
.p-bar.装载机{
宽度:0;
背景:1565C0;
身高:100%;
}


你说得对,
requestAnimationFrame
是制作动画时避免UI阻塞的推荐方法

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

另外,
document.querySelector
被认为是一个相对“繁重”的操作,所以我添加了
this.element
,以避免在每一帧都这样做

下面是计算新宽度的方法:
((100-this.startWidth)/timetoEnd)*deltaT+this.startWidth

  • 100-这个.startWidth
    是我们必须设置动画的总宽度
  • (100-this.startWidth)/timetoEnd
    是每秒必须增加的宽度(1)
  • ((100-this.startWidth)/timetoEnd)*deltaT
    是我们必须添加到(1)的宽度
  • 我们只需要将整个东西移动到这个。开始移动到px以获得帧的宽度
  • 还请注意,其中一些计算是常量,不必在每一帧上计算,这是我作为练习留下的:)

    以下是您的稍加修改的代码:

    设idx=1;
    常数timetoEnd=5000;
    功能进度条(startWidth){
    this.startWidth=startWidth | | 0;
    this.id=`pBar-${idx++}`;
    this.create=()=>{
    让pBar=document.createElement('div');
    pBar.id=this.id;
    pBar.className=`p-bar`;
    pBar.innerHTML=`;
    返回pBar;
    };
    this.animator=()=>{
    const deltaT=Math.min(new Date().getTime()-this.start,timetoEnd);
    如果(deltaT{
    this.element=document.querySelector(`${(this.id)}div`);
    this.start=new Date().getTime();
    这个。动画师();
    }
    }
    函数addLoader(){
    设bar1=新进度条(40);
    let container=document.querySelector(“容器”);
    container.appendChild(bar1.create());
    bar1.animate();
    }
    .p-bar{
    宽度:400px;
    高度:20px;
    背景:1px固体#ccc;
    利润率:10px;
    溢出:隐藏;
    边界半径:4px;
    }
    .p-bar.装载机{
    宽度:0;
    背景:1565C0;
    身高:100%;
    }
    
    
    :“…回调方法被传递一个参数,
    DOMHighResTimeStamp
    ,该参数指示requestAnimationFrame()排队的回调开始触发的当前时间。”请检查有关如何使用该信息的。您的解决方案看起来不错。但是,只有一个问题,我们是否不清除requestAnimationFrame?
    requestAnimationFrame
    仅请求一个帧,就这一点而言,它的行为类似于
    setTimeout
    。这就是我在这里调用
    requestAnimationFrame
    的原因。我得到了它。不过,我观察到一件事,上面的宽度计算并不能使内部宽度达到100%。如果检查DOM,每个加载程序都以不同的宽度完成。oups:)我的错,我将解决方案编辑为max
    deltaT
    timetoEnd
    。由于我们不知道何时执行死刑,deltaT可能会超过5000人。然而,它并没有使宽度达到100%,所以我在末尾添加了一个小的else if块来实现这一点。:)我接受了你的回答。希望得到回报。