关于 requestAnimationFrame 小结

1、小谈 requestAnimationFrame:css

提及 requestAnimationFrame,咱们先看幅图:html

 

 至关一部分的浏览器的显示频率是16.7ms, 就是上图第一行的节奏,表现就是“我和你一步两步三步四步往前走……”。若是咱们火力搞猛一点,例如搞个10ms setTimeout,就会是下面一行的模样——每第三个图形都没法绘制(红色箭头指示),表现就是“我和你一步两步 坑四步往前走……”。css3

想象国庆北京高速,最多每16.7s经过一辆车,结果,忽然插入一批 setTimeout的军车,强行要10s经过。显然,这是超负荷的,要想顺利进行,只能让第三辆车直接消失(正如显示绘制第三帧的丢失)。然,这是不现实的,因而就有了会堵车!git

一样的,显示器16.7ms刷新间隔以前发生了其余绘制请求(setTimeout),致使全部第三帧丢失,继而致使动画断续显示(堵车的感受),这就是过分绘制带来的问题。不只如此,这种计时器频率的下降也会对电池使用寿命形成负面影响,并会下降其余应用的性能。github

这也是为什么setTimeout的定时器值推荐最小使用16.7ms的缘由(16.7 = 1000 / 60, 即每秒60帧)。web

而我requestAnimationFrame就是为了这个而出现的。它所作的事情很简单,跟着浏览器的绘制走,若是浏览设备绘制间隔是16.7ms,那我就这个间隔绘制;若是浏览设备绘制间隔是10ms, 我就10ms绘制。这样就不会存在过分绘制的问题,动画不会掉帧,天然流畅的说~~canvas

内部是这么运做的:
浏览器(如页面)每次要洗澡(重绘),就会通知我(requestAnimationFrame):小丸子,我要洗澡了,你能够跟我一块儿洗哦!promise

这是资源很是高效的一种利用方式。怎么讲呢?浏览器

  1. 就算不少个小丸子要一块儿洗澡,浏览器只要通知一次就能够了。而setTimeout貌似是多个独立绘制。
  2. 页面最小化了,或者被Tab切换关灯了。页面是不会洗澡的,天然,小丸子也不会洗澡的(没通知啊)。页面绘制所有中止,资源高效利用。

2、兼容性:异步

 

因此,requestAnimationFrame 一个简单的兼容性代码以下:

(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||    // Webkit中此取消方法的名字变了
                                      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 = window.setTimeout(function() {
                callback(currTime + timeToCall);
            }, timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
    }
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
    }
}());

3、动画效果:

css3 能够实现不少动画效果,贝塞尔曲线是一个标准3次方曲线(详见:贝塞尔曲线与CSS3动画、SVG和canvas的基情),所以,只能是:LinearSineQuadCubicExpo等,以下图:

 

但 css3 对于 BackBounce等缓动则只可观望而不可亵玩焉。

先看一个效果:小球弹起落地效果 (此例结合了 Tweenjs 库)

动画核心代码以下:

funFall = function() {
    var start = 0, during = 100;
    var _run = function() {
         start++;
         var top = Tween.Bounce.easeOut(start, objBall.top, 500 - objBall.top, during);
         ball.css("top", top);
         shadowWithBall(top);    // 投影跟随小球的动
         if (start < during) requestAnimationFrame(_run);
    };
    _run();
};

4、深究 requestAnimationFrame:

事件循环和任务队列机制里边,牵扯到 setTimeout,在讨论浏览器刷新频率的时候,常常将 setTimeout和 requestAnimationFarme做比较。

那么,requestAnimationFarme是否也属于异步任务,若是是的话,是属于macro-task仍是micro-task?

关于macro-task 和 micro-task:

一、macrotasks包含:主js、UI渲染、setTimeout、setInterval、setImmediate、requestAnimationFarme、I/O等
二、microtasks包含:process.nextTick、promise、Object.observe等

具体详见:

从Promise来看JavaScript中的Event Loop、Tasks和Microtasks

理解事件循环一(浅析)

Promise的队列与setTimeout的队列有何关联

 

参考连接:https://www.zhangxinxu.com/wordpress/2013/09/css3-animation-requestanimationframe-tween-%e5%8a%a8%e7%94%bb%e7%ae%97%e6%b3%95/

相关文章
相关标签/搜索