preface
After readingH5 live crazy like animation is how to achieve? (Attached with full source code)After this article, I feel that the effect of the thumbs-up is very good, and I also followed the author to achieve this animation effect. The CSS implementation method is easy to understand, but I have different implementation ideas after reading the author’s canvas implementation method, so I implemented it according to my own ideas. The implementation effect is as follows:
Implementation approach
The first thing THAT came to my mind when I saw this animation was to declare an array of small icon objects, and to implement the thumbs-up animation by drawing these small ICONS in different positions. So first we implement a little icon animation.
Animation process decomposition
To do animation, we first decompose the entire animation process, which includes the following:
- There is an enlarged animation when the enlarged image first appears
- Y translation
- X-axis translation is the animation of the icon swinging from side to side
- Transparency animation when the transparency icon disappears
Single icon animation
Let’s first simplify the problem and animate a single icon. Here, for future action on icon animation, I write an Ani class representing icon animation, which contains the icon’s position properties, size, image object and animation track-related properties, as well as a draw method for drawing. The definition is 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 generate the amplitude of the sinusoidal curve
this.step=getRandom(10.60);
// Randomly generate the Y-axis moving speed
this.spite=getRandom(2.6);
// The oscillation frequency of the sine 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;
// The y offset, as the sine function argument
this.dy=0;
}
// The global context is not used here for reuse purposes
draw(context){
// Y panning animation
this.y-=this.spite;
// X-axis swing 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;
// Zoom in 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 vanishing
if(this.y<50) {this.op+=0.05
context.fillStyle = `rgba(255,255,255,The ${this.op}) `;
context.fillRect(x,this.y,this.width,this.height); }}}Copy the code
The getRandom() method is a simple function used to getRandom numbers between intervals. The code implementation is provided in the full source code below.
Here, the transparency of the icon is set by adding transparent background color at the specified position. After searching a lot on the Internet, I failed to find a method to directly modify the transparency of the image object, so I used this method.
The Ani class draw() method changes the ATTRIBUTES of the Ani object, such as y, x, width, height, and op, for each animation process. Here we will focus on the realization of the X-axis swing animation, X-axis motion animation is achieved with the help of sine function, JS has a ready-made math.sin () function for us to use, sine function 0->1->0->-1 curve perfectly fit our need for the motion curve. Here we take the y offset dy as a parameter of the sine function, generate the value dx between 0 and -1, and then use dx*step to obtain the x offset.
Once the Ani class is complete we also 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);
// Render function
function render(){
/ / the context clearRect,0,250,500 (0); // clear canvas
// Add a transparent background color fill to achieve a trailing effect
context.fillStyle = 'rgba (255255255,0.5)';
context.fillRect(0.0.250.500);
ani.draw(context);
window.requestAnimationFrame(render)
}
render();
Copy the code
Multiple icon animation
Once a single icon is animated, it is easy to animate multiple ICONS. We simply create an array that holds multiple icon objects and iterate over them each time the Render function executes.
Since we need multiple image ICONS, we need to implement a loadImge function to cache the loaded image in an imageList array. This method refers to the above article. (Attached with full source code). The code is as follows:
// Load the 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 the 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 the code
Finally we also need a render function:
// Render function
function render(){
/ / the context clearRect,0,250,500 (0); // clear canvas
context.fillStyle = 'rgba (255255255,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((a)= >{
console.log('Image load completed')
render();
setInterval(tapAdd,100);
});
Copy the code
Context. FillStyle = ‘rgba(255,255,255,0.5)’; ,0,250,500 context. FillRect (0); ClearRect (0,0,250,500); clearRect(0,0,250,500); .
Complete source code
<html>
<head>
<title>Cavans praised the animation</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 generate the amplitude of the sinusoidal curve
this.step=getRandom(10.60);
// Randomly generate the Y-axis moving speed
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;
// Enlarge the image animation
if(this.width<50) {this.width+=0.5;
this.height+=0.5;
}
context.drawImage(this.image,x,this.y,this.width,this.height);
// The image disappears and animates from 0-1
if(this.y<50) {this.op+=0.05
context.fillStyle = `rgba(255,255,255,The ${this.op}) `;
context.fillRect(x,this.y,this.width,this.height); }}}// Array of small icon animated objects
let aniList=[];
const canvas = document.getElementById('thumsCanvas');
let imageList=[];
let context = canvas.getContext('2d');
// Load the 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 a random number
function getRandom(min,max){
return Math.floor(Math.random()*(max-min))+min
}
// Add ICONS
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)
}
// Render function
function render(){
/ / the context clearRect,0,250,500 (0); // clear canvas
context.fillStyle = 'rgba (255255255,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((a)= >{
console.log('Image load completed')
render();
setInterval(tapAdd,100);
});
</script>
</html>
Copy the code
The picture material
zan.png
The last
The above is my own reading H5 live crazy like animation is how to achieve? (attached complete source code) in accordance with their own ideas to achieve a live point like effect, thank the author.