requestAnimationFrame是什么?
requestAnimationFrame()
即请求动画帧,是HTML5
中提供的动画API
,简称rAF
。可以优化浏览器中并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。
与setTimeout
相比,requestAnimationFrame
最大的优势是由浏览器来决定回调函数的执行时机,即紧跟浏览器的刷新步调。
具体一点讲,如果屏幕刷新频率是60Hz
,那么回调函数每16.7ms
被执行一次,如果屏幕刷新频率是75Hz
,那么这个时间间隔就变成了1000/75=13.3ms
。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,自然不会导致动画的卡顿。屏幕的刷新频率可在电脑中“高级显示设置
”中查看,一般为60Hz
工作中经常遇到动画的情况,之前常用的方法使用setTimeout
或setInterval
实现,但随着应用的越来越复杂,性能方面就会降低。所以选择使用requestAnimationFrame
来实现相同效果。这里就简单记录使用rAF
的方法
<style>
* {
margin: 0;
padding: 0
}
.box {
width: 100px;
height: 100px;
border-radius: 100%;
background: #f00;
position: absolute;
left: 0;
top: 0
}
</style>
<div class="box" id="box"></div>
<script>
let box = document.getElementById('box')
let flag = false
let left = 0
let rAFId = ''
function render() {
if (flag) {
if (left >= 100) {
flag = false
}
box.style.left = `${left++}px`
} else {
if (left <= 0) {
flag = true
}
box.style.left = `${left--}px`
}
}
(function animloop() {
render()
rAFId = window.requestAnimationFrame(animloop)
if (left == 50) {
cancelAnimationFrame(rAFId) // 取消动画
}
})()
</script>
简单用法
let progress = 0
// 回调函数
function render() {
progress++ // 修改图像的位置
if (progress < 100) {
// 在动画没有结束前,递归渲染
window.requestAnimationFrame(render)
}
}
// 第一帧渲染
window.requestAnimationFrame(render);
requestAnimationFrame还有以下优势:
CPU节能:
使用setTimeout实现的动画,当页面被隐藏(隐藏的)或最小化(后台标签页)时,setTimeout
仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,而且还浪费 CPU 资源和电池寿命。而requestAnimationFrame
则完全不同,当页面处于未激活的状态下,该页面的屏幕绘制任务也会被浏览器暂停,因此跟着浏览器步伐走的requestAnimationFrame也会停止渲染
,当页面被激活时,动画就从上次停留的地方继续执行
,有效节省了 CPU 开销,提升性能和电池寿命。