容易被忽视的RequestAnimationFrame

作者: 蓝瘦额香菇 | 来源:发表于2016-11-24 11:00 被阅读127次

    传统的JS动画都是用 setTimeout 和 setInterval 实现的,后来无意中在网上看到一个新的JS函数 requestAnimationFrame 用它来替代传统的JS动画方法,说是效果更好,当时也没有仔细深究。直到昨天去魅族面试的时候,面试官问我有什么新的办法可以替代传统的JS动画,我说“我知道一个叫 requestAnimationFrame 的函数,它的执行效果更好”。但是让我仔细描述的时候,我就说不下去了,这也是我写这篇博客的初衷,我们学习的过程中一定要知其然比知其所以然,不要什么都略懂,最后落得跟半吊子一样。

    定时器一直都是JS动画的核心技术。而编写动画循环的关键是要知道延迟时间多长合适。一方面,循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,才能确保浏览器有能力渲染产生的变化。

    大多数电脑显示器的刷新频率是60HZ,也就是每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会提升。因此,最平滑动画的最佳循环间隔是 1000ms / 60 ,约为16.7ms。

    传统的 setTimeout 和 setInterval 它们都不是很精确,因为它们实际上只是把动画代码添加到浏览器UI线程队尾以等待执行时间,如果它们前面有其它任务,则必须等前面的任务执行完在执行动画代码。

    而 requestAnimationFrame 采用系统时间间隔,让各种动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。它有如下三个特点:

    • 会把每一帧中所有的DOM操作集中起来,在一次动画操作就完成,并且动画的时间间隔紧紧跟随浏览器的刷新频率(不需要设置时间间隔)。
    • 在隐藏或者不可见的元素中,不会进行动画操作。
    • 当浏览器不是激活状态,不会进行动画操作。

    下面是一个兼容所有浏览器的使用 requestAnimationFrame 的代码(IE9-无该方法)

    (function() {
        var lastTime = 0;
        var vendors = ['ms', 'moz', 'webkit', 'o'];
        for(var x = 0; x < vendors.length && !window.requestAnimationFrame; x++) {
            window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
            window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
        }
        if (!window.requestAnimationFrame) {
            window.requestAnimationFrame = function(callback, element) {
                var currTime = new Date().getTime();
                var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
                var id = setTimeout(function() {
                    callback(currTime + timeToCall);
                }, timeToCall);
                lastTime = currTime + timeToCall;
                return id;
            }
        }
        if (!window.cancelAnimationFrame) {
            window.cancelAnimationFrame = function(id) {
                clearTimeout(id);
            }
        }
    }());
    

    最后附上我利用 requestAnimationFrame 制作的一个 跳动的小球 的DEMO。

    相关文章

      网友评论

        本文标题:容易被忽视的RequestAnimationFrame

        本文链接:https://www.haomeiwen.com/subject/cnrbpttx.html