イナヅマTVログ

JavaScript, requestAnimationFrameを下位互換実装するために

| 3件のコメント

requestAnimationFrameはJavaScriptで繰返し処理をするために新たに追加されたメソッドです。
全てのブラウザでサポートされていないので実装するためには下位互換を施さなければなりません。

http://caniuse.com/#search=requestAnimationFrame
上記caniuse.comのリポートだと実装されている方が圧倒的に少ない状況です。
実装されていても-webkit, -mozなどのprefixが必要だったりします。

なぜrequestAnimationFrameを使った方が良いの?

今までの繰返し(loop)処理はtimeベースを使っていました。
setTimeout, setIntervalのどちらかです。
この方式だと、ユーザーがアニメーションしているサイトを表示したまま別のタブ、ウインドウを開いてもタイマーが動いたままになり不必要なメモリを浪費してしまいます。
対策として開発者はユーザーのfocusが外れblurになったらループを止め、focusが戻ったらループを開始する処理を組み込む必要があります。

そこでrequestAnimationFrameです。
jQuery開発メンバーの一人Paul Irishさんのブログによれば、requestAnimationFrameを使うとCPU, GPU, メモリ消費を抑えバッテリーライフをのばせるとのことです。
requestAnimationFrame for smart animating

if you’re running the animation loop in a tab that’s not visible, the browser won’t keep it running

こちらでは2種類の対策コードが公開されています。

ひとつはPaul Irishさんによるもの

 // shim layer with setTimeout fallback
    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              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.

function renter () {}が描画部分になります。上記コード中には実行部分しか記述されていないので、作っておく必要があります。

次はOpera開発エンジニアのErik Möllerさんによるもの

(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 for smart(er) animating
ふむふむ、Erik MöllerさんのコードはrequestAnimationFrameだけでなくcancelAnimationFrameも実装してるのね。
これはステキすぎる。
キャンセルできるのはありがたい。

まだ試してないけど、コードを見るとこんな使い方かな。

var id;
function animloop(){
  id = requestAnimFrame(animloop);
  render();
};
window.onclick = function () {
    cancelAnimationFrame(id);
}
animloop();

MDN: requestAnimationFrame
MDN: cancelAnimationFrame

3件のコメント

  1. ピンバック: 超個人的メモ, JavaScript関連の投稿リンクをまとめておく « イナヅマTVログ

  2. ピンバック: [JavaScript] requestAnimationFrame, cancelAnimationFrame はこう使ってる « イナヅマTVログ

  3. ピンバック: [JavaScript] 今さらながらrequestAnimationFrameをもう一度 « イナヅマTVログ

コメントを残す

必須欄は * がついています