requestAnimationFrame を使って一定速度で移動する物体を canvas に描画する


やること

setInterval のかわりに requestAnimationFrame を使う場合に、物体を一定速度で動かすンプルです。特に難しいことはしてませんが、やろうとするたびに忘れるので、最小限のコードをメモっときます。

覚えておくべき

  • 開始時刻を覚えておいて、現在時刻との差分をとって、差分から位置を計算する。
  • 時刻は window.performance.now() で取得するのがよいらしい
    • そこまでシビアでなければ Date.now() でも問題なさそう。
    • new date().gettime() はブラウザによって遅いらしい? (要調査)
  • requestAnimationFrame は記述の方法がいくつかある。
sample.js
function update(){
    ...
}

(function loop(){
    update();
    window.requestAnimationFrame(loop);
}());

これで update() の中にループ処理を書く方法と

sample2.js
function update()
{
    ...
    window.requestAnimationFrame(update);
}

window.requestAnimationFrame(update);

setInterval() のようにループ処理の最後に再度 requestAnimationFrame を呼ぶ方法がある。ループの処理が固定であれば、前者のほうが若干スマートか。

サンプルコード

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset=utf-8>
<title>Constant Fall</title>
</head>
<body>
    <canvas id="canvas" width="640" height="480"></canvas>
    <br/>
    royalcrab@超Lチカ団 (c) 2020.

<script>
var canvas;
var ctx;
var startTime = Date.now();

var ball = {
    "x": 0,
    "y": 0
};

function init()
{
    canvas = document.getElementById("canvas");
    if ( ! canvas || ! canvas.getContext ) { return false; }
    ctx = canvas.getContext('2d');
}

function update()
{
    if ( ! canvas || ! canvas.getContext ) { return false; }
    ctx.fillStyle = "gray";
    ctx.fillRect( 0, 0, canvas.clientWidth, canvas.clientHeight );

    var currentTime = Date.now();
    var diff = currentTime - startTime;

    ctx.fillStyle = "rgb(255, 0, 0)";
    ctx.fillRect( 100, (diff % 960) / 2, 40, 20 );
}

(function loop(){
    update();
    window.requestAnimationFrame(loop);
}());

init();
</script>
</body>
</html>

おためし

下記URLにコードを置きました。ブラウザで直接ためせます。
- https://royalcrab.github.io/animation_sample1.html

参考