Particle systems are fundamental in game development and web visual effects. In this updated guide, you will learn how to create a dynamic particle system using modern JavaScript (ES6+) and the HTML5 <canvas> element.
Particle System Structure
To modernize our code, we will use JavaScript classes. This makes the code more readable, organized, and easy to scale. Here is the complete optimized code:
const canvas = document.getElementById("canvas-club");
const ctx = canvas.getContext("2d");
// Dynamic canvas resizing
let w = canvas.width = window.innerWidth;
let h = canvas.height = window.innerHeight;
const particles = [];
const maxParticles = 100;
const size = 5;
const r = size / 2;
const clearColor = "rgba(0, 0, 0, 0.1)";
const random = (min, max) => Math.random() * (max - min) + min;
class Particle {
constructor() {
this.init();
}
init() {
this.x = random(0, w - size);
this.y = h + random(0, 20);
this.vx = 0;
this.vy = random(-1, -2);
}
draw() {
const hue = (h - this.y) * 0.6;
ctx.fillStyle = `hsla(${hue}, 100%, 50%, 0.8)`;
ctx.beginPath();
ctx.arc(this.x + r, this.y + r, r, 0, 2 * Math.PI);
ctx.fill();
}
update() {
this.x += this.vx;
this.y += this.vy;
this.vx *= 1.15;
// Add random behavior as they rise
if (this.y < h * 0.8 && Math.random() > 0.5) {
this.vx = random(-1, 1);
this.vy -= 0.05;
}
// Reset particle when it leaves the screen
if (this.y + 50 < 0) {
this.init();
}
}
}
function setup() {
for (let i = 0; i < maxParticles; i++) {
setTimeout(() => {
particles.push(new Particle());
}, i * 100);
}
}
function animate() {
// The "trail" trick: we don't clear the canvas completely
ctx.fillStyle = clearColor;
ctx.fillRect(0, 0, w, h);
for (const p of particles) {
p.draw();
p.update();
}
requestAnimationFrame(animate);
}
// Listen for window resize events
window.addEventListener('resize', () => {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
});
setup();
animate();Modern Implementation Analysis
Unlike techniques from 2014, today we leverage language improvements so the browser processes graphics more efficiently.
- Use of Classes (Class): We encapsulate the logic of each particle within a
Particleclass, facilitating the creation of multiple instances with their own position and velocity properties. - Efficient Animation Cycle: We use
requestAnimationFrameinstead ofsetInterval. This synchronizes the animation with the monitor's refresh rate (usually 60fps), saving battery and CPU. - Memory Management: By using
letandconst, we avoid memory leaks and hoisting errors common in older versions of JavaScript.
Key Rendering Concepts
The "Trail" or Tail Effect
One of the most visual effects in this system is the tail left by the particles. This is achieved by painting a semi-transparent rectangle over the entire canvas in each frame:
ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
ctx.fillRect(0, 0, w, h);This doesn't erase previous particles immediately; instead, it "darkens" them progressively, creating a sense of fluid movement.

SEO and Performance Optimization
For a particle system to be production-ready, we must consider Performance.
- Limit the number of particles: Drawing thousands of circles can slow down mobile devices. 100-200 particles are usually enough for impactful visual effects.
- Use of HSLA: The
hsla()color model is ideal for animations because it allows the hue to vary mathematically, creating natural gradients based on the particle's position. - Responsive Design: We have added an
EventListenerfor theresizeevent, ensuring the particle system covers the entire screen even if the user resizes the browser or rotates their device.
If you are interested in diving deeper into visual effects with code, I recommend reading about how to create a glow point with JavaScript and Canvas, which can perfectly complement this particle system.
Conclusion
Creating particles with JavaScript and Canvas is an excellent way to practice programming logic and applied mathematics. With this foundation, you can add gravity, mouse interaction, or even custom textures to take your interfaces to the next level.