使用 requestAnimationFrame 实现高性能JS动画

吐槽君 分类:javascript

在web开发中,我们通过js的实现动画一般是通过定时器(setTimeoutserInterval)。

定时器实现动画

示例

let animateTimer = setTimer(() => {
 // 动画逻辑......
 // if(...)  clearTimeout(animateTimer )  满足某种条件 清除该动画
},1000/60)
 

这里把显示器屏幕刷新率视为60Hz,即每次屏幕刷新时同步动画。避免因掉帧引起的卡顿感。

定时器实现动画的弊端

  • 1、setTimeoutsetInterval 分别有4毫秒和10毫秒的最小时间间隔,前面如果有复杂的js逻辑会让动画的间隔延迟更长。
  • 2、 使用定时器频繁操作DOM做动画,可能会造成 页面卡顿性能浪费动画掉帧 等问题

requestAnimationFrame(以下用RAF简称)

什么是 RAF

告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行------MDN
说白了,就是你调用RAF并传入一个回调函数,下次页面重绘就会执行传入的回调。

RAF 优势

  • requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
  • 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

清理RAF

如同定时器实现动画一样,某段动画执行完毕怎么清除它。cancelAnimationFrame就是用来清除RAF的方法,每个 requestAnimationFrame 调用都会返回这个动画对应的ID,将这个ID传入到 cancelAnimationFrame(RAFID) 即可清除指定动画

定时器动画与RAF动画对比

用这两种方式分别实现同一个动画,在页面一个盒子,开始从最左侧向右运动,碰到右侧边界开始向左运动,碰到左侧边界就开始向右侧运动不断重复这个动作。
定时器盒子在运动中,感觉有一定的卡顿感(掉帧)。RAF盒子感觉正常。

vu6k7-eitr9.gif

回复

我来回复
  • 暂无回复内容