基本的なアニメーション

 

canvas 要素を制御するスクリプトを使っているので(インタラクティヴな)アニメーションを作ることも非常に簡単です。残念ながら canvas 要素は(Flash と違い)このために使われるように設計されていないので制限があります。 おそらく最も大きな制限は一度図形が描かれるとそれはそこにずっといることです。もしそれを動かす必要があればそれとそれ以前に描かれたすべてを再描画する必要があります。これは複雑なフレームの再描画に多くの時間を費やしパフォーマンスはそれを実行しているコンピュータの速度に大きく依存します。

簡単なアニメーションの作業

フレームを描くときは常にフレームを描くためにあなたが必要とするステップの全てがいります。

  1. canvas を消去
    あなたが描いた図形が完全に canvas を塗りつぶさない限り(例えば背景画像)、以前に描かれたどんな図形も消去しなくてはなりません。これを行うもっとも簡単な方法は clearRect メソッドを使うことです。
  2. canvas 状態を保存
    もしあなたが canvas 状態に影響のある何らかの設定(スタイル、変形、その他)を変更し原始状態がフレームが描かれる毎に使われているかを確認しておきあいなら 保存する必要があります。
  3. 動かす図形を描く
    実際にフレームを描画する作業
  4. canvas 状態を復帰
    もしあなたが状態を保存していたなら新しいフレームを描く前に復帰してください

アニメーションを制御する

図形は直接 canvas メソッドを使うかカスタム関数を呼び出すことで描かれます。通常スクリプトが実行し終わったとき canvas 上にそれらの結果が見えるだけです。例えば for ループの内側からアニメーションすることはできません。 一定時間ごとに描画する関数を実行させる必要があります。このようにアニメーションを制御するには二つの方法があります。一つ目は一定時間ごとに特定の関数を呼び出すために利用できる setIntervalsetTimeout 関数です。

setInterval('animateShape()',500);
setTimeout('animateShape()',500);

もしあなたがユーザの操作をが必要ないなら提供されたコードを繰り返し実行する setInterval を使うのが一番です。上の例の animateShape 関数は 500 ミリ秒(一秒の半分)。 setTimeout 関数は設定された時間後に一度だけ実行します アニメーションを制御する二番目の方法はユーザの入力です。もしあなたがゲームを作りたいならアニメーションの制御にキーボードかマウスのイベントを使うことができるでしょう。イベントリスナを設定することでどんなユーザの操作をつかまえてアニメーション関数を実行します。

以下の例で私はアニメーションを制御する最初の方法を使っています。このページの下には二番目の方法を使っている例へのリンクがあります。

アニメーションの例 1

この例の中で私は太陽系の小さなシミュレーションをアニメートします。

var sun = new Image();
var moon = new Image();
var earth = new Image();
function init(){
  sun.src = 'images/sun.png';
  moon.src = 'images/moon.png';
  earth.src = 'images/earth.png';
  setInterval('draw()',100);
}

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.globalCompositeOperation = 'destination-over';
  ctx.clearRect(0,0,300,300); // canvas を消去

  ctx.fillStyle = 'rgba(0,0,0,0.4)';
  ctx.strokeStyle = 'rgba(0,153,255,0.4)';
  ctx.save();
  ctx.translate(150,150);

  // 地球
  var time = new Date();
  ctx.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
  ctx.translate(105,0);
  ctx.fillRect(0,-12,50,24); // Shadow
  ctx.drawImage(earth,-12,-12);

  // 月
  ctx.save();
  ctx.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
  ctx.translate(0,28.5);
  ctx.drawImage(moon,-3.5,-3.5);
  ctx.restore();

  ctx.restore();

  ctx.beginPath();
  ctx.arc(150,150,105,0,Math.PI*2,true); // Earth orbit
  ctx.stroke();

  ctx.drawImage(sun,0,0,300,300);
}

アニメーションの例 2

function init(){
  clock();
  setInterval('clock()',1000);
}
function clock(){
  var now = new Date();
  var ctx = document.getElementById('canvas').getContext('2d');
  ctx.save();
  ctx.clearRect(0,0,150,150);
  ctx.translate(75,75);
  ctx.scale(0.4,0.4);
  ctx.rotate(-Math.PI/2);
  ctx.strokeStyle = "black";
  ctx.fillStyle = "white";
  ctx.lineWidth = 8;
  ctx.lineCap = "round";

  // 時間のマーク
  ctx.save();
  ctx.beginPath();
  for (i=0;i<12;i++){
    ctx.rotate(Math.PI/6);
    ctx.moveTo(100,0);
    ctx.lineTo(120,0);
  }
  ctx.stroke();
  ctx.restore();

  // 分のマーク
  ctx.save();
  ctx.lineWidth = 5;
  ctx.beginPath();
  for (i=0;i<60;i++){
    if (i%5!=0) {
      ctx.moveTo(117,0);
      ctx.lineTo(120,0);
    }
    ctx.rotate(Math.PI/30);
  }
  ctx.stroke();
  ctx.restore();

  var sec = now.getSeconds();
  var min = now.getMinutes();
  var hr  = now.getHours();
  hr = hr>=12 ? hr-12 : hr;

  ctx.fillStyle = "black";

  // 短針を描く
  ctx.save();
  ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
  ctx.lineWidth = 14;
  ctx.beginPath();
  ctx.moveTo(-20,0);
  ctx.lineTo(80,0);
  ctx.stroke();
  ctx.restore();

  // 長針を描く
  ctx.save();
  ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
  ctx.lineWidth = 10;
  ctx.beginPath();
  ctx.moveTo(-28,0);
  ctx.lineTo(112,0);
  ctx.stroke();
  ctx.restore();

  // 秒針を描く
  ctx.save();
  ctx.rotate(sec * Math.PI/30);
  ctx.strokeStyle = "#D40000";
  ctx.fillStyle = "#D40000";
  ctx.lineWidth = 6;
  ctx.beginPath();
  ctx.moveTo(-30,0);
  ctx.lineTo(83,0);
  ctx.stroke();
  ctx.beginPath();
  ctx.arc(0,0,10,0,Math.PI*2,true);
  ctx.fill();
  ctx.beginPath();
  ctx.arc(95,0,10,0,Math.PI*2,true);
  ctx.stroke();
  ctx.fillStyle = "#555";
  ctx.arc(0,0,3,0,Math.PI*2,true);
  ctx.fill();
  ctx.restore();

  ctx.beginPath();
  ctx.lineWidth = 14;
  ctx.strokeStyle = '#325FA2';
  ctx.arc(0,0,142,0,Math.PI*2,true);
  ctx.stroke();

  ctx.restore();
}

その他の例

  • Canvascape
    3D アドベンチャゲーム (一人称視点シューティングゲーム).
  • A Basic RayCaster
    キーボード操作を使ったアニメーションの方法のよい例
  • canvas adventure
    キーボード操作を使ったよい例