How to build particle effects with Canvas

When you design a Canvas game, in most cases, you can finish it well without particle effects. However, it's not perfect. When you really want to achieve something, just make it perfect and flawlessness! Some effects are cherubic and amazing, why not use them to improve user experience? Particle effect is one of them. And it is also the most powerful function of Canvas which is totally different from "SVG" and CSS animation. The former is pixel level, and the latter is block level. Ok, it's easy, don't wait, let's begin!

1. Put picture on the canvas

In order to let the canvas fill the entire screen, we should use JS to help us, because if using CSS, the width and height of canvas will be scaled down. And another thing to remind is when using "drawImage" function to put picture on the canvas, we should wait some time until the picture has been loaded. So the "drawImage" function should be written in the "image.onload()" or "window.onload()", both work.
var totalwidth = window.innerWidth; var totalheight = window.innerHeight; var canvas = "<canvas id='thecanvas' width='"+totalwidth+"px' height='"+totalheight+"px'></canvas>"; document.body.insertAdjacentHTML("beforeEnd", canvas); var thecanvas = document.querySelector("#thecanvas"); var context = thecanvas.getContext("2d"); var nyuimg = new Image(); nyuimg.src = "img/nyu.jpg"; nyuimg.onload = function(){ // you can also write here } window.addEventListener("load", canvasApp, false); function canvasApp(){ context.drawImage(nyuimg, totalwidth*0.5-100, totalheight*0.5-100, 200, 200); }
Let's see the effect, we can see that we put the "nyu" picture on the canvas.

2. "getImageData"

Before discussing the parameters, I want to remind you a detail, when we want to use both "getImageData" and "drawImage" at the same time, our browsers will warn because it does not seem safe for its different domain. So how to solve it? We have to put this case into our online server. You can put it on the github or your own server, anyway, you should let them in the same domain from the browsers' view. Ok, come back. The "getImageData" function has three attributes: width, height and data. The "data" attribute is an Uint8ClampedArray type array. It contains all the color information as follows. (The picture is provided by Jobbole. )
Every pixel will have four values in array(R, G, B, A). And the array's length is (data.width * data.height * 4). (The picture is provided by Jobbole. )
So if we want to find a certain color of pixel, we can use the following method: R = [(j-1)*data.width + (i-1)]*4 G = [(j-1)*data.width + (i-1)]*4 + 1 B = [(j-1)*data.width + (i-1)]*4 + 2 A = [(j-1)*data.width + (i-1)]*4 + 3

3. Get the right pixels

So now we can get the pixels we want by comparing RGBA. In this code, in order to show the particle effect, you should use "Math.random()" method to change pixel position randomly to leave them apart. What's more, if you want to keep the color of pixels, you should use a variable, and the color should record by using "rgb()" or "rgba()", but don't use "#" plus numbers since it cannot get the right color. (Little trick)
var imgdata = null, particles = []; function canvasApp(){ // ... var cols = 200, rows = 200, pos = 0, data = imgdata.data; for (var i = 0; i < cols; i++){ for (var j = 0; j < rows; j++){ var pos = [(j - 1)*imgdata.width + (i - 1)]*4; if (data[pos] > 50){ var particle = { x : totalwidth*0.5-100 + i + (Math.random()-0.5)*20, y : totalheight*0.5-100 + j + (Math.random()-0.5)*20, fillStyle : "rgb("+data[pos]+","+data[pos+1]+","+data[pos+2]+")" } particles.push(particle); } } } }

4. Draw particles

The final thing is to draw pixels.
context.clearRect(0, 0, totalwidth, totalheight); for (i = 0; i < particles.length; i++){ context.fillStyle = particles[i].fillStyle; context.fillRect(particles[i].x, particles[i].y, 1, 1); }
Ok, let's see the final particle effect. Actually, we can also use the pixels to do some amazing effects, such as particle trajectory, particle collision and so on. Just use some math formulas or Bezier curves.
(That's all)