requestAnimationframe 的理解

59 阅读2分钟

情景介绍

实现动画效果的方法有很多,js中可以通过定时器 setTimeout 来实现。 css3中可以使用transitionanimation 来实现,HTML5中的canvas也可以实现。除此之外,HTML5还提供了了一个用于专门处理动画的API, 那就是 requestAnimationFrame,顾名思义就是请求动画帧

MDN有对该方法的描述:

备注:  若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用 window.requestAnimationFrame()

语法window.requestAnimationFrame(callback); 其中,callback是下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。

取消动画:  使用cancelAnimationFrame()来取消执行动画,该方法接收一个参数——window.requestAnimationFrame默认返回的id,只需要传入这个id就可以取消动画了。

使用该方法有什么好处?

  • cpu节能:如果使用定时器实现的动画,页面最小化或者被隐藏的时候,定时器仍然是在执行的,页面不可见状态下刷新动画是毫无意义的,同时也在浪费cpu资源。使用RequestAnimationFrame效果则截然不同,页面处理不可见状态下,RequestAnimationFrame方法也会停止渲染动画,因为它window下的方法,是跟随系统走的,当页面再次可见的时候,动画会从上次停止的地方继续执行,这样大大节省了cpu的开销。
  • 函数节流:在js的一些高频函数中(scroll、rsize),这时候一般都是实现函数节流,目的是为了防止一个刷新时间间隔内多次执行函数,而RequestAnimationFrame能保证每个刷新时间间隔内,函数只会执行一次,在保证性能的同时,也能节省函数执行的开销,其实在一个刷新间隔内,多次执行函数是没有意义的。
  • 减少DOM操作requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

额外提一下setTimeout执行动画的缺点

setTimeout是通过设置间隔的时间来不断改变图像的位置,实现动画的效果,但是页面卡顿,抖动的现象也会随之出现,其原因是:

  • settimeout任务被放入异步队列,只有当主线程任务执行完后才会执行队列中的任务,因此实际执行时间总是比设定时间要晚;
  • settimeout的固定时间间隔不一定与屏幕刷新间隔时间相同,会引起丢帧。