火曜日, 4月 22, 2025

Let's start JavaScript 63 
HTML上でスピログラフを描画(改良版)

前回のスピログラフ改良版です。余計なラインが出ないようにしてみました。

■スピログラフのパラメータ
外側の固定円(半径 R)
内側の回転円(半径 r)
描画点の距離 d(内円の中心からの距離)
ステップ数 s(1ユニットのプロット数)
角度 θ(回転角)

■スピログラフの方程式
スピログラフの曲線 (x, y) は、以下のパラメータ方程式で表されます。

基本形(ハイポサイクロイド)
x(θ)=(R-r)cos(θ)+d cos(((R-r)r)θ)
y(θ)=(R-r)sin(θ)-d sin(((R-r)r)θ)

ここで:

θ は回転角(0 から 2π × ループ回数 まで変化)
(R - r) の比が整数であれば閉じた軌跡になる

<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport"
        content="width=device-width, initial-scale=1.0">
<title>スピログラフ描画</title>
<style>
body {
text-align: center;
background-color: #333;
font-family: Arial, sans-serif;
}
canvas {
border: 1px solid #000;
background-color: #000;
margin-top: 10px;
}
input {
margin: 5px;
text-align: right;
width: 40px;
}
.controls {
margin-bottom: 10px;
}
</style>
</head>
<body>
<font color="white">
<h2>スピログラフ描画</h2>
</font>
<div class="controls">
<font color="white">
<label>外円の半径 (R): <input type="number"
            id="R" value="150"></label>
<label>内円の半径 (r): <input type="number"
            id="r" value="70"></label>
<label>ペンの距離 (d): <input type="number"
            id="d" value="100"></label>
<label>ステップ数: <input type="number"
            id="steps" value="200"></label>
<label>回転数: <input type="number"
            id="rotations" value="10"></label>
<button onclick="drawSpirograph()">描画</button>
</font>
</div>
<canvas id="spiroCanvas" width="550" height="550"></canvas>

<script>
function drawSpirograph() {
// ユーザー入力を取得
let R = parseFloat(document.getElementById('R').value);
let r = parseFloat(document.getElementById('r').value);
let d = parseFloat(document.getElementById('d').value);
let steps = parseInt(document.getElementById('steps').
                value, 10);
let rotations = parseInt(document.getElementById('rotations').
                value, 10);

// Canvas の設定
let canvas = document.getElementById('spiroCanvas');
let ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = 'yellow';
ctx.lineWidth = 2;

// 中心座標
let centerX = canvas.width / 2;
let centerY = canvas.height / 2;

// スピログラフの描画
ctx.beginPath();
for (let i = 0; i <= steps * rotations; i++) {
let theta = (Math.PI * 2 * i) / steps;
let x = (R - r) * Math.cos(theta) +
                    d * Math.cos(((R - r) / r) * theta);
let y = (R - r) * Math.sin(theta) -
                    d * Math.sin(((R - r) / r) * theta);
if (i === 0) {
ctx.moveTo(centerX + x, centerY + y);
} else {
ctx.lineTo(centerX + x, centerY + y);
}
}
ctx.stroke();
}

// 初回描画
drawSpirograph();
</script>

</body>
</html>
<!-- index.html -->

実行直後の状態です。

パラメーター変更例(その1)

パラメーター変更例(その2)

パラメーター変更例(その3)