首先,MDN的定义是:
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()
结论:
当你准备更新动画时你应该调用此方法。这将使浏览器在下一次重绘之前调用你传入给该方法的动画函数(即你的回调函数)。回调函数执行次数通常是每秒60次,但在大多数遵循W3C建议的浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配。为了提高性能和电池寿命,因此在大多数浏览器里,当
requestAnimationFrame()运行在后台标签页或者隐藏的<iframe>里时,requestAnimationFrame()会被暂停调用以提升性能和电池寿命。
关于其他:
浏览器渲染
- 在地址栏中输入URL后,当前的浏览器进程中的UI线程会启动一个网络请求线程
- 网络请求线程请求到的数据会经过安全验证,确认安全后,UI线程会开启一个渲染器进程
- 渲染器进程中的主线程负责html解析和js的执行。
- 具体的解析过程就不赘述了,解析出来
Layout Tree后,为了显示到屏幕上会进行栅格化。这会在新开辟的合成器线程中执行 - 合成器线程返回的合成器帧会被回传给浏览器进程,最后显示到屏幕上。
以上是大致流程,有很多细节没讲清楚,比如合成器线程如何栅格化、html如何被解析,这些有机会放到以后解释
那么requestAnimationFrame()发生在哪个阶段?答案是渲染器进程的主线程中,因为在该主线程中不只会解析html还会执行js
动画卡顿原因
以60帧动画为例
每一帧约为16ms,在一帧中,当解析渲染html的用时小于16ms时,一帧中主线程会有空余时间,这时,js会被推入主线程执行。问题在于js如果执行时间太长,比如20ms,会导致js不仅占满了当前帧的空余时间,甚至把下一帧原本用来渲染的时间也占用了,这会造成渲染的阻塞,显示到页面上,就是动画可能会出现卡顿,掉帧
requestAnimationFrame()功效
往该函数中传入1个回调函数,把原先的js代码塞到回调函数中,他会告诉浏览器,我有代码必须在下一帧来临前就执行,这些代码会在下一次渲染前执行完毕。通常,我们这个回调函数里面做一些动画的更新,那么它可以保证下一次渲染前,dom已经通过代码更新了,可以被渲染,这也就防止了页面的阻塞