requestAnimationFrame Web中写动画的另一种挑选

HTML5/CSS3时期,我们要在web里做动画挑选实在已很多了:

你可以用CSS3的animattion+keyframes;

你也可以用css3的transition;

你还可以用经由历程在canvas上作图来完成动画,也可以借助jQuery动画相干的API轻易地完成;

固然最原始的你还可以运用window.setTimout()或许window.setInterval()经由历程不断更新元素的状况位置等来完成动画,条件是画面的更新频次要到达每秒60次才能让肉眼看到流通的动画结果。

如今又多了一种完成动画的计划,那就是还在草案当中的window.requestAnimationFrame()要领。

《requestAnimationFrame Web中写动画的另一种挑选》

初识requestAnimationFrame

来看MDN上对其给出的解释:

The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes as an argument a callback to be invoked before the repaint.

window.requestAnimationFrame() 将示知浏览器你立时要最先动画结果了,后者须要在下次动画前挪用响应要领来更新画面。这个要领就是传递给window.requestAnimationFrame()的回调函数。

也可以说这个要领道理实在也就跟setTimeout/setInterval差不多,经由历程递归挪用一致要领来不断更新画面以到达动起来的结果,但它优于setTimeout/setInterval的处所在于它是由浏览器特地为动画供应的API,在运转时浏览器会自动优化要领的挪用,而且假如页面不是激活状况下的话,动画会自动停息,有用节省了CPU开支。

基础语法

可以直接挪用,也可以经由历程window来挪用,吸收一个函数作为回调,返回一个ID值,经由历程把这个ID值传给window.cancelAnimationFrame()可以作废该次动画。

requestAnimationFrame(callback)//callback为回调函数

 

一个简朴的例子

模仿一个进度条动画,初始div宽度为1px,在step函数中将进度加1然后再更新到div宽度上,在进度到达100之前,一向反复这一历程。

为了演示轻易加了一个运转按钮。

<div id="test" style="width:1px;height:17px;background:#0f0;">0%</div>
<input type="button" value="Run" id="run"/>

window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
var start = null;
var ele = document.getElementById("test");
var progress = 0;

function step(timestamp) {
    progress += 1;
    ele.style.width = progress + "%";
    ele.innerHTML=progress + "%";
    if (progress < 100) {
        requestAnimationFrame(step);
    }
}
requestAnimationFrame(step);
document.getElementById("run").addEventListener("click", function() {
    ele.style.width = "1px";
    progress = 0;
    requestAnimationFrame(step);
}, false);

 

浏览器支撑状况

既然照样草案状况下引入的一个功用,在运用全我们就须要体贴一下各浏览器对它的支撑状况了。就现在来讲,主流当代浏览器都对它供应了支撑。

更加详细的浏览器兼容性可以在这里看到

Polyfill

Polyfill就是垫片,按发现这个词的人的原话来讲,它就是一段如许的代码,让浏览器原生地支撑我们希冀运用的一些API。

就比方这里的requestAnimationFrame,在看到了上面的浏览器支撑状况后,你就知道了比上面列出的浏览器版本老的就不支撑该要领,但为了让代码可以有更好的浏览器兼容性在老机械上也能运转不报错,我们可以写一些代码让浏览器在不支撑requestAnimationFrame的状况下运用window.setTimeout(),这是一种回退(fallback)到过去的要领。

如许一来,就可以浅显一点的明白polyfill了,它就是备胎。

下面是由Paul Irish及其他贡献者放在GitHub Gist上的代码片断,用于在浏览器不支撑requestAnimationFrame状况下的回退,回退到运用setTmeout的状况。固然,假如你肯定代码是事情在当代浏览器中,下面的代码是没必要的。

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(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 - (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);
    };
}());

 

上面代码作用有二,一是把各浏览器前缀举行一致,二是在浏览器没有requestAnimationFrame要领时将其指向setTimeout要领。

提到备胎代码呢,这里多说一句,在CSS代码中,我们也常常运用这类回退的技能,即对一致条CSS划定规矩,编写多条以差别浏览器前缀开首代码,或许编写一条备用款式。

下面是一个CSS中的备胎代码的例子:

div {
    background: rgb(0, 0, 0); /* fallback */
    background: rgba(0, 0, 0, 0.5);
}

 

代码中设置div背景为黑色带50%的透明度,但IE9-的浏览器是不支撑rbga花样的色彩的,所以浏览器会回退到上一条CSS划定规矩运用rgb色彩。

Reference

  1. article about rAF from css tricks

  2. article about rAF from Paul Irish

  3. what is polyfill

  4. setInterval与requestAnimationFrame的时候距离测试

  5. 求索:GSAP的动画快于jQuery吗?为什么?

  6. 求索:GSAP的动画快于jQuery吗?/ 续 V1.1

by 刘哇勇
编辑 SegmentFault

    原文作者:weakish
    原文地址: https://segmentfault.com/a/1190000000514843
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞