requestAnimationFrameによるHTML5 canvasのアニメーション

これまでJavaScriptでのアニメーションには、setTimeout()やsetInterval()が使われてきましたが、これらのメソッドはアニメーション用に設計されたわけではないため、色々と問題がありました。現在、W3CのワーキングドラフトにrequestAnimationFrame()が挙がっており、一部のブラウザはベンダープレフィックス付きでサポートを始めています。requestAnimationFrame()を使うことで、処理の高速化や複数のアニメーションの同期といったメリットが期待できます。

requestAnimationFrameを使ったアニメーションのサンプル

requestAnimationFrame()を使った簡単なアニメーションのサンプルを作ってみました。サンプルでは、requestAnimationFrame()でcanvasの描画更新処理を呼び出し、アニメーションさせています。canvas上をクリックするとアニメーションを停止し、再びクリックすると再開します。

アニメーションの開始 requestAnimationFrame

先日、私が確認したかぎりでは、Windows, Mac共にGoogleChrome18.0とFirefox12.0がベンダープレフィックス付きのrequestAnimationFrame()をサポートしています。まだサポートしていないブラウザも多いですが、下記のように記述することで、未対応のブラウザでもsetTimeout()で代用できるようになります。

JavaScript

window.requestAnimationFrame = (function() {
  return window.requestAnimationFrame ||
         window.webkitRequestAnimationFrame ||
         window.mozRequestAnimationFrame ||
         window.msRequestAnimationFrame ||
         window.oRequestAnimationFrame ||
         function(f) { return window.setTimeout(f, 1000 / 60); };
}());

アニメーションを開始するには、requestAnimationFrame()に描画更新処理を行う関数を渡します。その際、アニメーションを停止することを考慮して、戻り値を変数に格納しておきます。サンプルでは、下記のように描画更新処理を行う関数を再帰処理するようにしています。

JavaScript

function update() {
  _degree += _speed;
  _degree = (_degree + 360) % 360;
  draw();
  _animationID = requestAnimationFrame(update);
}

アニメーションの停止 cancelAnimationFrame

requestAnimationFrame()のアニメーションを停止するには、cancelAnimationFrame()を使用します。requestAnimationFrame()と同様に未対応のブラウザがあるため、下記のように記述して、対応していないブラウザではclearTimeout()を実行するようにしておきます。

JavaScript

window.cancelAnimationFrame = (function() {
  return window.cancelAnimationFrame ||
         window.cancelRequestAnimationFrame ||
         window.webkitCancelAnimationFrame ||
         window.webkitCancelRequestAnimationFrame ||
         window.mozCancelAnimationFrame ||
         window.mozCancelRequestAnimationFrame ||
         window.msCancelAnimationFrame ||
         window.msCancelRequestAnimationFrame ||
         window.oCancelAnimationFrame ||
         window.oCancelRequestAnimationFrame ||
         function(id) { window.clearTimeout(id); };
}());

下記は、canvasがクリックされた時に呼ばれるメソッドです。cancelAnimationFrame()の引数にrequestAnimationFrame()の戻り値を渡すことでアニメーションを停止します。

JavaScript

CanvasAnimation.stop = function() {
  _isRunning = false;
  cancelAnimationFrame(_animationID);
};

HTML5 canvasの描画更新処理

HTML5 canvasでアニメーションを表示するには、描画の前にcanvasをクリアする必要があります。下記は、サンプルの描画更新処理を行う関数ですが、clearRect()でcanvasをクリアしてから描画を行っています。この関数をrequestAnimationFrame()に登録した関数から呼び出すことで、ブラウザの画面更新のタイミングでcanvasを更新し、アニメーションしているように見せています。

JavaScript

function draw() {
  _context.clearRect(0, 0, _canvas.width, _canvas.height);
  var x = -_imageWidth * 0.5;
  var y = -_imageHeight;
  for (var i in _flowers) {
    _context.save();
    changeMatrix(_flowers[i]);
    _context.drawImage(_image, x, y, _imageWidth, _imageHeight);
    _context.restore();
  }
}