Object-Detection-Space / static /js /particles.js
derpiestme's picture
Upload 23 files
8491f89 verified
// Animated dumbbell particles on a Canvas background
(() => {
const canvas = document.getElementById('bg-canvas');
const ctx = canvas.getContext('2d', { alpha: true });
function resize() {
const dpr = window.devicePixelRatio || 1;
canvas.width = Math.floor(innerWidth * dpr);
canvas.height = Math.floor(innerHeight * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
window.addEventListener('resize', resize);
resize();
// Create particles shaped like tiny dumbbells
const NUM = Math.min(70, Math.floor((innerWidth * innerHeight) / 22000));
const particles = Array.from({ length: NUM }, () => spawn());
function spawn() {
const s = 0.5 + Math.random() * 1.2; // scale
return {
x: Math.random() * innerWidth,
y: Math.random() * innerHeight,
vx: -0.4 + Math.random() * 0.8,
vy: -0.4 + Math.random() * 0.8,
rot: Math.random() * Math.PI * 2,
vr: (-0.004 + Math.random() * 0.008),
s,
alpha: 0.15 + Math.random() * 0.35
};
}
function drawDumbbell(x, y, scale, rot, alpha) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(rot);
ctx.scale(scale, scale);
ctx.globalAlpha = alpha;
// bar
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255,255,255,0.35)';
ctx.beginPath();
ctx.moveTo(-16, 0);
ctx.lineTo(16, 0);
ctx.stroke();
// plates
ctx.fillStyle = 'rgba(255,255,255,0.25)';
ctx.beginPath(); ctx.arc(-18, 0, 4, 0, Math.PI*2); ctx.fill();
ctx.beginPath(); ctx.arc(18, 0, 4, 0, Math.PI*2); ctx.fill();
ctx.restore();
}
function tick() {
ctx.clearRect(0, 0, innerWidth, innerHeight);
for (const p of particles) {
p.x += p.vx; p.y += p.vy; p.rot += p.vr;
// wrap-around
if (p.x < -30) p.x = innerWidth + 30;
if (p.x > innerWidth + 30) p.x = -30;
if (p.y < -30) p.y = innerHeight + 30;
if (p.y > innerHeight + 30) p.y = -30;
drawDumbbell(p.x, p.y, p.s, p.rot, p.alpha);
}
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
})();