JavaScript is not available.

           

Copyright © 2016-2018 MediaKobo Co., Ltd. All rights reserved.
JavaScript コンソール       ホーム       目次

アニメーション

アニメーションの単純な実現

 JavaScript でアニメーションやシミュレーションなどの長時間ループやループ中の処理経過を表示する場合には、注意が必要です。 以下のような、ランダムな線分を描くプログラムを実行すると、途中経過は表示されず最終結果のみが表示されます。 また、実行時間が長時間に及ぶ場合にはブラウザによっては警告が発せられます。

var canvas = document.getElementById('jsccanvas');
var context = canvas.getContext('2d');
    context.clearRect(0, 0, 640, 400);

var step = 1;
var r, g, b;
var x0, y0, x1, y1;

x0 = 640 * Math.random();
y0 = 400 * Math.random();

while(step <= 500) {
  ++ step;
  drawline();
}

function drawline() {
  r = Math.floor(255 * Math.random());
  g = Math.floor(255 * Math.random());
  b = Math.floor(255 * Math.random());
  x1 = 640 * Math.random();
  y1 = 400 * Math.random();
  context.beginPath();
  context.strokeStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
  context.moveTo(x0, y0);
  context.lineTo(x1, y1);
  context.stroke();
  x0 = x1;
  y0 = y1;
}

 実行途中で処理を開放しなかったために、意図した結果が得られない様です。 以下の、ループを実現している処理に、問題がありそうです。

while(step <= 500) {
  ++ step;
  drawline();
}

setInterval によるアニメーションの実現

 インターバルタイマを利用して、ループの各ステップが、タイマで呼び出されるようにして、処理を開放します。 こうすることで、ループ処理の途中経過が表示され、長時間ループによる警告も発せられなくなります。

上記プログラムの while ループを以下の様に書き換えます。

jscsetintervalid = setInterval(function() {
  if(step >= 500) {
    clearInterval(jscsetintervalid);
    jscsetintervalid = null;
  }
  ++ step;
  drawline();
}, 10);

 setInterval の返値である ID を jscsetintervalid に保存すると、本環境では Cls ボタンを押したときに、アニメーションループがキャンセルされます。 本環境の様な機能が実現されてない環境では、アニメーションループは設定したステップ数が終了するまで処理が継続されます。

var canvas = document.getElementById('jsccanvas');
var context = canvas.getContext('2d');
    context.clearRect(0, 0, 640, 400);

var step = 1;
var r, g, b;
var x0, y0, x1, y1;

x0 = 640 * Math.random();
y0 = 400 * Math.random();

jscsetintervalid = setInterval(function() {
  if(step >= 500) {
    clearInterval(jscsetintervalid);
    jscsetintervalid = null;
  }
  ++ step;
  drawline();
}, 10);

function drawline() {
  r = Math.floor(255 * Math.random());
  g = Math.floor(255 * Math.random());
  b = Math.floor(255 * Math.random());
  x1 = 640 * Math.random();
  y1 = 400 * Math.random();
  context.beginPath();
  context.strokeStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
  context.moveTo(x0, y0);
  context.lineTo(x1, y1);
  context.stroke();
  x0 = x1;
  y0 = y1;
}

requestAnimationFrame によるアニメーションの実現

 ブラウザが備えているアニメーション機能によって、実現します。 こうすることで、ループ処理の途中経過が表示され、長時間ループによる警告も発せられなくなります。

上記プログラムのループを以下の様に書き換えます。

function loop() {
  if(step >= 500) {
    clearInterval(jscrequestanimationid);
    jscrequestanimationid = null;
  } else {
    jscrequestanimationid = requestAnimationFrame(loop);
  }
  ++ step;
  drawline();
}
jscrequestanimationid = requestAnimationFrame(loop);

 requestAnimationFrame の返値である ID を jscrequestanimationid に保存すると、本環境では Cls ボタンを押したときに、アニメーションループがキャンセルされます。 本環境の様な機能が実現されてない環境では、アニメーションループは設定したステップ数が終了するまで処理が継続されます。

var canvas = document.getElementById('jsccanvas');
var context = canvas.getContext('2d');
    context.clearRect(0, 0, 640, 400);

var step = 1;
var r, g, b;
var x0, y0, x1, y1;

x0 = 640 * Math.random();
y0 = 400 * Math.random();

function loop() {
  if(step >= 500) {
    clearInterval(jscrequestanimationid);
    jscrequestanimationid = null;
  } else {
    jscrequestanimationid = requestAnimationFrame(loop);
  }
  ++ step;
  drawline();
}

jscrequestanimationid = requestAnimationFrame(loop);

function drawline() {
  r = Math.floor(255 * Math.random());
  g = Math.floor(255 * Math.random());
  b = Math.floor(255 * Math.random());
  x1 = 640 * Math.random();
  y1 = 400 * Math.random();
  context.beginPath();
  context.strokeStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
  context.moveTo(x0, y0);
  context.lineTo(x1, y1);
  context.stroke();
  x0 = x1;
  y0 = y1;
}

目次へ