More code, read carefully!!

preview

Full project preview —- preview address;

Properties design

Fireworks state: Fireworks should have three states:

  1. launch
  2. Waiting for the crack
  3. After the burst

Fireworks: launch point (X, Y), explosion point (xEnd, yEnd), wait time after lift-off (wait), number of particles after blasting (count), fireworks radius (RADIUS)

The particle after fireworks burst: its position (X, Y), its size (size), its speed (rate), maximum fireworks radius (RADIUS).

Config: global variables and control parameters, including canvas width and height, setting fireworks properties, etc.

Setting global variables

const config = {
    width: 360.height: 600.canvases: ['bg'.'firework'].skyColor: '210, 60%, 5% and 0.2)'.fireworkTime: {min:30.max:60},
    // The fireworks parameter itself has a default value
    fireworkOpt:{
    	x: undefined.y: undefined.xEnd: undefined.yEnd: undefined.count: 300.// Number of particles after blasting
    	wait: undefined.// After disappearing => Burst wait time}}Copy the code

Construction of microparticles

class Particle{
    // The default value
    constructor({x, y, size = 1, radius = 1.2{} = {})this.x = x;
    	this.y = y;
    	this.size = size;
        
    	this.rate = Math.random(); // Each particle moves at a randomly different speed
    	this.angle = Math.PI * 2 * Math.random(); // The offset Angle of each particle
    	
    	// Each particle movement is decomposed into a horizontal and vertical movement.
    	this.vx = radius * Math.cos(this.angle) * this.rate; 
    	this.vy = radius * Math.sin(this.angle) * this.rate;
    }

    go(){
    	this.x += this.vx;
    	this.y += this.vy; 
    	this.vy += 0.02; // The greater the gravity effect y, the lower it actually is
    	
    	// Air resistance
    	this.vx *= 0.98;
    	this.vy *= 0.98;
    }
    
    // Draw the positions of the particles
    render(ctx){
    	this.go();
    	ctx.beginPath();
    	ctx.arc(this.x, this.y, this.size, 0.Math.PI * 2.false); ctx.fill(); }}Copy the code

Building fireworks class

class Firework{
    constructor({x, y = config.height, xEnd, yEnd, count = 300, wait} = {}){
        // Fireworks themselves
    	this.x = x || config.width / 8 + Math.random() * config.width * 3 / 4; 
    	this.y = y;
    	this.xEnd = xEnd || this.x;
    	this.yEnd = yEnd || config.width / 8 + Math.random() * config.width * 3 / 8;
    	this.size = 2;
    	this.velocity = - 3;
    	
    	this.opacity = 0.8;
    	this.color = `hsla(The ${360 * Math.random() | 0}`, 80%, 60%, 1);
    	this.wait = wait || 30 + Math.random() * 30;
    	// Number of particles, etc
        this.count = count;
    	this.particles = [];
    	this.createParticles();
    
    	this.status = 1;
    }
    // Create a particle
    createParticles(){
    	for(let i = 0; i <this.count; ++i){
            this.particles.push(new Particle({x:this.xEnd, y:this.yEnd})); }}/ / launch
    rise(){
    	this.y += this.velocity * 1;
    	this.velocity += 0.005; // Drag during liftoff
    	// The fireworks begin to fade away when they reach their target
    	if(this.y - this.yEnd <= 50) {this.opacity = (this.y - this.yEnd) / 50;
    	}
    	// If you reach the target position, start the second state
    	if(this.y <= this.yEnd){
    		this.status = 2; }}// Render fireworks returns false when all actions are complete
    render(ctx){
        switch(this.status){
            case 1: / / launch
    		ctx.save();
    		ctx.beginPath();
    		ctx.globalCompositeOperation = 'lighter';
    		ctx.globalAlpha = this.opacity;
    		ctx.translate(this.x, this.y);
    		ctx.scale(0.8.2.3);
    		ctx.translate(-this.x, -this.y);
    		ctx.fillStyle = this.color;
    		ctx.arc(this.x + Math.sin(Math.PI * 2 * Math.random()) / 1.2.this.y, this.size, 0.Math.PI * 2.false);
    		ctx.fill();
    		ctx.restore();
    
    		this.rise();
    		return true;
            break;
    	    case 2: // The fireworks disappear stage, waiting to explode
    		if(--this.wait <= 0) {this.opacity = 1;
    		    this.status = 3;
    		}
    		return true;
    	    break;
    	    case 3: // Render firework particles after blasting
    		ctx.save();
    		ctx.globalCompositeOperation = 'lighter';
    		ctx.globalAlpha = this.opacity;
    		ctx.fillStyle = this.color;
    		for(let i = 0; i <this.particles.length; ++i){this.particles[i].render(ctx);
    		}
    		ctx.restore();
    		this.opacity -= 0.01;
    		return this.opacity > 0;
    	    break;
    	    default: 
    		return false; }}}Copy the code

set off fireworks

const canvas = {
    init: function(){
        // Some attribute Settings can be ignored
    	this.setProperty();
    	this.renderBg();
    	
    	// Loop body ** main
    	this.loop();
    },
    setProperty: function(){
    	this.fireworks = [];
    	this.width = config.width;
    	this.height = config.height;
    	this.fireworkTime = (config.fireworkTime.min + (config.fireworkTime.max - config.fireworkTime.min) * Math.random()) | 0;
    
    	this.bgCtx = document.querySelector('#bg').getContext('2d');
    	this.fireworkCtx = document.querySelector('#firework').getContext('2d');
    },
    renderBg(){
    	this.bgCtx.fillStyle = 'hsla (210, 60%, 5% and 0.9)'
    	this.bgCtx.fillRect(0.0.this.width, this.height);
    },
    
    loop(){
    	requestAnimationFrame(this.loop.bind(this));
    	this.fireworkCtx.clearRect(0.0.this.width, this.height);
        
        // Randomly create fireworks
    	if(--this.fireworkTime <= 0) {this.fireworks.push(new Firework(config.fireworkOpt));
            / / every time point after resetting the fireworks produce time (| 0 into integer)
            this.fireworkTime = (config.fireworkTime.min + (config.fireworkTime.max - config.fireworkTime.min) * Math.random()) | 0;
    	}
    
    	for(let i = this.fireworks.length - 1; i >= 0; --i){
    	    // Render fireworks (remove fireworks if return value is false)
            !this.fireworks[i].render(this.fireworkCtx) && this.fireworks.splice(i,1);	
    	}
    
    }
}
canvas.init();
Copy the code

perfect

Now the fireworks are like this, it feels like a little tail is missing.

Now we are clearing the canvas for each frame. It is easy to add the tail. Instead of clearing the canvas for each frame, we will cover it with a new layer of transparent sky.

/ / canvas. Loop method

// this.fireworkCtx.clearRect(0, 0, this.width, this.height);
this.fireworkCtx.fillStyle = config.skyColor;
this.fireworkCtx.fillRect(0.0.this.width,this.height);	
Copy the code

And then it looks like this.

However, the scene where the sky lightens up at the moment of the explosion is still missing.

So when painting fireworks, the first will get the color and transparency of fireworks.

// *****Firework constructor
// this.color = `hsla(${360 * Math.random() | 0},80%,60%,1)`;
this.hue = 360 * Math.random() | 0;
this.color = `hsla(The ${this.hue}`, 80%, 60%, 1);
Copy the code
// *****Firework adds instance methods
getSkyColor(){
    const skyColor = {
        // Only the burst phase can return brightness
    	lightness: this.status == 3 ? this.opacity : 0 ,
    	hue: this.hue
    };
    return skyColor;
}
Copy the code
// *****config Modify the skyColor of config
// skyColor: 'hSLA (210, 60%, 5%, 0.2)',
skyColor: 'hsla ({hue}, 60%, {lightness} %, 0.2)'.Copy the code
/ / canvas. Loop method
//this.fireworkCtx.fillStyle = config.skyColor;
// Replace hue and brightness values each time.
this.fireworkCtx.fillStyle = config.skyColor.replace('{lightness}'.5 + this.skyColor.lightness * 15).replace('{hue}' , this.skyColor.hue);

this.skyColor = { / / new
    lightness: 0.hue: 210
};
for(let i = this.fireworks.length - 1; i >= 0; --i){
    // Add the sky color to the brightest fireworks color
    this.skyColor = this.skyColor.lightness >= this.fireworks[i].getSkyColor().lightness ? this.skyColor : this.fireworks[i].getSkyColor();
    !this.fireworks[i].render(this.fireworkCtx) && this.fireworks.splice(i,1);	
}
Copy the code

And now we’re done.

Complete the project

Github project address

If you think so, please star one.

Fireworks making reference links

I refer to many works on codepen. IO.

Fireworks seen in the countryside

fireworks seen in the countryside