const CANVAS = document.createElement("canvas"),
CTX = CANVAS.getContext("2d"),
NUM_BODIES = 15,
COLOR_MULT = 255 / NUM_BODIES;
let animating = true,
radius;
const setCanvasSize = () => {
CANVAS.width = window.innerWidth;
CANVAS.height = window.innerHeight;
radius = CANVAS.width >= CANVAS.height
? CANVAS.height * 0.4
: CANVAS.width * 0.4;
};
const drawTemplate = () => {
CTX.beginPath();
CTX.arc(CANVAS.width * 0.5, CANVAS.height * 0.5, radius, 0, Math.PI * 2);
CTX.closePath();
CTX.stroke();
}
const drawMain = delta => {
let i = 1;
let j = 1;
let angleIncr = Math.PI / NUM_BODIES;
// draw lines first
for (i; i <= NUM_BODIES; i++) {
let angle = i * angleIncr;
CTX.beginPath();
CTX.moveTo(
CANVAS.width * 0.5 - radius * Math.cos(angle),
CANVAS.height * 0.5 - radius * Math.sin(angle)
);
CTX.lineTo(
CANVAS.width * 0.5 + radius * Math.cos(angle),
CANVAS.height * 0.5 + radius * Math.sin(angle)
);
CTX.closePath()
CTX.stroke();
}
// draw dots on top
for (j; j <= NUM_BODIES; j++) {
let angle = j * angleIncr;
let node = [
CANVAS.width * 0.5 + radius * Math.cos(angle) * Math.sin(delta + angle),
CANVAS.height * 0.5 + radius * Math.sin(angle) * Math.sin(delta + angle)
];
CTX.save();
CTX.fillStyle = `rgb(${j * COLOR_MULT}, 0, ${j * COLOR_MULT})`;
CTX.beginPath();
CTX.arc(node[0], node[1], 10, 0, Math.PI * 2);
CTX.closePath();
CTX.fill();
CTX.restore();
}
}
const update = delta => {
CTX.clearRect(0, 0, CANVAS.width, CANVAS.height);
drawTemplate();
drawMain(delta);
};
const render = delta => {
if (!delta) delta = 0;
delta *= 0.0015;
update(delta);
if (animating) requestAnimationFrame(render);
}
const onResize = () => {
setCanvasSize();
update();
};
const addEventListeners = () => {
window.addEventListener("resize", onResize);
};
const init = () => {
setCanvasSize();
addEventListeners();
document.body.appendChild(CANVAS);
render();
};
init();
body {
background-image: radial-gradient(circle at 50% 50%, #fff 0%, #666 120%);
}
console