requestAnimationFrame
在Web应用中,实现动画效果的方法比较多,Javascript 中可以通过定时器 setTimeout/ setInterval
来实现,css3 可以使用 transition
和 animation
来实现,html5 中的 canvas
也可以实现。除此之外,html5 还提供一个专门用于请求动画的API,那就是 requestAnimationFrame
。
setTimeout/ setInterval
的显著缺陷就是设定的时间并不精确,它们只是在设定的时间后将相应任务添加到任务队列中,而任务队列中如果还有前面的任务尚未执行完毕,那么后添加的任务就必须等待,这个等待的时间造成了原本设定的动画时间间隔不准。requestAnimationFrame
的到来就是解决这个问题的 ,它采用的是系统时间间隔(约16.7ms),保持最佳绘制效果与效率,使各种网页动画有一个统一的刷新机制,从而节省系统资源,提高系统性能。
如下是MDN文档对requestAnimationFrame
的解释
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
从中可知,该方法需要传入一个回调函数作为参数,且回调函数会在页面被刷新时前调用
语法如下:
window.requestAnimationFrame(callback);
callback
:下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。回调函数会被传入DOMHighResTimeStamp
参数(时间戳,十进制数,单位是毫秒,最小精度为1ms),DOMHighResTimeStamp
指示当前被requestAnimationFrame()
排序的回调函数被触发的时间。返回值
:是个非零值( long 整数),请求 ID ,是回调列表中唯一的标识。可以传这个值给window.cancelAnimationFrame()
以取消回调函数。
注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()
举个例子
var s = 0
function f(DOMHighResTimeStamp) {
s++
console.log(s);
console.log(DOMHighResTimeStamp);
if (s < 99) {
window.requestAnimationFrame(f)
}
}
window.requestAnimationFrame(f)
控制台不断输出s直到99。
接下来,我们实现一个进度条
<body>
<div style="width: 0px;height:12px;line-height: 12px;background: pink;">
0%</div>
<script>
var div=document.querySelector('div')
div.onclick=function(){
var timer=requestAnimationFrame(function fn(){
if(parseInt(div.style.width)<300){
div.style.width=parseInt(div.style.width)+3+'px';
div.innerHTML=parseInt(div.style.width)/3+'%'
timer=requestAnimationFrame(fn)
}else{
cancelAnimationFrame(timer)
}
})
}
</script>
</body>
点击后,进度条逐渐变成100%