Skip to content

Instantly share code, notes, and snippets.

@goldenratio
Created September 7, 2025 20:59
Show Gist options
  • Select an option

  • Save goldenratio/49d2653a80323387e54f72e9465df4d3 to your computer and use it in GitHub Desktop.

Select an option

Save goldenratio/49d2653a80323387e54f72e9465df4d3 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Particle System</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #1a1a1a;
color: #fff;
font-family: 'Inter', sans-serif;
}
canvas {
display: block;
background: #000;
}
.info {
position: fixed;
top: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 8px;
font-size: 14px;
}
</style>
</head>
<body>
<div class="info">
<p>Particles: <span id="particleCount">0</span></p>
<p>Click and hold to generate more particles.</p>
</div>
<canvas id="particleCanvas"></canvas>
<script>
const canvas = document.getElementById('particleCanvas');
const ctx = canvas.getContext('2d');
const particleCountElement = document.getElementById('particleCount');
let particles = [];
let mouse = { x: null, y: null, isDown: false };
let hue = 0;
// Set canvas size to full window
function setCanvasSize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
setCanvasSize();
// Event listeners for window and mouse
window.addEventListener('resize', setCanvasSize);
window.addEventListener('mousemove', (event) => {
mouse.x = event.x;
mouse.y = event.y;
});
window.addEventListener('mousedown', () => {
mouse.isDown = true;
});
window.addEventListener('mouseup', () => {
mouse.isDown = false;
});
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = Math.random() * 5 + 1;
this.speedX = Math.random() * 3 - 1.5;
this.speedY = Math.random() * 3 - 1.5;
this.color = `hsl(${hue}, 100%, 50%)`;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
if (this.size > 0.2) this.size -= 0.1;
}
draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}
function handleParticles() {
for (let i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].draw();
// Remove particles that are too small
if (particles[i].size <= 0.2) {
particles.splice(i, 1);
i--;
}
}
}
function createParticles(count, x, y) {
for (let i = 0; i < count; i++) {
particles.push(new Particle(x, y));
}
}
function animate() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
handleParticles();
if (mouse.isDown) {
createParticles(2, mouse.x, mouse.y);
hue = (hue + 1) % 360;
}
particleCountElement.textContent = particles.length;
requestAnimationFrame(animate);
}
// Initial particle creation
createParticles(100, canvas.width / 2, canvas.height / 2);
window.onload = function() {
animate();
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment