js利用H5的requestAnimationFrame()API实现动画效果
为什么要使用requestAnimationFrame:
- 我们知道,浏览器实现动画绘制无非就是CSS3的动画属性
transition,aniamtion和JavaScript的setTImeOut和setInterval方法(进行DOM的样式循环改变达到动画效果)。说到这可能很多同学都有疑问了,既然有CSS的动画属性这么方便的东西了,为何还要用setTimeOut等js方法这么麻烦呢?我们首先来解决这个疑问。
- CSS3的动画属性与JavaScript的动画方法:
- 一个事物的存在必有其存在的道理,api也不例外,不然早被淘汰了。首先CSS3的动画属性是存在兼容问题的,最明显的就是IE10之后才兼容。而目前主流的向下兼容的标准还是要达到IE9的,所以
setTImeOut等js方法还是主流的动画解决方案。 - 有些动画效果CSS3无法实现,如改变元素
scrollTop的值进行滚动,这样就只能使用js的相关方法了。 - CSS3的动画无法实现过于复杂的动画效果,如CSS3支持控制动画速度赛贝尔曲线的数值有限,更复杂的动画效果得使用js结合相关算法才能完成
- 接着回到正题哈, 那
requestAnimationFrame有setTimeOut和setInterval又有和区别呢,嗯,接下来就是正题了。
setTimeOut和setInterval出现的问题:
- 首先,我们得知道动画的渲染是一帧一帧的进行的,每一帧就是动画的一个静止状态,每一帧连起来就成为了一个动画。因此每一帧的时间间隔要足够短动画才显得平滑流畅,但每一帧又不能间隔得太短,因为浏览器每一秒的渲染能是有限的,而且屏幕的刷新能力也是有限的,大多数的显示器刷新频率是60H也就是每秒60帧,因此浏览器的重绘频率不会超过显示器的刷新频率。
- 所以每一帧大约17秒就是最佳的重绘间隔。那使用就直接使用
setTimeOut或者setInterval,间隔设置为17不就得了?但这样还是不行的。 - 因浏览器的毫秒不精确:浏览器的计时器精度并非精确到毫秒级的,IE8的精确度是15ms多一点,而IE9等大多数的浏览器精确度都在4ms差不多。所以难以保证动画最佳的时间间隔。
- 不同的浏览器渲染能力不同,因此并非每一帧17ms就是最佳渲染间隔。
- 在不需要动画的地方,如后台标签页,动画任然在运行,消耗CPU的性能。
- 因此,h5的
requestAnimationFrame就是解决以上问题的。
- requestAnimationFrame的特点:
requestAnimationFrame会把每一帧中所有的DOM操作集中起来,在一次重绘或者重排中就完成。
requestAnimationFrame重绘或者重排的时间间隔是系统的时间间隔,因为不同的浏览器的系统时间间隔不同,requestAnimationFrame将会保持最佳的绘制间隔,即不会因为绘制间隔时间过短而造成浏览器渲染能力跟不上,也不会因为绘制间隔时间过长,而造成动画卡顿。这样就能在不同的浏览器中实现最佳的绘制效果。
- 在隐藏或者不可见的元素中,
requestAnimationFrame将不会进行重排或者重绘,而运行在页面没有激活的情况下,如requestAnimationFrame运行在后台标签页中,动画将会暂停,有效的节省了CPU的开销。
- 那么,该如何使用
requestAnimationFrame呢?
requestAnimationFrame的具体使用:
requestAnimationFrame使用非常简单,只需传入改变DOM的函数,然后反复调用requestAnimationFrame即可达到动画效果了。requestAnimationFrame返回一个整数型请求id的,可以用cancelAnimationFrame函数去取消传入requestAnimationFrame的回调函数。具体使用可以看MDN的教程。
后话: