LoginSignup
0
0

More than 3 years have passed since last update.

【入門者向け】Canvas入門講座#11 円をタイマーで動かそう【JavaScript】

Last updated at Posted at 2020-12-01

問題11

中心が(150, 150)、半径50の円を塗りつぶしなさい。
塗りつぶす色はマゼンタ色(#ff00ff)であること。
円を最初右側へ動かし、canvasの右端に到達したら、左側へ動かしなさい。
左端に到達したら、右側へ動かしなさい。
タイマー処理はrequestAnimationFrameで行うこと。
なお、以下のHTMLを使うこと。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>問題11</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => {    
    // ここにプログラムを書く
});
</script>
</head>
<body>
<canvas id="my-canvas" width="500" height="300"></canvas>
</body>
</html>

円がタイマーで移動しました。
image.png

答え

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>問題11</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => {

    const RADIUS = 50;  // 円の半径
    let posX = 150, // 円の中心のX座標
        deltaX = 2; // 円の中心のX方向の移動量

    // アニメーション開始
    anim();

    function anim() {
        posX += deltaX;
        if(posX - RADIUS <= 0) {// 円がcanvasの左端に到達した
            deltaX *= -1;
        } else if(posX + RADIUS >= 500) {// 円がcanvasの右端へ到達した
            deltaX *= -1;
        }
        drawCircle(posX);
        requestAnimationFrame(anim);
    }

    function drawCircle(posX) {
        // コンテキストを取得
        const ctx = $('#my-canvas')[0].getContext('2d');

        // 現在の描画状態を保存する
        ctx.save();

        // canvasをクリア
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

        // 塗りつぶしの色をマゼンタ色にする
        ctx.fillStyle = '#ff00ff';        

        ctx.setTransform(1, 0, 0, 1, posX, 0);

        ctx.beginPath();        // 現在のパスをリセットする
        ctx.arc(0, 150, RADIUS, 0, Math.PI*2, true); // 円を描画する
        ctx.closePath();        // パスを閉じる
        ctx.fill();           // 現在のパスを塗りつぶす

        // 描画状態を保存した時点のものに戻す
        ctx.restore();
    }
});
</script>
</head>
<body>
<canvas id="my-canvas" width="500" height="300"></canvas>
</body>
</html>

解説

円がの半径、円の中心のX座標、
円の中心のX方向の移動量(右側へ動いているときは+2、左側へ動いているときは-2)を定義します。

const RADIUS = 50;  // 円の半径
    let posX = 150, // 円の中心のX座標
        deltaX = 2; // 円の中心のX方向の移動量

アニメーションをタイマーで行う時は
setTimeoutやsetIntervalよりrequestAnimationFrameが推奨されています。
使い方はsetTimeoutと似ています。
最初にanimメソッドを呼んでいますが、animメソッドは円の位置を変更し、描画を行います。
animメソッドの最後でrequestAnimtionFrameを呼び、animメソッド自信を渡しています。
こうすることによって、一定時間(通常は1/60秒)毎にanimメソッドが呼ばれます。

// アニメーション開始
anim();

function anim() {
    posX += deltaX;
    if(posX - RADIUS <= 0) {// 円がcanvasの左端に到達した
        deltaX *= -1;
    } else if(posX + RADIUS >= 500) {// 円がcanvasの右端へ到達した
        deltaX *= -1;
    }
    drawCircle(posX);
    requestAnimationFrame(anim);
}

円の描画は問題10と対して変わりません。

function drawCircle(posX) {
    // コンテキストを取得
    const ctx = $('#my-canvas')[0].getContext('2d');

    // 現在の描画状態を保存する
    ctx.save();

    // canvasをクリア
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    // 塗りつぶしの色をマゼンタ色にする
    ctx.fillStyle = '#ff00ff';        

    ctx.setTransform(1, 0, 0, 1, posX, 0);

    ctx.beginPath();        // 現在のパスをリセットする
    ctx.arc(0, 150, RADIUS, 0, Math.PI*2, true); // 円を描画する
    ctx.closePath();        // パスを閉じる
    ctx.fill();           // 現在のパスを塗りつぶす

    // 描画状態を保存した時点のものに戻す
    ctx.restore();
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0