キャンバス グラフィックスをアニメーション化する方法 (HTML)

[ この記事は、Windows ランタイム アプリを作成する Windows 8.x および Windows Phone 8.x 開発者を対象としています。Windows 10 向けの開発を行っている場合は、「最新のドキュメント」をご覧ください]

キャンバス要素は HTML ドキュメント上に描画できる領域で、JavaScript を使って、アニメーション、グラフ、ゲームなどのグラフィックスを生成できます。 このトピックでは、キャンバス要素を使う基本的な描画をアニメーション化するために必要な手順について説明します。

必要条件

このトピックの前提条件は次のとおりです。

  • JavaScript テンプレート用 Windows ライブラリを使う、JavaScript で開発された基本的な Windows ストア アプリを作成できる。
  • HTML と JavaScript の基本を把握している必要があります。

JavaScript を使った Windows ストア アプリを初めて作成する場合は、「JavaScript を使った初めての Windows ストア アプリの作成」をご覧ください。WinJS テンプレートの使い方について詳しくは、「WinJS ツールキットの取得および使用方法」をご覧ください。

手順

ステップ 1: アニメーションのタイミング

requestAnimationFrame メソッドを使い、次の再描画のためにアニメーションを更新する場合に常に呼び出す (コールバックする) 関数を指定することによって、アニメーションを開始します。

requestAnimationFrame(animationFunction);

requestAnimationFrame は、ページの表示状態と画面のリフレッシュ レートを考慮して、アニメーションに割り当てる 1 秒当たりのフレームの数を決定します (つまり、animationFunction を呼び出す)。

ここでは、大きな円を描くようにらせん状に移動する円のアニメーションを描画する JavaScript の例を示します。

requestAnimationFrame(draw);

次に、アニメーションの例を示します (結果はさまざまであり、ハードウェアの処理速度が速いほどぎっしり詰まった円になります)。

キャンバス アニメーションを使って描画されるらせん状の円の例。

ステップ 2: 画像の描画

  1. キャンバスのクリア

    各フレームを描画する前に、キャンバスをクリアする必要があります。

    キャンバスをクリアする方法 (または画像の一部をクリアする方法) にはいくつかの方法があります。たとえば、globalCompositOperation プロパティを使ったり、clip メソッドでクリッピング パスを使ったりして、特定の領域をクリアできます。 キャンバスをクリアする最も簡単な方法は、clearRect メソッドを使う方法です。

    ここで示す例では、clearRect メソッドを使ってキャンバス全体をクリアしていますが、画像描画の効果をわかりやすくするため、clearRect メソッドをコメント アウトしてあります。 この行がコメント アウトされていない場合、大きな円を描くようにらせん状に移動する 1 つの円が描かれ、各フレームを描画する前に軌跡がクリアされます。

    // The clearRect method clears the entire canvas.
    context.clearRect(0, 0, 160, 160);
    
  2. キャンバスの状態の保存

    画像を描画するときに、スタイル、変換などの一部の設定を変更することがあります。 画像を再描画するときに元の設定を使う必要がある場合は、save メソッドを使います。

    save メソッドと restore メソッドを使って、キャンバスの状態をスタックに保存し、スタックから取得します。 キャンバスの状態は、適用されているすべてのスタイルと変換で構成されています。save メソッドを呼び出すたびに、現在のキャンバスの状態がスタックに保存されます。 restore メソッドを呼び出すと、スタックから最も新しい状態が返されます。

    ここで示す例では、円のアニメーションの描画と移動の変換を設定する直前に、save メソッドが使われています。

    // Save the canvas state.
    context.save();
    
  3. 画像の描画

    画像をキャンバスに描画するときに、移動メソッドと回転メソッドの 2 種類の変換を使って画像を変更できます。

    移動メソッドは、キャンバスとその原点をキャンバス グリッド内の別の場所に移動するために使います。

    translate(x, y)
    

    このメソッドには 2 つの引数があります。x はキャンバスを左右に移動する量、y は上下に移動する量です。

    キャンバスを元の状態に戻す場合、逆方向の変換を使うよりも restore メソッドを呼び出す方が簡単であるため、変換を実行する前にキャンバスの状態を保存することをお勧めします。 translate メソッドを使うと、座標を手動で調整することなく、キャンバス内の任意の場所に画像を配置できます。

    rotate メソッドは、現在の原点を中心としてキャンバスを回転させるために使います。 このメソッドのパラメーターは 1 つのみで、キャンバスを回転させる角度をラジアン単位で指定します。

    rotate(angle)
    

    時計回りの方向に回転され、回転の中心点は常にキャンバスの原点 (左上隅) です。 中心点を移動するには、translate メソッドを使ってキャンバスを移動する必要があります。

    ここで示す例では、translate メソッドと rotate メソッドをいくつか交互に使っています。最初に呼び出す translate メソッドでは、アニメーションをキャンバスの中心に配置します。

    次に、rotate メソッドと translate メソッドの組み合わせを 2 回呼び出します。 最初に呼び出す rotate メソッドと translate メソッドの組み合わせでは、大きなループをキャンバス上に描く小さな円が描画されます。2 つ目の組み合わせの呼び出しでは、もっと小さい軌道を描く小さい円が描画されます。

    キャンバスのサイズは、高さ 160 ピクセル、幅 160 ピクセルに設定されているため、移動メソッドの x 座標と y 座標を 80 に設定して、アニメーション全体がキャンバスの中心に配置されるようにします。

    // centers the image on the canvas             
    context.translate(80, 80);
    

    最初に呼び出す rotate メソッドの先頭で、date オブジェクトを使って rotate メソッドのパラメーターを計算しています。このパラメーターはキャンバスを回転させる角度です。

    var time = new Date();
    context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
    

    getSeconds の計算に使われる値は 60 ですが、getMilliseconds の計算に使われる値は 60,000 です。

    translate メソッドによって x 座標が移動します。これによって、大きな軌道でキャンバス内を回転する円が移動します。

    // Translate determines the size of the circle's orbit.
    context.translate(50, 0);
    

    最初の rotate メソッドと translate メソッドを実行した結果は次のようになります。

    ループしていない大きな円。

    次に呼び出される 2 組の rotate メソッドと translate メソッドでは、ループしている小さい方の円軌道が作成されます。

    // Rotate causes the circle to move in a small orbit.
    context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
    
    // Translate determines the size of the orbit.
    context.translate(0, 5);
    

    2 つ目の回転メソッド呼び出しの角度計算で、getSeconds の計算に使われる値は 6、getMilliseconds の計算に使われる値は 6,000 です。

    最初の rotate メソッドと translate メソッドをコメント アウトしておくと、2 つ目の rotate メソッドと translate メソッドでは次のように描画されます。

    ループしている円。

    再配置のための設定がすべて行われた後で、円がキャンバスに描かれます。

    // This draws the repositioned circle
    context.beginPath();
    context.arc(5, 5, 4, 0, Math.PI*2, true); 
    context.stroke();
    
  4. キャンバスの状態の復元

    前の手順 b. でキャンバスの状態を保存してあるため、次のフレームを描くためにキャンバスの状態をリセットします。

    // Restores the canvas to the previous state
    context.restore();
    

完全な例

グラフィックスのアニメーション化

この JavaScript の例では、大きな円を描くようにらせん状に移動する円のアニメーションを描画します。

window.onload = init;
  
// As an optimization, make "context" a global variable that is only set once.
var context;
  
function init(){
  context = document.getElementById('canvas').getContext('2d');    
  window.requestAnimationFrame(draw);
} // init

function draw() {
  // Save the canvas state.
  context.save();         
  
  // context.clearRect(0, 0, 160, 160);

  // centers the image on the canvas             
  context.translate(80, 80); 
  
  // Rotate moves the spiraling circle around the canvas in a large orbit.
  var time = new Date();
  context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
  
  // Translate determines the location of the small circle.
  context.translate(50, 0);  
  
  // Rotate causes the circle to spiral as it circles around the canvas.
  context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
  
  // determines the size of the loop
  context.translate(0, 5);  
  
  // This draws the circle
  context.beginPath();
  context.arc(5, 5, 4, 0, Math.PI*2, true); 
  context.stroke();
  
  // Restores the canvas to the previous state
  context.restore();
  window.requestAnimationFrame(draw);
}  // draw

キャンバス要素の周りに黒の境界線を作成するカスケード スタイル シート (CSS) の例を次に示します。

/* style the canvas element with a black border. */
canvas { border: 1px solid black; }

次の HTML ファイルでは、キャンバス要素が作成され、外部の JavaScript ファイルと CSS ファイルが使われます。

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="myJavascript.js"></script>
        <link Rel="stylesheet" Href="myStyle.css" Type="text/css">
    </head>
    <body>
        <canvas id="canvas" width="160" height="160" />
    </body>
</html>

関連トピック

クイック スタート: キャンバスへの描画