This article talks about how to use canvas to draw a beautiful rain effect. Let’s take a look at the final effect.
renderings
explainLook at the picture to analyze what effects we need to achieve.
1. Raindrop falling effect, move the mouse to control the falling direction
2. The raindrops fall and scatter into small water droplets. The movement direction of the small water droplets is the same as the movement direction of the mouse.
3. The raindrops fall within a certain range of the mouse coordinates and scatter into small water droplets. Similarly, the movement direction of the small water droplets is the same as the movement direction of the mouse.
Okay, let's roughly split the entire effect into three effects, and achieve these three effects, and we're done.
Let's do it step by step.
1. Raindrop falling effect, move the mouse to control the falling directionThe idea to achieve the entire effect is,
Initial timeUse an array to save raindrop objects.
A raindrop object has various attributes used to represent the raindrop's x coordinate, y coordinate, length, falling speed, color, and a flag to determine whether to delete it.
When updating animationAdd a certain number of raindrop objects to the array, then traverse the array, modify the x-coordinate and y-coordinate of each raindrop object, and use canvas to draw two points based on the coordinates of the raindrop object. When connected, a raindrop is formed.
So the focus of achieving the effect is on the coordinates
When initializing a raindropRaindrop x-coordinate: a random number
Raindrop y coordinate: -100, this is to allow raindrops to come in from outside the visible area
When updating animation Raindrop x coordinate:原x坐标的值+ speed * speedx
speed is a fixed value, indicating the falling speed of raindrops,
speedx is a variable related to the direction of mouse movement, speedx = speedx + (maxspeedx - speedx) / 50
And maxspeedx is a value obtained based on the direction of mouse movement.
maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2)
,
e.clientX: The value of the mouse distance to the left of the visible area
canvasEl.clientWidth: width of the entire visual area
In other words, speedx is a value gradually approaching maxspeedx
The value range of maxspeedx is -1 to 1. The closer its value is to -1, the direction is further to the left. The closer the value is to 1, the direction is further to the right.
Why not just use maxspeedx?
This is to prevent the raindrops from changing direction so quickly. Instead of changing direction immediately following the change of the mouse, there should be a slight delay to make it look better.
If you use maxspeedx, the effect is like this
If you use speedx, the effect is like this
Raindrop y coordinate:原y坐标的值+ speed
Speed is the same as mentioned in the x coordinate above. It is a fixed value that represents the falling speed of raindrops.
Okay, finally, I use canvas to draw two points according to the coordinates of the raindrop object, and then connect them, and the raindrop is drawn.
The first point coordinate is relatively simple. Directly obtain the x coordinate and y coordinate of the raindrop object, which is the coordinate of this point.
Coordinates of the second point:
x坐标= 雨滴x坐标的值+ 雨滴长度* speedx
y坐标= 雨滴y坐标的值+ 雨滴长度
Finally, connect these two points, and there will be a line, which is a raindrop.
When setting the x coordinate, the variable speedx is used again. This is to make the raindrop direction and the raindrop falling direction the same.
When speedx is not used, it is like this
When using speedx, this is the case
2. The raindrops fall and scatter into small water droplets. The movement direction of the small water droplets is the same as the movement direction of the mouse.The idea here is actually somewhat similar to the effect above
Initial timeUse an array to save small water drop objects.
A small drop of water is actually a circular arc.
A small water drop object has various attributes used to represent the coordinates of the small water drop, the x-axis movement speed, the y-axis movement speed, the radius of the circle, and a flag to determine whether to delete it.
When updating animationAdd a certain number of small water drop objects to the array, then traverse the array, modify the x coordinate and y coordinate of each small water drop object, and use canvas to draw an arc based on the coordinate attributes and radius attributes of the small water drop object.
Therefore, the focus of achieving the effect is still on the coordinates
When initializing a small water dropletSmall water droplets appear when the raindrop disappears, so the coordinates of the small water droplet are also based on the coordinates of the raindrop. If you delete a raindrop, some small water droplets will appear, and the moving direction of the small water droplet is also the direction of the raindrop falling. Mouse The movement direction is the same, so the variable speedx mentioned above will still be needed.
小水珠x坐标: 删除的雨滴x坐标+ 删除的雨滴长度* speedx
小水珠y坐标:删除的雨滴y坐标+ 删除的雨滴长度
Here we need to use two attributes of the small water drop object vx (the speed of change of the value of the x-axis) and vy (the speed of change of the value of the y-axis).
The x-coordinate of the small water droplet
vx = vx + speedx / 2
小水珠的x坐标=原x坐标+ vx
,
speedx: a variable related to the mouse movement direction mentioned above. The function here is to control the movement direction of the small water droplets in the same direction as other directions.
speedx / 2
, the purpose of dividing by 2 is to make the moving distance of the small water droplets on the x-axis shorter and look more realistic.
The y coordinate of the small water drop
vy = vy + gravity
小水珠的y坐标= 原y坐标+ vy;
,
vy: a negative number
Gravity: Gravity, a positive number, set to 0.5 in the complete code
Because the original y coordinate is a positive number, the value of the y coordinate of the small water droplet will first decrease and then increase. This is to achieve the effect that the small water droplet will first rise and then fall. See the picture
Finally, just use canvas to draw an arc based on the coordinate attributes and radius attributes of the small water droplets. The arc is random.
3. The raindrops fall within a certain range of the mouse coordinates and scatter into small water droplets. Similarly, the movement direction of the small water droplets is the same as the movement direction of the mouse.
It is easy to determine the size of the circle in the picture. Assume that the radius of the circle is 35. We can get the coordinates of the mouse. Taking the coordinates of the mouse as the center of the circle and 35 as the radius, we can determine the size of the circle.
The key point is how to judge whether the raindrops have entered this range. This requires the use of the Pythagorean Theorem. Look at the picture.
Because a raindrop is a line connecting two points. To see whether the raindrop has entered this range, you need to look at the coordinates of the point below the raindrop. What is the straight-line distance from the mouse is the length of line segment AB in the picture.
Pythagorean Theorem: The sum of the squares of the two right-angled sides of a right triangle is equal to the square of the hypotenuse.
AB = Math.sqrt(BC BC + AC AC)
BC = raindrop x-coordinate - mouse x-coordinate
AC = raindrop y coordinate - mouse y coordinate
Math.sqrt() method is used to calculate the square root of a number
After we know the straight-line distance from the raindrop to the mouse, compare it with the radius of the circle. If it is greater than the radius, it is not within the range, otherwise it is.
If it's within range, delete the raindrops and draw some small water drops.
Summarize
To achieve this effect, the trouble lies in the direction, the direction of raindrops, the direction of raindrops falling, and the direction of movement of small water droplets. These are all related to the direction of mouse movement. After determining the various directions, use canvas to continuously draw lines based on the distance. An arc will do.
Complete code
<!doctype html><html lang=en><head> <meta charset=UTF-8> <style> * { margin: 0; padding: 0; } </style></head><body> <canvas id =canvas style=position: absolute; height: 100%; width:100%;></canvas> <script> window.onload = main; function main() { // Get the canvas element var canvasEl = document.getElementById('canvas'); var ctx = canvasEl.getContext('2d'); // The background color of the canvas canvas var backgroundColor = '#000'; // The width of the canvas canvas is equal to the width of the visual area canvasEl. width = canvasEl.clientWidth; // The height of the canvas canvas is equal to the height of the visible area canvasEl.height = canvasEl.clientHeight; // Array to save small water drops // After the raindrops fall, they scatter into small water droplets. The small water droplets are arcs. var dropList = []; // Gravity // After the raindrops fall, they scatter into small water droplets. The small water droplets will first rise and then fall, mainly because of gravity. Because of variables var gravity = 0.5; // Save the array of raindrops // Each raindrop is a line drawn var linelist = []; // Save the coordinates of the mouse // mousePos[0] Represents the value of the x-axis, mousePos[1] represents the value of the y-axis var mousePos = [0, 0]; // Following the mouse, the raindrops in the mouseDis size area will disappear, forming a scattering effect // With mousePos as the center of the circle, mouseDis is Radius, the raindrops within this range will spread out and form many small water droplets var mouseDis = 35; // Update the animation once and draw lineNum raindrops. The larger the lineNum value, the denser the rain will be. var lineNum = 3; // Follow the direction of the mouse to change the speed of the rain direction // After the mouse moves, the direction of the rain will slowly change, mainly depending on the variable speedx var speedx = 0; // maxspeedx is the maximum value that speedx can take // When speedx = maxspeedx, the direction of rain will change immediately with the direction of mouse movement var maxspeedx = 0; // When the page size changes, reset the canvas size window.onresize = function () { canvasEl.width = canvasEl.clientWidth; canvasEl.height = canvasEl.clientHeight; } //Move the mouse to trigger the event window.onmousemove = function (e) { //Set mousePos equal to the mouse coordinates // e.clientX is the distance to the left of the visible area of the browser window Distance // e.clientY is the distance from the top of the visible area of the browser window mousePos[0] = e.clientX; mousePos[1] = e.clientY; // Set the value of maxspeedx through the mouse position, the value range is -1 to 1 // The value of maxspeedx is related to // 1. The direction of the raindrops // 2. The direction of the raindrops // 3. The speed at which the falling direction of raindrops changes with the direction of mouse movement // 4. The movement direction of small water droplets // The closer the value is to 1, the direction is further to the right // The closer the value is to -1, the direction is further to the left maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2); } // According to the parameters, return an rgb color, used to set the color of raindrops function getRgb(r, g, b) { return rgb( + r + , + g + , + b + ); } // Draw a raindrop (a line) function createLine(e) { // Randomly generate the length of the raindrop var temp = 0.25 * (50 + Math.random() * 100); // A line object, representing a raindrop var line = { // Raindrop falling speed speed: 5.5 * (Math.random() * 6 + 3), / / Determine whether to delete, delete if the value is true die: false, // Raindrop x coordinate posx: e, // Raindrop y coordinate posy: -50, // Raindrop length h: temp, // Color of raindrops color: getRgb(Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75)) }; // Create Good line (raindrop) object, added to the array holding raindrops linelist.push(line); } // Draw a small water drop (the small water droplets after the raindrops disperse are arcs) function createDrop(x, y) { // A drop object, representing an arc var drop = { // Determine whether to delete, value If true, delete die: false, // The x coordinate of the arc center posx: x, // The y coordinate of the arc center posy: y, // vx represents the speed at which the x-axis value changes vx: (Math.random( ) - 0.5) * 8, // vy represents the speed range of the change of the y-axis value: -3 to -9 vy: Math.random() * (-6) - 3, // The radius of the arc radius: Math. random() * 1.5 + 1 }; return drop; } // Draw a certain number of small water drops function madedrops(x, y) { // Randomly generate a number maxi // maxi Represents the number of small water drops to be drawn var maxi = Math.floor(Math.random() * 5 + 5); for (var i = 0; i < maxi; i++) { dropList.push(createDrop(x, y) ); } } // Start calling the update function to update the animation window.requestAnimationFrame(update); // Update the animation function update() { // If the array holding the small water drops has content if (dropList.length > 0) { // Traverse the array that holds small water drops dropList.forEach(function (e) { //Set e.vx, vx represents the speed of x coordinate change // (speedx)/2 is for, Make the moving distance of the small water droplets on the x-axis shorter and look more realistic // Also make the moving direction of the small water droplets the same as the direction of the raindrops, the falling direction of the raindrops, and the moving direction of the mouse e.vx = e.vx + (speedx / 2); e.posx = e.posx + e.vx; //Set e.vy, vy represents the speed of change of y coordinate // The range of e.vy is -3 to -9, and at this time e.posy ( y coordinate) must be a positive value, so the value of e.posy will first decrease and then increase // that is, the raindrops will disperse into small water droplets, and the small water droplets will first rise and then fall. e.vy = e.vy + gravity; e.posy = e.posy + e.vy; // If the y coordinate of the small water drop is greater than the height of the visible area, set the die attribute to true // If the small water drop exceeds the visible area, delete it if (e.posy > canvasEl.clientHeight) { e .die = true; } }); } // Delete the array member whose die attribute is true // Delete the small water drops outside the visible area for (var i = dropList.length - 1; i >= 0; i- -) { if (dropList[i].die) { dropList.splice(i, 1); } } // Set the speed of rain direction change, value range: -1 to 1 // When speedx = maxspeedx, the rain direction will Change the direction of mouse movement immediately speedx = speedx + (maxspeedx - speedx) / 50; // Draw a certain number of raindrops according to the value of lineNum for (var i = 0; i < lineNum; i++) { // Call the createLine function, the parameter is the x-coordinate of the raindrop createLine(Math.random() * 2 * canvasEl.width - (0.5 * canvasEl.width)); } // Set the end line, that is, the raindrops spread out to form many small water droplets. Position var endLine = canvasEl.clientHeight - Math.random() * canvasEl.clientHeight / 5; // Traverse the array holding raindrops linelist.forEach(function (e) { // Use the Pythagorean theorem to determine a range within which the raindrops will spread out to form small water droplets // e.posx + speedx * eh is the x coordinate of the raindrop/ / e.posy + eh is the y coordinate of the raindrop var dis = Math.sqrt(((e.posx + speedx * eh) - mousePos[0]) * ((e.posx + speedx * eh) - mousePos[0]) + (e.posy + eh - mousePos[1]) * (e.posy + eh - mousePos[1])); // If it is in the mouseDis area, delete the raindrop and draw it Some small water drops (arcs) // Realize the effect of the mouse touching the raindrops and the raindrops scattering into small water droplets if (dis < mouseDis) { // Delete the raindrops e.die = true; // Draw some small water droplets (circles) arc) madedrops(e.posx + speedx * eh, e.posy + eh); } // If the raindrops exceed the end line, delete the raindrops and draw some small water drops (arcs) if ((e.posy + eh) > endLine) { e.die = true; madedrops(e.posx + speedx * eh, e.posy + eh); } // If the y-coordinate of the raindrop is greater than the height of the visible area, set the die attribute to true // If the raindrop exceeds the visible area, delete it if (e.posy >= canvasEl.clientHeight) { e.die = true; } else { // Gradually increase the value of the y coordinate of the raindrop e.posy = e.posy + e.speed ; // Change the x coordinate of the raindrop // * speedx is used to control the falling direction of the raindrop // Make the falling direction of the raindrop the same as the mouse movement direction e.posx = e.posx + e.speed * speedx; } }); // Delete the array members whose die attribute is true // Delete the raindrops in the mouse area, beyond the end line, and outside the visible area for (var i = linelist.length - 1; i >= 0; i--) { if (linelist[i].die) { linelist.splice(i, 1); } } // Render render(); // Recursively call update to achieve animation effect window.requestAnimationFrame(update); } // Rendering function render() { // Draw a rectangle as large as the visible area ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0, canvasEl.width, canvasEl.height); // Draw a raindrop effect ctx. lineWidth = 5; linelist.forEach(function (line) { ctx.strokeStyle = line.color; ctx.beginPath(); ctx.moveTo(line.posx, line.posy); // * speedx is used to control the direction of raindrops // Make the direction of raindrops the same as the direction of mouse movement ctx.lineTo(line.posx + line.h * speedx, line.posy + line.h); ctx.stroke(); }); // Draw raindrops that spread out to form small water droplets. ctx.lineWidth = 1; ctx.strokeStyle = #fff; dropList.forEach(function (e) { ctx.beginPath(); ctx.arc(e.posx, e.posy, e.radius, Math.random() * Math.PI * 2, 1 * Math.PI); ctx.stroke(); }); // Uncomment and you can see the mouse range/* ctx.beginPath(); ctx.arc(mousePos[0], mousePos[1], mouseDis, 0, 2 * Math.PI); ctx.stroke(); */ } } </script></body></html>
The above is the entire content of this article. I hope it will be helpful to everyone’s study. I also hope everyone will support VeVb Wulin Network.