This year Hangzhou has started to hold a fireworks conference again, and the fireworks are really beautiful. If you don’t have the opportunity to watch it live, as a front end, you can implement a fireworks page by yourself.
Come with me and learn this fireworks code to waste.
Function split
Common fireworks are sent upwards from one place, and when they reach a certain height, they explode into a circle of light spots. The height is different, the size of the circle is different, and the color of the light spot is also different.
Therefore, the process of a firework can be divided into 2 steps: 1. Rising from a certain position P0 to P1; 2. Exploding from P1 into a circle of light spots, the light spots spread outward, and the light spots spread to a certain extent, and then gradually disappeared.
write code step by step
For this firework, we need to use canvas to draw, so we need to make the canvas first:
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); // clear canvas function clearCanvas() { ctx.fillStyle = '#000000'; ctx.fillRect(0, 0, canvas.width, canvas.height); } clearCanvas();
fireworks lift off
First set the basic information of the fireworks, including the size of the fireworks particles and the position where the fireworks start to be released.
const size = 2; // The size of the fireworks particles const start = { x: canvas.width / 2, y: canvas.height - 100, };
Then make a mouse click event, and when the canvas is clicked, the fireworks will start playing (fire method). In the fire method, the position of the current fireworks particles is constantly updated to form an upward effect of fireworks.
let rid = 0; function fire() { const p = {x: start.x, y: start.y} function tick() { clearCanvas(); step1(p); rid = requestAnimationFrame(tick); } cancelAnimationFrame(rid); tick() } // Fireworks first step, take off function step1(p) { p.y = p.y - 4; // Change particle position every frame ctx.beginPath(); ctx.arc(p.x, p.y, size, 0, Math.PI*2, false) ctx.closePath(); ctx.fillStyle = "#ffffff"; ctx.fill(); } function mouseDownHandler(e) { fire(); } document.addEventListener('mousedown', mouseDownHandler, false);
When the firework is rising, the speed will become slower and slower. When it reaches a certain height, the rising speed will reach 0 and enter the second stage. So the change of p.y needs to be changed to change, and then add a control to enter the second state.
function tick() { clearCanvas(); // Control phase according to state if (p.state === 1) { step1(p); } else if(p.state === 2) { step2(p); } } function step1(p) { if (p.upSpeed < 0.1) { // When the speed is very low, enter the second stage p.state = 2; return; } p.upSpeed = p.upSpeed - 0.05; // The speed change is gradually reduced p.y = p.y - p.upSpeed; ... }
fireworks explode
After entering the second stage, you need to explode a bunch of particles that spread around. We first make a circle of particles, and then add animation and particles.
let radius = 10; // Particle Surrounding Radius function step2(p) { const count = 10; // 10 particles radius++ // The radius keeps growing, forming an animation for (var i = 0; i < count; i++) { var angle = 360/count * i; let radians = angle * Math.PI / 180; let vx = Math.cos(radians) * radius; let vy = Math.sin(radians) * radius; ctx.beginPath(); ctx.arc(p.x - 5 + vx, p.y - 5 + vy, size, 0, Math.PI * 2, false); ctx.closePath(); ctx.fillStyle = '#ffffff'; ctx.fill(); } }
Then now we want to increase the number of particles, just change the count here, each particle is not evenly distributed, so the angle and radius should be random. There is a step2 that will be re-run every time it is refreshed, so the production of particles needs a separate method, otherwise every time it is refreshed, the particles will be randomly generated again, so the particles will fly randomly.
// Retrofit method to bring the creation of fireworks together. Spending multiple fireworks at the same time var fireworks = []; function createFireworks(p) { const firework = { x: start.x, y: start.y, upSpeed: 12, state: 1, particles: [], // Particles after explosion }; var count = Math.floor(Math.random() * 100) + 80; for (var i = 0; i < count; i++) { var p = {vx:0, vy:0}; // For each particle, vx,vy represent the offset relative to the inflation position var angle = Math.floor(Math.random() * 360); p.radians = angle * Math.PI / 180; p.speed = (Math.random() * 5) + .4; p.radius = p.speed; p.size = Math.floor(Math.random() * 3) + 1; firework.particles.push(p); } } function step2(f) { const particles = f.particles; for (let i = 0, len = particles.length; i < len; i++) { const p = particles[i]; let vx = Math.cos(p.radians) * p.radius; let vy = Math.sin(p.radians) * p.radius + 0.4; p.vx += vx; p.vy += vy; p.radius *= 1 - p.speed / 100; // gradually slow down ctx.beginPath(); ctx.arc(f.x - 5 + p.vx, f.y - 5 + p.vy, size, 0, Math.PI * 2, false); ctx.closePath(); ctx.fillStyle = '#ffffff'; ctx.fill(); } }
At this point, the basic appearance of the fireworks is OK. After a period of time, the fireworks need to disappear, and different styles are used to distinguish the fireworks. It is best to have different angles and starting positions. different.
Fireworks are different in color and disappear
The disappearance of fireworks is relatively simple, just make a transparency for each particle, the transparency gradually becomes smaller, and finally disappears. For the color, it can be done randomly through hsla.
function createFireworks() { const firework = {...}; let count = Math.floor(Math.random() * 100) + 80; let hue = Math.floor(Math.random() * 6) * 60; // Divided into 6 main colors for (let i = 0; i < count; i++) { ... p.hue = Math.floor(Math.random() * 30) + hue; // A slight variation on each main color p.brightness = Math.floor(Math.random() * 30) + 70; p.alpha = (Math.floor(Math.random() * 61) + 40) / 100; ... } } function step2(f) { for (let i = 0, len = particles.length; i < len; i++) { ... p.alpha -= 0.005; // disappear slowly ... ctx.fillStyle = 'hsla(' + p.hue + ', 100%, ' + p.brightness + '%, ' + p.alpha + ')'; // hsla color } }
The starting position and launch angle of fireworks are random
The last thing is to make the firing position and firing angle of the fireworks random.
function createFireworks() { const firework = { x: start.x + Math.floor(Math.random() * 100) - 50, // random position on x ... }; ... } function step1(p) { ... p.x = p.x + p.xAngle; // During the ascent, the change in the x direction ... }
Perfect, already comparable to the fireworks effect of the fireworks festival. The last thing is to add some different types of fireworks. I will simply make a heart-shaped one here, and the complicated ones are up to you.
different types of fireworks
If you want to add a heart-shaped firework, how do you do it? First, you need to split the step2 of the explosion to support multiple types of rendering.
function step2(f) { const particles = f.particles; for (let i = 0, len = particles.length; i < len; i++) { const p = particles[i]; if (p.alpha <= 0) { continue; } // Depending on the type of fireworks, different rendering methods are used switch(f.type){ case 1: step2_circle(p, f.x, f.y); // This is the original round firework break; case 2: step2_heart(p, f.x, f.y); break; default: step2_circle(p, f.x, f.y); break; } } } // The fireworks produced by createFireworks add a type attribute to control different types of fireworks function createFireworks(type) { const firework = { ... type: Math.floor(Math.random() * 2) + 1, }; }
Love type
The last is to make the fireworks of love into a separate rendering method:
// The effect after the explosion is love function step2_heart(p, x, y) { const t = p.radians let vx = p.radius * Math.pow(Math.sin(t), 3); let vy = p.radius / 1.2 * Math.cos(t) - p.radius / 3.2 * Math.cos(2*t) - p.radius / 8 * Math.cos(3*t) - p.radius / 16 * Math.cos(4*t) + p.radius / 6.4; p.vx += vx; p.vy -= vy; p.radius *= 1 - p.speed / 100; // gradually slow down p.alpha -= 0.005; ctx.beginPath(); ctx.arc(x - 5 + p.vx, y - 5 + p.vy, size, 0, Math.PI * 2, false); ctx.closePath(); ctx.fillStyle = `hsla(${p.hue}, 100%, ${p.brightness}%, ${p.alpha})`; ctx.fill(); }
at last
Finally, there is a question, if the firework explosion is a piece of text, how to do it?
Finish
Well, this is the end of this article, I hope this article is helpful to you :-)
Recently, I created a new official account: Hao, who writes code, please pay attention 😄. Later, I will gradually accumulate the front-end knowledge and workplace knowledge I have mastered.
If you have any questions or suggestions, you can communicate more. Original articles have limited writing skills and lack of knowledge. If there are any inaccuracies in the article, please let me know.