↓の動画が面白かったので自分で実装しました。
↓ここで見れます。
http://riverta.net/gallery/trigonometry/beautiful_trigonometry/main.html
コードは以下の通りです。
<html> <body> <script type="text/javascript" src="trigonometry.js"></script> </body> </html>
const WIDTH = 500; const HEIGHT = 500; const canvas = document.createElement('canvas'); canvas.width = WIDTH; canvas.height = HEIGHT; const context = canvas.getContext('2d'); document.body.appendChild(canvas); const CENTER_X = WIDTH/2; const CENTER_Y = HEIGHT/2; const RADIUS = 200; const NUM_CIRCLES = 12; const T_MAX = 300; class Circle{ constructor(theta, phi, radius, color){ this.theta = theta; this.phi = phi; this.radius = radius; this.color = color; this.t = 0; } update(){ this.theta += 2 * Math.PI / T_MAX; this.t += 1; if(this.t >= T_MAX){ this.t = 0; } } render(context){ context.beginPath(); context.fillStyle = this.color; let x = CENTER_X + RADIUS * Math.cos(this.theta) * Math.cos(this.phi); let y = CENTER_Y + RADIUS * Math.cos(this.theta) * Math.sin(this.phi); context.arc(x, y, this.radius, 0, 2*Math.PI); context.fill(); } } function draw_line(theta){ context.beginPath () ; let x0 = CENTER_X + RADIUS * Math.cos(theta); let y0 = CENTER_Y + RADIUS * Math.sin(theta); context.moveTo(x0, y0) ; let x1 = CENTER_X - RADIUS * Math.cos(theta); let y1 = CENTER_Y - RADIUS * Math.sin(theta); context.lineTo(x1, y1) context.strokeStyle = "gray"; context.lineWidth = 1; context.stroke() ; } const objects = []; const dr = 2 * Math.PI / NUM_CIRCLES; for(let i=0;i<NUM_CIRCLES;i++){ let theta = i * dr / 2; let phi = i * dr / 2; objects.push(new Circle(theta, phi, 5, "black")); } objects[0].color = "red"; count = 0; function loop(timestamp) { context.clearRect(0, 0, WIDTH, HEIGHT); for(let i=0;i<NUM_CIRCLES;i++){ draw_line(i * dr / 2); } objects.forEach((obj) => obj.render(context)); objects.forEach((obj) => obj.update()); window.requestAnimationFrame((ts) => loop(ts)); } window.requestAnimationFrame((ts) => loop(ts));