Intro
One of the things I love the most about the HTML5 canvas are particle systems. For this post I prepared a small but good looking example. One of the colleagues from work even thought that I used some kind of graphical framework to do this and couldn't believe it's just plain old javascript.
The Particle definition
var Particle = function (ind) { // remember the index inside array // faster performance on collisions this.ind = ind; // initial position this.x = randomMax(canvas.width); this.y = randomMax(canvas.height); // random direction vectors this.dy = -5 + randomMax(10); this.dx = -5 + randomMax(10); // radius (small flash in the beginning) this.r = randomMax(radiusmax); // give it a random color from the set this.color = colorSet[Math.floor(Math.random() * colorSet.length)]; };
Particle draw method
// reduce the size of the particle down to the minimal size // using log function - looks nicer and more organic this.r = this.r > miParticleSize ? flashfactor * (Math.log(this.r) / Math.LN10) : miParticleSize; // adjust particle position this.y += this.dy; this.x += this.dx; // check for collision with other particles // only on same color for (var i = this.ind + 1; i < particleSystem.particles.length; i++) { if (distance(this, particleSystem.particles[i]) < criticalDistance && this.color === particleSystem.particles[i].color) { this.r = radiusmax; particleSystem.particles[i].r = radiusmax; } } // if the particle is outside of the canvas // or moving vectors are both 0 if (this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height || (this.dy === 0 && this.dx === 0)) { // initialize the particle again this.x = randomMax(canvas.width); this.y = randomMax(canvas.height); this.dy = -5 + randomMax(10); this.dx = -5 + randomMax(10); } ctx.beginPath(); // this is the part that makes people thing it's a framework // simple radial gradient fillStyle = ctx.createRadialGradient(this.x, this.y, this.r * 0.001, this.x, this.y, this.r ); fillStyle.addColorStop(0, this.color); fillStyle.addColorStop(1, particleBackground); // particle drawing code ctx.fillStyle = fillStyle; ctx.beginPath(); ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2); ctx.fill();
Other than helper function and standard shims that's all there is to it.
Firefox issues
I couldn't find why firefox deals so bad with a larger number of particles, essentially everything freezes past 100 particles on firefox. Initialy I thought it's my draw method, but turned out that there's not much to be improved there.
Even when I removed the draw code and let the firefox "draw" the objects with an empty method the performace was still very poor (around 5-6 fps). If you perhaps figured it out or know about some issues please let me know!
And here's my example on:Codepen