requestAnimationFrame
在网页开发中实现动画实现动画的方式有下面几种。css中的 transition 和 animation。js中通过计时setInterval来触发动画。requestAnimationFrame是H5提供一个专门用于请求动画的API。
requestAnimationFrame的特性
系统来决定回调函数的执行时间。如果屏幕刷新率是60Hz(每秒60次的频率刷新),那么回调函数就每1000/60=16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,requestAnimationFrame的执行时间跟着系统的刷新刷新走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。
setInterval的动画存在的问题
setInterval是通过定时,在一定时间间隔后,通过改变属性来达到动画的目的,而位置的变化必须要等到屏幕下次刷新时才会被更新到屏幕上,所以setInterval实现的动画可能会出现卡顿、抖动的现象,这是因为动画执行的时间不确定(任务队列,假设设定的时间是10ms,但是10ms后不一定会运行),还有就是屏幕的刷新频率不一样。如下面代码(假设60HZ,10毫秒后,动画一定执行):
var move= document.getElementById('test');
var t=1;
setInterval(() => {
t=t+10;
move.style.marginLeft=t+'px';
}, 10);
0ms: marginLeft 0
10ms marginLeft 1 (但是屏幕上位置并没有变化,因为屏幕没有刷新)
16.7ms: marginLeft 1(屏幕上的位置变化)
20ms: marginLeft 2 (但是屏幕上位置并没有变化,因为屏幕没有刷新)
30ms: marginLeft 3 (但是屏幕上位置并没有变化,因为屏幕没有刷新)
33.3ms: marginLeft 3 (屏幕上的位置变化)
但是我们可以看到屏幕上的位置是从1变化到了3,跳帧了。
requestAnimationFrame的实现
var progress=0;
function render() {
progress += 1;
window.requestAnimationFrame(render);
moveTwo.style.marginLeft=progress+'px';
}
window.requestAnimationFrame(render);
比较效果图
requestAnimationFrame其余优势:
CPU节:requestAnimationFrame在页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。
函数节流:在高频率事件中,使用requestAnimationFrame可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销。