性能优化-requestAnimationFrame
# 官方简介
官网文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame (opens new window)

- 根据官网简介,我们大致可以知道:
requestAnimationFrame这个api主要是用来做动画的。 - 我们翻译这个英文单词,也能大致明白。request(
请求)Animation(动画)Frame(帧)。
# 带着问题去学习
- 问题1: 前端动画方案有哪些?
- 问题2: 这个api较之前做动画的方式优点有哪些?
# 前端的动画有哪些
主要分类为
css动画和js动画,如下细分:
css动画transition过渡动画animation直接动画(搭配@keyframes)
js动画setInterval或setTimeout定时器(比如不停地更改dom元素的位置,使其运动起来)canvas动画,搭配js中的定时器去运动起来(canvas只是一个画笔,然后我们通过定时器会使用这个画笔去画画-动画)requestAnimationFrame动画(js动画中的较好方案)
另有svg动画标签,不过工作中这种方式是比较少的,这里不赘述
# 这个api较之前做动画的方式优点有哪些
在工作中,做动画最优的方案无疑是css动画,但是某些特定场景下,css动画无法实现我们所需要的需求,此时,我们就要考虑使用js去做动画了
canvas动画的本质也是定时器动画
使用定时器动画干活,实际上是可以的,但是存在一个最大的问题,就是动画会抖动,体验效果不是非常好。
而,使用requestAnimationFrame去做动画,就不会抖动,体验效果很好
下面一个demo动画(分别是上述两种方式实现dom元素向右平移)给大家看一下,就知道具体的区别。我们先看一下效果图:(红色dom是定时器实现、绿色dom是requestAnimationFrame实现)
demo源码: demo (opens new window)
例子观察结论
因为笔者的gif录制软件的问题,看着都有点卡,实际上,大家把下方代码复制一份跑起来看的话,会发现定时器动画在微微颤抖,而requestAnimationFrame动画却稳如老狗
# requestAnimationFrame的语法规则
一言以蔽之:requestAnimationFrame和js中的setTimeout定时器函数基本一致,不过setTimeout可以自由设置间隔时间,而requestAnimationFrame的间隔时间是由浏览器自身决定的,大约是17毫秒左右
- requestAnimationFrame我们可以在控制台输入window,然后展开查看其身上的属性,就能找到了

- 由上图我们可以看到,requestAnimationFrame本质上是一个全局window对象上的一个属性函数,函数是要被执行的,要被调用的。所以我们使时,直接:window.requestAnimationFrame(callBack)即可。
- 和定时器一样其接收的参数callback也是一个函数,即下一次重绘之前更新动画帧所调用的函数,即在这个函数体中,我们可以写对应的逻辑代码(和定时器类似)
- requestAnimationFrame也有返回值,返回值是一个整数,主要是定时器的身份证标识,可以使用 window.cancelAnimationFrame()来取消回调函数执行,相当于定时器中的clearTimeout()。
- 二者也都是只执行一次,想要继续执行,做到类似setInterval的效果,需要写成递归的形式(上述案例中也提到了)
# 为什么定时器会卡,而requestAnimationFrame不会卡
# 为什么定时器会卡
- 我们在手机或者电脑显示屏上看东西时,显示屏会默默的不停地干活(刷新画面)
- 这个刷新值得是每秒钟刷新次数,普通显示器的刷新率约为60Hz(每秒刷新60次),高档的有75Hz、90Hz、120Hz、144Hz等等
- 刷新率次数越高,显示器显示的图像越清晰、越流畅、越丝滑
- 不刷新就是静态的画面,刷新比较低就是卡了,PPT的感觉
- 动画想要丝滑流畅,需要卡住时间点进行代码操作(代码语句赋值、浏览器重绘)
- 所以只需要每隔1000毫秒的60分之一(60HZ)即约为17毫秒,进行一次动画操作即可
- 只要卡住这个17毫秒,每隔17毫秒进行操作,就能确保动画丝滑
- 但是定时器的回调函数,会受到js的事件队列宏任务、微任务影响,可能设定的是17毫秒执行一次,但是实际上这次是17毫秒、下次21毫秒、再下次13毫秒执行,所以并不是严格的卡住了这个60HZ的时间
- 没有在合适的时间点操作,就会出现:类似这样的情况:变、不变、不变、变、不变...
- 于是就出现了,绘制不及时的情况,就会有抖动的出现(以上述案例,位置和时间没有线性对应更新变化导致看起来抖动)
# 为何requestAnimationFrame不会卡
关键点
requestAnimationFrame能够做到,精准严格的卡住显示器刷新的时间,比如普通显示器60HZ它会自动对应17ms执行一次,比如高级显示器120HZ,它会自动对应9ms执行一次。- 当然
requestAnimationFrame只会执行一次,想要使其多次执行,要写成递归的形式。上述案例也给出了递归写法
- 这就是requestAnimationFrame的好处。
- 上述内容验证了:一项新技术新的技术方案的提出,一定是为了解决相关的问题的。
- window.requestAnimationFrame这个api就是解决了定时器不精准的问题的。
编辑 (opens new window)
上次更新: 2025/04/18, 01:42:12