
Canvas+JavaScriptで同心円上を等速円運動する円を描いた話
はじめに
JavaScriptとCanvasの練習がてら、同心円上を等速円運動する円を描いて遊びました。
具体的には下記を実装してみました。
・同心円上に小さい円を配置する
・小さい円を等速円運動させる

html
ヘッダー画像のページを作ります。
canvasが上下中央に配置されるように、body要素に高さを指定(横幅は勝手にされる)。flexを指定して子要素のcanvasが上下中央に来るようにしました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Circle guruguruguru</title>
<style>
body{
margin: 0px;
padding: 0px;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript" src="main.js"></script>
</body>
</html>
JavaScript
draw関数を10msecごとに描写(つまり100fpsで描写)しています。
draw関数を1回呼ぶごとに、drawCircle関数を13個呼んで、13個の小さい円が表示されるようにします。
小さい円は(x,y)座業を (x-r*sin(t), y-r*cos(t))のような形で指定することで、円運動をさせます。
"use strict";
// async/awaitでループ中にスリープしつつ
// draw関数を呼び出す
(async () => {
let i = 3;
while (true) {
draw(i);
await wait(10); // 10ミリ秒ごとに描写
i++;
}
})();
function wait(msec) {
return new Promise(resolve => setTimeout(resolve, msec));
}
// 動く円を描写
function drawCircle(ctx, i, j, h, w, r, cr, cg, cb, ca){
ctx.beginPath();
ctx.arc(h/2 - j*r*Math.sin(2*Math.PI/360 * i),
w/2 - j*r*Math.cos(2*Math.PI/360 * i),
r,
0,
2*Math.PI); // 円描写(x, y, r, start Rad,end Rad)
ctx.fillStyle = "rgba("+cr+", "+cg+", "+cb+", "+ca+")" ;// 塗りつぶしの色
ctx.fill() ;// 塗りつぶしを実行
}
// 頂点数vertices、頂点を(skip-1)個飛ばしで繋いだ図を描写する
function draw(i) {
console.log(i);
// パラメータ
const height = 1000;
const width = 1000;
const radius = Math.min(height, width)/2*0.03;
// canvasのお作法
const cvs = document.getElementById('canvas'); // canvas要素への参照の取得
const ctx = canvas.getContext('2d'); // コンテキストの取得
cvs.width = width;
cvs.height = height;
// 円を描写
drawCircle(ctx, i*0.1, 0, height, width, radius, 44, 33, 222, 0.75);
drawCircle(ctx, i*0.2, 2, height, width, radius, 54, 44, 222, 0.75);
drawCircle(ctx, i*0.3, 4, height, width, radius, 65, 56, 222, 0.75);
drawCircle(ctx, i*0.4, 6, height, width, radius, 75, 67, 222, 0.75);
drawCircle(ctx, i*0.5, 8, height, width, radius, 86, 78, 222, 0.75);
drawCircle(ctx, i*0.6, 10, height, width, radius, 96, 89, 222, 0.75);
drawCircle(ctx, i*0.7, 12, height, width, radius, 107, 100, 222, 0.75);
drawCircle(ctx, i*0.8, 14, height, width, radius, 117, 111, 222, 0.75);
drawCircle(ctx, i*0.9, 16, height, width, radius, 128, 122, 222, 0.75);
drawCircle(ctx, i*1.0, 18, height, width, radius, 138, 133, 222, 0.75);
drawCircle(ctx, i*1.1, 20, height, width, radius, 149, 144, 222, 0.75);
drawCircle(ctx, i*1.2, 22, height, width, radius, 159, 155, 222, 0.75);
drawCircle(ctx, i*1.3, 24, height, width, radius, 170, 167, 222, 0.75);
}