我们平时实现JavaScript动画效果时离不开setInterval或者setTimeout函数,这两个函数本质上相同的。
以setInterval为例,他的作用是以相同的时间间隔执行某个操作,这个时间可以自定义,利用这个特性我们就可以让然也元素跑起来。
可是这个函数有个毛病,他和显示器的刷新频率无法对应。比如说显示器每100毫秒刷新一次,setInterval函数设置的间隔执行也是100毫秒,可是我们没有办法保证显示频率刷新的时候setInterval的操作正好被执行,虽然它们的相对执行时间相同,可绝对时间不一定一致,所以setInterval制作动画的时候会出现丢帧和动画效果生硬不连贯等情况。
requestAnimFrame是H5新标准上的东西,在PC浏览器上会出现兼容问题,在移动端浏览器中可以任意使用。 次函数会接受一个回调函数,当浏览器的显示频率刷新的时候,此函数会被执行。
window.requestAnimationFrame(function( time){
//显示频刷新的时候被执行
});
回调函数有一个参数,是一个相对的时间毫秒值,表示当前的刷新时间。
requestAnimationFrame的回调函数并不能被重复调用,这点和setInterval不同,它和setTimeout类似,回调函数只能被调用一次,只不过setTimeout可以自定义调用时间, requestAnimationFrame的调用时间则是跟着系统的刷新频率走的,所以在实现动画的时候,setTimeout比requestAnimationFrame更加灵活, requestAnimationFrame比setTimeout表现效果更加优秀。
以在3000毫秒内移动1500px距离的动画为例
setTimeout的实现方式
以上代码通过setTimeout每10毫秒为间隔时间改变一次元素的位置以实现元素的动画效果, 当然, 可以通过改变这个间隔时间来微调动画效果,可是你永远没有办法确定最优方案,因为它总会和刷新频率存在交叉。
通过requestAnimationFrame我们可以给出更好的解决方案
如果setTimeout,handler函数也会被递归的重复调用,只是它的调用和显示的刷新频率是一致的,因此动画效果更加顺滑自然,也能找到性能和效果的最佳均衡点,得到最有的解决方案。