Spirograph

스피로그래프

The curve traced by a point inside a small circle as it rolls around inside a larger one. Popularised by the 1965 UK toy of the same name.

Also known as: Hypotrochoid curveRoulette curve
···
js
const c = document.createElement('canvas');
document.body.appendChild(c);
c.style.width = '100%'; c.style.height = '100%';
const ctx = c.getContext('2d');
const cs = getComputedStyle(document.documentElement);
const ACCENT2 = cs.getPropertyValue('--accent-2').trim() || '#f25c8a';
let w, h;
function resize() {
  const dpr = Math.min(devicePixelRatio || 1, 2);
  w = innerWidth; h = innerHeight;
  c.width = w * dpr; c.height = h * dpr;
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
addEventListener('resize', resize);
resize();

const R = 100, r = 37, d = 62; // R,r의 최대공약수로 꽃잎 개수가 정해진다
function point(t) {
  return [(R - r) * Math.cos(t) + d * Math.cos(((R - r) / r) * t), (R - r) * Math.sin(t) - d * Math.sin(((R - r) / r) * t)];
}
const PERIOD = 2 * Math.PI * r; // t 가 이 값만큼 지나면 곡선이 닫힌다(gcd 기반 근사)
const TOTAL_T = PERIOD;
const SEG = 2000;
const pts = [];
for (let i = 0; i <= SEG; i++) pts.push(point((TOTAL_T * i) / SEG));

function draw(frac) {
  const scale = Math.min(w, h) / (2 * (R + d) * 1.15);
  ctx.fillStyle = '#0d0d12'; ctx.fillRect(0, 0, w, h);
  ctx.save();
  ctx.translate(w / 2, h / 2); ctx.scale(scale, scale);
  ctx.strokeStyle = ACCENT2; ctx.lineWidth = 1.6 / scale; ctx.lineJoin = 'round';
  const count = Math.max(2, Math.floor(pts.length * frac));
  ctx.beginPath(); ctx.moveTo(pts[0][0], pts[0][1]);
  for (let i = 1; i < count; i++) ctx.lineTo(pts[i][0], pts[i][1]);
  ctx.stroke();
  ctx.restore();
}
draw(1); // 첫 프레임은 완성된 곡선으로 시작
let start = performance.now();
const DRAW_MS = 2600, HOLD_MS = 1400;
(function loop(t) {
  const elapsed = (t - start) % (DRAW_MS + HOLD_MS);
  draw(Math.min(1, elapsed / DRAW_MS));
  requestAnimationFrame(loop);
})(performance.now());

Roll a small circle of radius r, without slipping, around the inside of a fixed larger circle of radius R, and track where a point at distance d from the small circle's centre goes. That path is called a hypotrochoid, given exactly by x = (R−r)cos t + d·cos((R−r)/r · t) and y = (R−r)sin t − d·sin((R−r)/r · t).

The ratio of R to r sets the number of "petals." A larger greatest common divisor closes the pattern sooner; ratios closer to coprime need many more revolutions before the curve closes, producing a denser pattern. The physical toy realises this no-slip rolling with interlocking gears; this demo just computes the same curve directly and animates it as if a pen were drawing it.

It's used for pattern design, watermark and security motifs (the intricate guilloché curves on banknotes are a close relative of the same idea), and decorative logo backgrounds.

When to use

Use it for decorative patterns and watermark/motif design. Vary the R, r, d ratio to change petal count and density completely.