<div>
<canvas id="canvas" width="400px" height="400px'"></canvas>
</div>
:root {
--background: rgba(22,22,22,1);
}
body {
background: var(--background);
}
div {
width: 400px;
margin: 0 auto;
}
View Compiled
// https://www.maissan.net/articles/javascript-spirograph
var canvas = document.getElementById("canvas");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext("2d");
var canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
// fun things to change
const backgroundColor = `rgba(22,22,22,1)`
const strokeWidth = 3;
var radius1 = 20;
var radius2 = 100;
var ratio = 10;
const color1 = chroma.random().hex();
const color2 = chroma.random().hex();
const color3 = chroma.random().hex();
document.documentElement.style
.setProperty('--background', backgroundColor);
function drawSpirograph(context, cx, cy, radius1, radius2, ratio, color, limit = 2) {
let x, y;
let theta = 0;
const draw = setInterval(() => {
// Move to starting point (theta = 0)
context.beginPath();
if (!x) {
context.moveTo(cx + radius1 + radius2, cy);
} else {
context.moveTo(x, y);
}
// Draw segments from theta = 0 to theta = 2PI
var R = radius1;
var r = radius2;
var angle = theta;
var d = ratio;
x = cx + radius1 * Math.cos(theta) + radius2 * Math.cos(theta * ratio);
y = cy + radius1 * Math.sin(theta) + radius2 * Math.sin(theta * ratio);
context.lineTo(x, y);
// Apply stroke
ctx.strokeStyle = color;
ctx.lineWidth = strokeWidth;
context.stroke();
if (theta > Math.PI * limit) {
clearInterval(draw);
}
theta += 0.01;
}, 0);
}
drawSpirograph(
ctx,
canvas.width / 2,
canvas.height / 2,
radius1,
radius2,
ratio,
color1
);
drawSpirograph(
ctx,
canvas.width / 2,
canvas.height / 2,
radius1 * 5,
radius2 - 20,
ratio / 2,
color2,
);
drawSpirograph(
ctx,
canvas.width / 2,
canvas.height / 2,
radius1 * 6,
radius2 / 5,
ratio * 60,
color3,
8
);
View Compiled
This Pen doesn't use any external CSS resources.