持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
定义
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引擎执行结束