定义
requestAnimationFrame
帧动画,又叫 RAF
,在 requestAnimationFrame
中执行的事件叫 RAF
回调
setInterval
引用 MDN
的定义
Window 和 Worker 接口提供的setInterval()
方法重复调用一个函数或执行一个代码片段,在每次调用之间具有固定的时间间隔。它返回一个
interval ID
,该ID
唯一地标识时间间隔,因此你可以稍后通过调用 clearInterval() 来移除定时器。
区别
不同点
requestAnimationFrame
会把每一帧中的所有DOM
操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60
帧- 在隐藏或不可见的元素中,
requestAnimationFrame
将不会进行重绘或回流,这当然就意味着更少的的cpu, gpu
和内存使用量 setTimeout/setInterval
会造成丢帧,requestAnimationFrame
不会,有人测试过setTimeout(callback, 0)
的执行时机为4.7ms
,对于某些屏幕来说这太快了,就拿60HZ
刷新率的屏幕来说,浏览器的刷新频率为每秒60
帧,也就是1000/60 = 16.7ms
,浏览器在16.7ms
的时候显示一帧,也就是浏览器会渲染一次,假设上面的setTimeout
没有干扰,固定4.7ms
执行一次,它执行3
次以后,浏览器才会显示第3
次的动画执行结果,前2
次的运行没有意义,浏览器不会渲染也看不见,这个就是过度绘制导致丢帧,而requestAnimationFrame
是根据帧数刷新的,它会在浏览器渲染前一点或者后一点执行(具体实现要看浏览器),它能保证动画可以根据浏览刷新率进行不会丢帧丢帧的危害
- 动画断断续续显示
- 过度绘制会对电池使用寿命造成负面影响,并会降低其他应用的性能
setTimeout/setInterval
会造成跳帧,requestAnimationFrame
不会,假设我们直到屏幕的刷新率并将其设置为setTimeout/setInterval
的执行时间,但仍然会因为其不够精确,某一次的渲染可能会执行两次setTimeout/setInterval
的回调,导致出现跳帧,requestAnimationFrame
因为是帧动画就不会有这个问题setTimeout/setInterval
有性能问题,requestAnimationFrame
不会,因为requestAnimationFrame
是根据帧数刷新的,而setInterval
是根据时间刷新的,也就是说setInterval
在页面停止渲染,浏览器切换回后台后也是会继续执行,但实际上动画没有更新,因为页面已经停止渲染,而requestAnimationFrame
只有在页面渲染的时候会执行
共同点
requestAnimationFrame
和setInterval
都可能被阻塞,因为JS
引擎和渲染引擎是互斥的,因此当存在大量JS
计算时,setInterval
会因为前面的宏任务或者微任务执行过久而导致无法及时更新动画,而requestAnimationFrame
是在渲染引擎执行时执行的,同样需要等待JS
引擎执行结束