在 Web 应用中,实现动画效果的方法比较多,JavaScript 中可以通过定时器 setTimeout
来实现,CSS3 可以使用 transition
和 animation
来实现,HTML5 中的 canvas 也可以实现。除此之外,浏览器还提供一种专门用于请求动画的 API,那就是 requestAnimationFrame
。
一、相关概念
为了理解 requestAnimationFrame
背后的原理,我们首先需要了解一下与之相关的几个概念:
1.1 屏幕刷新频率
即图像在屏幕上更新的速度,也即屏幕上的图像每秒钟出现的次数,它的单位是赫兹(Hz)。对于一般的笔记本电脑,这个频率大概是 60Hz,这个值的设定受屏幕分辨率、屏幕尺寸和显卡的影响。
1.2 动画原理
根据屏幕刷新频率的原理,我们可以得出:我们所看到的图像正在以每秒 60 次的频率刷新,由于刷新频率很高,因此你感觉不到它在刷新。而动画本质就是要让人眼看到图像被刷新而引起变化的视觉效果,这个变化要以连贯的、平滑的方式进行过渡。
刷新频率为 60Hz 的屏幕每 16.7ms 刷新一次,我们在屏幕每次刷新前,将图像的位置向右移动一个像素,即 1px。这样一来,屏幕每次刷出来的图像位置都比前一个要差 1px,因此会看到图像在移动;由于我们人眼的视觉停留效应,当前位置的图像停留在大脑的印象还没消失,紧接着图像又被移到了下一个位置,因此才会看到图像在流畅的移动,这就是视觉效果上形成的动画。
二、requestAnimationFrame 用法
2.1 说明
window.requestAnimationFrame()
会告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用
window.requestAnimationFrame
2.2 语法
window.requestAnimationFrame(callback)
2.1.1 参数 callback
下一次重绘之前更新动画帧所调用的函数(即上面说的回调函数)。回调函数会被传入 DOMHighResTimeStamp
参数,该参数是当前回调函数被触发的时间。
2.1.2 返回值
一个 long
整数,请求 ID,是回调列表中唯一的标识。是个非零值,没有特别的意义。可以传这个值给 window.cancelAnimationFrame()
用来取消回调函数。
2.3 示例
const element = document.getElementById('#example')
let start
function step(timestamp) {
if (start === void(0)) {
start = timestamp
}
const elapsed = timestamp - start
element.style.transform = `translateX(${Math.min(0.1 * elapsed, 200)}px)`
// 动画在两秒后停止
if (elapsed < 2000) {
window.requestAnimationFrame(step)
}
}
// 开始执行
window.requestAnimationFrame(step)
三、cancelAnimationFrame 用法
3.1 说明
取消一个先前通过调用 window.requestAnimationFrame()
方法添加到计划中的动画帧请求。
3.2 语法
window.cancelAnimationFrame(requestId)
// Firefox
window.mozCancelAnimationFrame(requestId)
参考链接: