你可能不瞭解的動畫神器之requestAnimationFrame及其兼容寫法

介紹

  • 此篇文章翻譯自paul_irish( 就任於Google Chrome團隊工程師)
  • 文中提到對requestAnimationFrame的polyfill很是不錯,能夠直接拿來用
  • 原文連接:requestAnimationFrame for Smart Animating

什麼是requestAnimationFrame?

你可能用過定時器實現動畫(經過每隔一段時間去改變元素)。瀏覽器給咱們帶來了個好消息「爲何不提供一個API給開發者,來使一些事情更高效呢」。requestAnimationFrame就是爲動畫而生的API,用於改變dom樣式、canvas或WebGL。javascript

我爲何要使用它?

瀏覽器可以將並發動畫優化爲單個事件流和重繪週期中,從而更流暢。例如同時進行的以下任務:基於js的動畫、css動畫、SVG SMIL。並且,當正在執行動畫的標籤頁不可見時,瀏覽器並不會一直運行它,這就意味着更少的CPU、 GPU和內存的使用,從而延長電池壽命。css

天啦嚕,我能夠吹噓本身的網站對電池更友好?

是的大兄弟Totes McGoats(此人跟做者是啥關係~)java

我應該如何使用它?

下面這段是一個簡單的requestAnimationFrame兼容寫法,當瀏覽器不支持時回退到setTimeout的實現方式:web

// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();


// usage:
// instead of setInterval(render, 16) ....

(function animloop(){
  requestAnimFrame(animloop);
  render();
})();
// place the rAF *before* the render() to assure as close to
// 60fps with the setTimeout fallback.

更加健壯的polyfill

如下代碼是Opera工程師Erik Möller所寫更加健壯的polyfill。你能夠閱讀下,尤爲是在處理4-16ms的延遲時間這段代碼,從而使幀率更接近60fps。你會喜歡上它的,請注意他使用的標準方法名。我同時也修正了cancel方法名稱(WebKit內核的瀏覽器已更改過)。canvas

(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'] || 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);
        };
}());

來看看它的效果

http://jsfiddle.net/XQpzU/435...瀏覽器

requestAnimationFrame API

window.requestAnimationFrame(function(/* time */ time){
  // time ~= +new Date // the unix time
});

該回調函數將當前時間做爲參數傳遞,也正是你說須要的。併發

(此文寫於2011年,下面介紹了不一樣瀏覽器實現上的差別)
Is it ready?
Right now, the Webkit implementation (available in Nightly Safari and Chrome Dev Channel) and the Mozilla one (available in FF4) differ slightly. Mozilla’s has a bug which caps potential framerates at about 30fps.Actually, 「It’s currently capped at 1000/(16 + N) fps, where N is the number of ms it takes your callback to execute. If your callback takes 1000ms to execute, then it’s capped at under 1fps. If your callback takes 1ms to execute, you get about 60fps.」 (thx, Boris) It’ll be fixed though, probably for the next release after FF4 ships. Also Chrome 10 doesn’t have the time parameter (added in m11), FF currently ignores the element argument.app

相關文章
相關標籤/搜索