JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
HTML
<canvas id="canvas"></canvas>
CSS
#canvas {
border: 1px solid black;
}
JavaScript
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 400;
let particles = [];
for (let i = 0; i < 10; i++) {
particles.push({
x: Math.random() * 400,
y: Math.random() * 400,
xv: (Math.random() - 0.5) * 4,
yv: (Math.random() - 0.5) * 4
});
}
function tick() {
requestAnimationFrame(tick);
ctx.clearRect(0, 0, 400, 400);
for (const particle of particles) {
const { x, y, xv, yv } = particle;
ctx.beginPath();
ctx.arc(x, y, 4, 0, 2 * Math.PI);
ctx.fill();
}
particles = particles.map(particle => {
const newParticle = { ...particle };
newParticle.x += particle.xv;
newParticle.y += particle.yv;
const speed = Math.hypot(particle.xv, particle.yv);
const angle = Math.atan2(particle.yv, particle.xv);
pushParticle(newParticle, angle, -0.0001 * speed ** 3);
pushParticle(
newParticle,
Math.atan2(particle.y - 200, particle.x - 200) + Math.PI,
100 / Math.hypot(particle.x - 200, particle.y - 200)
);
for (const p of particles) {
pushParticle(
newParticle,
Math.atan2(particle.y - p.y, particle.x - p.x),
-1 / (1.8 * particles.length) * Math.hypot(particle.x - p.x, particle.y - p.y)
);
}
return newParticle;
});
}
function pushParticle(particle, angle, a) {
particle.xv += a * Math.cos(angle);
particle.yv += a * Math.sin(angle);
}
tick();