#問題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>
#答え
<!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();
}