All the cool particle animations on the web dazzle people, but the principle is actually very simple.
Get pixel information
First we need to draw an image on the Canvas. In this case, because I am lazy with images (actually I don’t), I will use a jpeg image with white background. It’s actually much better to use PNG transparence.
It is important to wait for the image to load before drawing. You can use the complete property of the image and set the onLoad method to wait for the image to load before initialization. In addition, there are cross-domain restrictions for drawing images. For local viewing, either your image server supports cross-domain or you need to use a local server.
var img = new Image();
img.src = "images.jpeg";
if(img.complete){
init()
} else {
img.onload = function(){
init()
}
}Copy the code
After the image is obtained, we can start to obtain the pixel information of the image. The interface is simple:
Context.getimagedata (x,y, Width, Height) gets the pixel data for the specified rectangle on the canvas.
ctx.drawImage(img, sx, sy);
var imgData = ctx.getImageData(sx, sy, imgW, imgH);Copy the code
Get the pixel data. Don’t make it too easy, okay? ! Since I draw the image in the middle of the canvas, the starting point is not (0,0), and the width and height of the rectangle will be the width and height of the image.
Print it out and see what the data looks like.
The data type is Uint8ClampedArray. It looks like a two-dimensional array with a bunch of numbers in it. The ImageData object is the Uint8ClampedArray.
Fortunately there is documentation:
Uint8ClampedArray
Object is a typed array of 8-bit unsigned integers with values ranging from 0 to 255.- This pile of Numbers represent a rgba values, but each number represents a, such as the first number 0, represent the first pixel value of R, the second number is 0 first G values of pixels, the third fourth 0 respectively represent the first pixel value of B and Alpha value, finally out of the first pixel is a transparent color, The fifth digit represents the R value of the second pixel.
In fact, the image is two-dimensional, with height determining the number of rows and width determining the determinant of the column pixels.
To do particle animation, we first need to particle the picture, to find the position, so that things will not be messy, so we get the position information of each point can be saved.
for(var x=0; x<imgData.width; x+=6) {
for(var y=0; y<imgData.height; y+=6) {
var i = (y*imgData.width + x) * 4;
if(imgData.data[i+3] > 128 && imgData.data[i] < 100) {var dot = new Dot(x, y, 2); dotList.push(dot); }}}Copy the code
Forget the double loop, here are a few quick explanations:
- There’s one in the loop condition
x+=6
.y+=6
Why is this not a 1? Because you’re doing a particle, you need a little bit of space between each point to see it, so you don’t have to take every point, you can just take one point at a distance, and the 6 here is kind of like the idea of sampling. - The inner loop has an if statement,
[i+3]
Alpha refers to the value of Alpha in the pixel, greater than 128 is used to filter out some transparent pixels. Behind theimgData.data[i] < 100
Since I’m using a jpeg file with black text on a white background, I also need to filter out pixels that don’t look black, because most of them are black and white, so I simply decided that the R value is less than 100, so like I said before, IT’s better to use PNG images. - The Dot object is used to store the information of each pixel sampled. Here I only save the information of x and y, and the third parameter is the value of the radius, so I’ll just write 2 here. In fact, I can also consider storing the rGBA information of the pixel and the radius as a random number.
function Dot(centerX, centerY, radius) {
this.x = centerX;
this.y = centerY;
this.radius = radius;
}Copy the code
The final step is to draw the saved information onto the Canvas.
function draw(){
var imgW = img.width,
imgH = img.height,
sx = winWidth/2-imgW/2,
sy = winHeight/2-imgH/2;
ctx.clearRect(0.0, winWidth, winHeight);
ctx.fillStyle = "# 000";
for(var i=0; i<dotList.length; i+=1){
curDot = dotList[i];
ctx.save();
ctx.beginPath();
ctx.arc(sx+curDot.x, sy+curDot.y, curDot.radius, 0.2*Math.PI); ctx.fill(); ctx.restore(); }}Copy the code
The final result:
Particle basically wrote here, the next part will talk about using particle things to do animation, recently more things, lazy cancer again.
Source address: github.com/bob-chen/ca…
Part 2 Address: juejin.cn/post/684490…
Part 3 Address: juejin.cn/post/684490…
reference
www.w3school.com.cn/tags/canvas…
Msdn.microsoft.com/zh-cn/libra…
www.cnblogs.com/axes/p/3500…