js利用H5的requestAnimationFrame()API实现动画效果

6,101 阅读4分钟

为什么要使用requestAnimationFrame:

    • 我们知道,浏览器实现动画绘制无非就是CSS3的动画属性transitionaniamtion和JavaScript的setTImeOutsetInterval方法(进行DOM的样式循环改变达到动画效果)。说到这可能很多同学都有疑问了,既然有CSS的动画属性这么方便的东西了,为何还要用setTimeOut等js方法这么麻烦呢?我们首先来解决这个疑问。

      •  CSS3的动画属性与JavaScript的动画方法:

        1. 一个事物的存在必有其存在的道理,api也不例外,不然早被淘汰了。首先CSS3的动画属性是存在兼容问题的,最明显的就是IE10之后才兼容。而目前主流的向下兼容的标准还是要达到IE9的,所以setTImeOut等js方法还是主流的动画解决方案。
        2. 有些动画效果CSS3无法实现,如改变元素scrollTop的值进行滚动,这样就只能使用js的相关方法了。
        3. CSS3的动画无法实现过于复杂的动画效果,如CSS3支持控制动画速度赛贝尔曲线的数值有限,更复杂的动画效果得使用js结合相关算法才能完成
    • 接着回到正题哈, 那requestAnimationFramesetTimeOutsetInterval又有和区别呢,嗯,接下来就是正题了。
      • setTimeOutsetInterval出现的问题:

        1. 首先,我们得知道动画的渲染是一帧一帧的进行的,每一帧就是动画的一个静止状态,每一帧连起来就成为了一个动画。因此每一帧的时间间隔要足够短动画才显得平滑流畅,但每一帧又不能间隔得太短,因为浏览器每一秒的渲染能是有限的,而且屏幕的刷新能力也是有限的,大多数的显示器刷新频率是60H也就是每秒60帧,因此浏览器的重绘频率不会超过显示器的刷新频率。
        2. 所以每一帧大约17秒就是最佳的重绘间隔。那使用就直接使用setTimeOut或者setInterval,间隔设置为17不就得了?但这样还是不行的。
          1. 因浏览器的毫秒不精确:浏览器的计时器精度并非精确到毫秒级的,IE8的精确度是15ms多一点,而IE9等大多数的浏览器精确度都在4ms差不多。所以难以保证动画最佳的时间间隔。
          2. 不同的浏览器渲染能力不同,因此并非每一帧17ms就是最佳渲染间隔。
          3. 在不需要动画的地方,如后台标签页,动画任然在运行,消耗CPU的性能。
    • 因此,h5的requestAnimationFrame就是解决以上问题的。

      • requestAnimationFrame的特点:

        1. requestAnimationFrame会把每一帧中所有的DOM操作集中起来,在一次重绘或者重排中就完成。
        2. requestAnimationFrame重绘或者重排的时间间隔是系统的时间间隔,因为不同的浏览器的系统时间间隔不同,requestAnimationFrame将会保持最佳的绘制间隔,即不会因为绘制间隔时间过短而造成浏览器渲染能力跟不上,也不会因为绘制间隔时间过长,而造成动画卡顿。这样就能在不同的浏览器中实现最佳的绘制效果。
        3. 在隐藏或者不可见的元素中,requestAnimationFrame将不会进行重排或者重绘,而运行在页面没有激活的情况下,如requestAnimationFrame运行在后台标签页中,动画将会暂停,有效的节省了CPU的开销。
    • 那么,该如何使用requestAnimationFrame呢?

requestAnimationFrame的具体使用:

    • requestAnimationFrame使用非常简单,只需传入改变DOM的函数,然后反复调用requestAnimationFrame即可达到动画效果了。requestAnimationFrame返回一个整数型请求id的,可以用cancelAnimationFrame函数去取消传入requestAnimationFrame的回调函数。具体使用可以看MDN的教程

后话: