Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
171
Help us understand the problem. What is going on with this article?

More than 5 years have passed since last update.

@nekoneko-wanwan

Canvasアニメーションの要点

はじめに

いまさらですがHTML5 Canvasの勉強をはじめました。
Canvas APIを使ったアニメーションの実装は、jQuery animate()css3 keyframesといったものとは考え方が異なります。はじめて調べた時には結構戸惑ったので、同じような方のためにメモしたいと思います。

アニメーション = 再描画

Canvasでは便利なアニメーションメソッドはなく、単純に描画自体を繰り返すことでアニメーションを実現させます。イメージとしては、パラパラまんがのように画面自体が次々と差し替わっていくようなものでしょうか。

アニメーションサンプル

canvas-anim.gif

なお↓ページで実際の動きを確認できます
http://nekoneko-wanwan.github.io/demo/canvas/animation/

Canvasアニメーションの手順

ざっくりと以下のような流れになります

  1. 要素を削除
  2. 要素を描画
  3. 要素を動かす(動かす位置座標を再定義)
  4. 終了フラグが無ければ1.へ戻る

サンプルコード

index.html
<canvas id="myCanvas" width="100" height="100"></canvas>
script.js
function drawLoopSquare() {
    /* Canvas要素の定義など */
    var cs  = document.getElementById('myCanvas');
    var ctx = cs.getContext('2d');
    var w = cs.width;
    var h = cs.height;
    var x = 0;

    /* 描画フロー */
    function render() {
        // Canvas全体をクリア
        ctx.clearRect(0, 0, w, h);

        // 要素を描画する
        ctx.beginPath();
        ctx.strokeRect(x, 0, 10, 10);

        // 要素を動かす
        // 四角形のx座標がCanvasの横幅を超えたら初期位置(x座標を0)へ
        // そうでなければ、x座標を1増やす
        if (x > cs.width) {
            x = 0;
        } else {
            x += 1;
        }

        // このrender関数を繰り返す
        // 下記どちらかを使った場合は、外側でrender()を実行する※1(もしくは即時実行)
        // setTimeout(render, 100);
        // requestAnimationFrame(render);
    }
    /* ※1 */
    // render();

    /* render()関数を繰り返す */
    /* setTimeout、requestAnimationFrameではなく、setIntervalを使う場合 */
    setInterval(render, 100);
}
drawLoopSquare();

再描画を行うためのループメソッドとして、

  • setInterval()
  • setTimeout()
  • requestAnimationFrame()

がよく使用されます。それぞれ以下のように使い分けることができます。

  • 決まった時間でループを行ないたい: setInterval(), setTimeout()
  • 描画負荷を抑えたい・なるべくヌルヌルさせたい: requestAnimationFrame()

requestAnimationFrame()について

requestAnimationFrame()は高速でCPUにやさしいですが、未対応ブラウザも存在します。
対応するためのpolyfillは以下になります。

window.requestAnimFrame = (function() {
  return (
      window.requestAnimationFrame       || 
      window.webkitRequestAnimationFrame || 
      window.mozRequestAnimationFrame    || 
      window.oRequestAnimationFrame      || 
      window.msRequestAnimationFrame     || 
      function(callback, time) {
        var time = time ? time: 1000 / 60;
        window.setTimeout(callback, time);
    }
  );
})();

またrequestAnimationFrameはグローバルなため、場合によってはbindでthisを束縛してやる必要があります。

{
    update: function() {
        // 座標を変更する処理など
    },
    draw: function() {
        // 要素を描画する処理など
    },
    render: function() {
        this.update();
        this.draw();
        requestAnimationFrame(this.render.bind(this));  // 引数にthisを使うためにbind
    }
}

おわりに

まだまだ分かっていないことばかりなので、不正確なところがあればコメントや編集リクエストをお願いします

追記: 2015年5月19日

Canvasイベントについて別途記事を書きました。
http://qiita.com/nekoneko-wanwan/items/9af7fb34d0fb7f9fc870)

171
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
171
Help us understand the problem. What is going on with this article?