@[TOC](requestAnimationFrame() 方法)
一、基本使用
1.基本介绍
window.requestAnimationFrame()
主要是用来实现动画的时候使用的,不管是移动动画还是数字增长动画,使用这个api可以让你的动画看起来非常平滑,因为它是要求浏览器在下次重绘之前调用指定的回调函数更新动画。
它和setInterval的区别是不需要我们去设置时间间隔,因为他会根据我们的屏幕刷新率来决定何时执行回调的内容。
2.创建任务
语法:requestAnimationFrame(callback)
callback
是你需要执行的回调函数,回调函数会传入 DOMHighResTimeStamp
参数,该参数与 performance.now()
的返回值相同,它表示 requestAnimationFrame()
开始执行回调函数的时刻
例如:
window.onload = () => {
const test1 = (timeStamp) => {
console.log('requestAnimationFrame---', timeStamp)
window.requestAnimationFrame(test1)
}
window.requestAnimationFrame(test1)
}
注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用 requestAnimationFrame()。requestAnimationFrame() 是一次性的
执行结果:
可以看到,执行间隔大约为17毫秒,即60hz的刷新率下。
3.清除任务
就像clearInterval一样,我们可以执行window.cancelAnimationFrame()
来清除任务。
requestAnimationFrame()
会返回一个 long 整数,是回调列表中唯一的标识。是个非零值,没有别的意义。你可以传这个值给 window.cancelAnimationFrame() 以取消回调函数的执行。
例如:
let requestAnimation = undefined
window.onload = () => {
const test1 = (timeStamp) => {
console.log('requestAnimationFrame---', timeStamp)
requestAnimation = window.requestAnimationFrame(test1)
window.cancelAnimationFrame(requestAnimation)
}
window.requestAnimationFrame(test1)
}
执行结果:
回调中的 requestAnimationFrame
就被取消了
二、优势所在
我们使用setInterval也可以达到类似的效果,那么requestAnimationFrame 的优势在哪里?
1.平滑执行
requestAnimationFrame
会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。所以每次回调中的内容执行的间隔都是和用户屏幕刷新率相关的,这样动画看起来就会非常平滑。使用setInterval不可避免会有些抖动的现象出现
2.执行间隔稳定
了解微任务、宏任务相关知识的同学应该知道,setInterval在任务队列中是会被阻塞的,这就导致即使我们设定了17毫秒,实际上每次的间隔并不会是刚好17毫秒。但是requestAnimationFrame
可以保证在每一帧都完成回调中的内容渲染。
3.性能提升
requestAnimationFrame
是由浏览器专门为实现动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU和电池的开销。这也能避免使用setInterval的时候出现任务积压的问题。