コアダンプの数だけ強くなれるよ

見習いエンジニアの備忘log

Javascriptのcanvasと遅延処理でアニメーション

Javascriptのcanvasと遅延処理を組み合わせて簡単なアニメーションを描画してみる。夏なので簡単な花火っぽいアニメを作ってみた。

完成品

点火ボタンを押すとお粗末な花火が描画される(た~まや~)


花火風アニメの作り方

花火の描画

任意のサイズのキャンバスを作成して、キャンバスの中心から円形上に直線を描くことで実現する。

円形上に直線を描画するには下記のように三角関数を利用する。

var x0 = canvas.width/2;  //キャンバスの中心(x成分)
var y0 = canvas.height/2; //キャンバスの中心(y成分)
var len = 20;             //描画する直線の長さ
var div = 12;             //描画する直線の数
for(var i = 0; i < div; i++) {
   // tは描画時刻のこと
   var rad = (((360/div) * i) / 180) * Math.PI;
   var x1 = x0 + (len * t) * Math.sin(rad);
   var y1 = y0 + (len * t) * Math.cos(rad);
   var x2 = x0 + (len * (t + 1)) * Math.sin(rad);
   var y2 = y0 + (len * (t + 1)) * Math.cos(rad);
   
   ctx.moveTo(x1, y1);
   ctx.lineTo(x2, y2);
}


遅延処理

動きのあるアニメーションにするためには描画と遅延を組み合わせる必要がある。 遅延はwindow.setTimeout(callback(), msec)を使って描画処理を再帰的に呼び出すことで実現できる。

例えば、描画処理を100ミリ秒ごとに10回実行する処理は下記のように書くことができる。

function drawFireWork(t, ms) {
  // 
  // ここに描画処理
  // 
  if (t < 10) {
    window.setTimeout(function() {drawFireWork(t+1, ms)}, ms);
  }
}

function fire() {
  window.setTimeout(function() {drawFireWork(0, 100)}, 100);
}


ソースコード

下記は本ページに埋め込んだ花火風アニメのソースコード。

<html>
<head>
<canvas id="canv" width="400" height="400" style="background-color:rgb(230,230,230);"></canvas>
<script type="text/javascript">
  function drawFireWork(t, ms) {
    
    var canvas = document.getElementById("canv");
    
    if (canvas.getContext) {
      var ctx = canvas.getContext('2d');
      
      ctx.fillStyle = "rgb(230,230,230)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      
      ctx.strokeStyle = "red"
      ctx.lineWidth = 2;
      ctx.beginPath();
      
      var x0 = canvas.width/2;
      var y0 = canvas.height/2;
      var len = 20;
      var div = 12;
      var rate = 0.9;
      for(var i = 0; i < div; i++) {
         var rad = (((360/div) * i) / 180) * Math.PI;
         var x1 = x0 + (len * t) * Math.sin(rad);
         var y1 = y0 + (len * t) * Math.cos(rad);
         var x2 = x0 + (len * (t + 1)) * Math.sin(rad);
         var y2 = y0 + (len * (t + 1)) * Math.cos(rad);
         
         ctx.moveTo(x1, y1);
         ctx.lineTo(x2, y2);
      }
      
      // 描画内容を実行する
      ctx.stroke();
      
      if (t < (x0 - len * (t+1))) {
        window.setTimeout(function() {drawFireWork(t+1, ms)}, ms);
      } else {
        ctx.fillStyle = "rgb(230,230,230)";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
    }
  }
  
  function fire() {
    window.setTimeout(function() {drawFireWork(0, 100)}, 100);
  }
</script>
</head>
<body>
  <p></p>
  <input type="button" value="点火" onclick="fire()">
</body>
</html>