Preface
Reading How does the H5 live mad compliment animation work?(with full source code) This article feels like it's a good point to follow and animate.The implementation of css is easy to understand, but I have different ideas after reading the author's implementation of canvas, so I implemented it according to my own ideas.The results are as follows:
Ideas for implementation
The first thing I think about when I see this animation effect is to declare an array of small icon objects that you can do by drawing them in different places.So first we'll animate a small icon.
Animation process decomposition
To make an animation, we first break down the entire animation process. This animation contains the following:
- enlarge
There was an enlarged animation just after the picture appeared
- y-axis translation
- x-axis translation
That is, the animation in which the icon swings left and right
- transparency
Transparency animation when icon disappears
Single icon animation
Let's start by simplifying the problem and animating a single icon.Here, for later operations on icon animation, I wrote an Ani class representing icon animation, which contains the location properties, size, image object and animation track related properties of the icon, as well as a drawing method to draw it.Define as follows:
//Icon Animation Class class Ani{ constructor(img,x,y,w,h){ this.x=x; this.y=y; this.width=w; this.height=h; this.image=img; //Randomly generated sinusoidal wave amplitude this.step=getRandom(10,60); //The moving speed of the randomly generated y-axis this.spite=getRandom(2,6); //Oscillating frequency of sinusoidal function this.frequency=getRandom(50,100); //Small Icon Transparency this.op=0; //Random Curve Type Math.random()>=0.5?this.type=1:this.type=2; //y-axis offset as a parameter of sine function this.dy=0; } //Global context s are not used here to facilitate reuse draw(context){ //y-axis translation drawing this.y-=this.spite; //x-axis pendulum animation this.dy+=this.spite; let dx=0; //Different wave directions this.type==1?dx=Math.sin(this.dy/this.frequency):dx=Math.sin(-this.dy/this.frequency); let x=this.x+dx*this.step; //Enlarge Animation if(this.width<50){ this.width+=0.5; this.height+=0.5; } context.drawImage(this.image,x,this.y,this.width,this.height); //Transparency animation when disappearing if(this.y<50){ this.op+=0.05 context.fillStyle = `rgba(255,255,255,${this.op})`; context.fillRect(x,this.y,this.width,this.height); } } } Copy Code
To explain the above code a little, the frequency attribute in the constructor is used to control the swing frequency of the sine function. You can modify its value to see the effect. The getRandom() method is used to get the random numbers between intervals. The source code of the line surface is given.
The transparency of the icon is achieved by adding a transparent background color to the specified location. You have searched many websites and have not found a way to directly modify the transparency of the image object, so you use this method.
The Ani class draw() method implements each animation process by changing the y, x, width, height, op and other properties of the Ani object.Here we will focus on the implementation of the swing animation of the x-axis. The motion animation of the x-axis is achieved by means of sine function. js has ready-made Math.sin() function for us to use. The 0->1->0->-1 curve of the sine function perfectly matches the motion curve we need.Here we take the y-axis offset dy as a parameter of the sine function, generate the value DX between 0 and 1, and use dx*step to get the x-axis offset.
After the Ani class is finished, we still need a function to start the animation:
const canvas = document.getElementById('thumsCanvas'); let context = canvas.getContext('2d'); let image=new Image("./img/star.png"); let ani=new Ani(image,250/2-50/2,500-50,20,20); //renderer function render(){ //context.clearRect(0,0,250,500); // clear canvas //Add transparent background color fill for trailing effect context.fillStyle = 'rgba(255,255,255,0.5)'; context.fillRect(0,0,250,500); ani.draw(context); window.requestAnimationFrame(render) } render(); Copy Code
Multiple icon animation
If you have animated a single icon, it is easy to animate multiple icons.We just need to create an array that holds multiple icon objects and traverse to draw them each time the render function executes.
Since we need icon objects for more than one image, we need to implement a loadImage function to cache the image to be loaded into an imageList array, which refers to the above article How does the H5 live mad compliment animation work?(with full source code) .The code is as follows:
//Load Image function loadImage(){ const images=[ '../img/red.png', '../img/dog.png', '../img/cat.png', '../img/star.png', '../img/zan.png', ]; const promiseList=[]; images.forEach(element => { let p=new Promise((resolve)=>{ const img=new Image(); img.onload=resolve.bind(null,img) img.src=element; }) promiseList.push(p) }); return new Promise(resolve=>{ Promise.all(promiseList).then(imgs=>{ this.imageList=imgs; resolve(); }) }) } Copy Code
Then we need to add a method to the icon object:
//Add Icon Object to Array function tapAdd(){ let image=this.imageList[this.getRandom(0,5)]; let ani=new Ani(image,250/2-50/2,500-50,20,20) aniList.push(ani) } Copy Code
Finally, we also need a rendering function:
//renderer function render(){ //context.clearRect(0,0,250,500); // clear canvas context.fillStyle = 'rgba(255,255,255,0.5)'; context.fillRect(0,0,250,500); aniList.forEach((ani,index)=>{ if(ani.y<-50){ ani=null; }else{ ani.draw(context); } }) window.requestAnimationFrame(render) } loadImage().then(()=>{ console.log('Image Loading Completed') render(); setInterval(tapAdd,100); }); Copy Code
The two sentences context.fillStyle ='rgba (255,255,255,0.5)'; context.fillRect (0,0,250,500); are used to achieve a tailing effect by adding a translucent fill color, which can be directly replaced by context.clearRect(0,0,250,500) if not needed;
Full Source:
<!DOCTYPE html> <html> <head> <title>cavans Praise animation effect</title> </head> <body> <canvas onclick="tapAdd()" id="thumsCanvas" width="250" height="500" style="width:250px;height:500px;background-color: #f4f4f4;"></canvas> </body> <script> //Icon Animation Class class Ani{ constructor(img,x,y,w,h){ this.x=x; this.y=y; this.width=w; this.height=h; this.image=img; //Randomly generated sinusoidal wave amplitude this.step=getRandom(10,60); //The moving speed of the randomly generated y-axis this.spite=getRandom(2,6); this.frequency=getRandom(50,100); //Small Icon Transparency this.op=0; //Random Curve Type Math.random()>=0.5?this.type=1:this.type=2; this.dy=0; } draw(context){ //y-axis animation effect this.y-=this.spite; //x-axis animation effect this.dy+=this.spite; let dx=0; //Different wave directions this.type==1?dx=Math.sin(this.dy/this.frequency):dx=Math.sin(-this.dy/this.frequency); let x=this.x+dx*this.step; //Image Enlargement Animation if(this.width<50){ this.width+=0.5; this.height+=0.5; } context.drawImage(this.image,x,this.y,this.width,this.height); //Image vanishing animation, transparency from 0-1 if(this.y<50){ this.op+=0.05 context.fillStyle = `rgba(255,255,255,${this.op})`; context.fillRect(x,this.y,this.width,this.height); } } } //Array of small icon animation objects let aniList=[]; const canvas = document.getElementById('thumsCanvas'); let imageList=[]; let context = canvas.getContext('2d'); //Load Image function loadImage(){ const images=[ '../img/red.png', '../img/dog.png', '../img/cat.png', '../img/start.png', '../img/zan1.png', ]; const promiseList=[]; images.forEach(element => { let p=new Promise((resolve)=>{ const img=new Image(); img.onload=resolve.bind(null,img) img.src=element; }) promiseList.push(p) }); return new Promise(resolve=>{ Promise.all(promiseList).then(imgs=>{ this.imageList=imgs; resolve(); }) }) } //Get Random Numbers function getRandom(min,max){ return Math.floor(Math.random()*(max-min))+min } //Add Icon function tapAdd(){ let image=this.imageList[this.getRandom(0,5)]; let ani=new Ani(image,250/2-50/2,500-50,20,20) aniList.push(ani) } //renderer function render(){ //context.clearRect(0,0,250,500); // clear canvas context.fillStyle = 'rgba(255,255,255,0.5)'; context.fillRect(0,0,250,500); aniList.forEach((ani,index)=>{ if(ani.y<-50){ ani=null; }else{ ani.draw(context); } }) window.requestAnimationFrame(render) } loadImage().then(()=>{ console.log('Image Loading Completed') render(); setInterval(tapAdd,100); }); </script> </html> Copy Code
Picture material
zan.png
cat.png dog.png heart.png star.pngLast
That's what I'm reading. How does the H5 live mad compliment animation work?(with full source code) After that, I realized a live point of praise effect according to my own ideas, and expressed my thanks to the author.
If there are good suggestions for modification, you are welcome to make them, and if you feel OK, you are welcome to give them a compliment.