< html > < body style =' background - color : black '> < canvas id =' myCanvas ' width =' 800 ' height =' 800 '></ canvas > < script > const max _ fireworks = 5 , max _ sparks = 50 ; let canvas = document . getElementById (' myCanvas '); let context = canvas . getContext ('2d'); let fireworks = []; for ( let i = 0 ; i < max _ fireworks ; i ++) { let firework = { sparks : [] }; for ( let n = 0 ; n < max _ sparks ; n ++) { let spark = { vx : Math . random () * 5 + . 5 , vy : Math . random () * 5 + . 5 , weight : Math . random () * . 3 + . 03 , red : Math . floor ( Math . random () * 2 ), green : Math . floor ( Math . random () * 2 ), blue : Math . floor ( Math . random () * 2 ) }; if ( Math . random () > . 5 ) spark . vx = - spark . vx ; if ( Math . random () > . 5 ) spark . vy = - spark . vy ; firework . sparks . push ( spark ); } fireworks . push ( firework ); resetFirework ( firework ); } window . requestAnimationFrame ( explode ); function resetFirework ( firework ) { firework . x = Math . floor ( Math . random () * canvas . width ); firework . y = canvas . height ; firework . age = 0 ; firework . phase = ' fly '; } function explode () { context . clearRect ( 0 , 0 , canvas . width , canvas . height ); fireworks . forEach (( firework , index ) => { if ( firework . phase == ' explode ') { firework . sparks . forEach (( spark ) => { for ( let i = 0 ; i < 10 ; i ++) { let trailAge = firework . age + i ; let x = firework . x + spark . vx * trailAge ; let y = firework . y + spark . vy * trailAge + spark . weight * trailAge * spark . weight * trailAge ; let fade = i * 20 - firework . age * 2 ; let r = Math . floor ( spark . red * fade ); let g = Math . floor ( spark . green * fade ); let b = Math . floor ( spark . blue * fade ); context . beginPath (); context . fillStyle = ' rgba (' + r + ',' + g + ',' + b + ', 1 )'; context . rect ( x , y , 4 , 4 ); context . fill (); } }); firework . age ++; if ( firework . age > 100 && Math . random () < . 05 ) { resetFirework ( firework ); } } else { firework . y = firework . y - 10 ; for ( let spark = 0 ; spark < 15 ; spark ++) { context . beginPath (); context . fillStyle = ' rgba (' + index * 50 + ',' + spark * 17 + ', 0 , 1 )'; context . rect ( firework . x + Math . random () * spark - spark / 2 , firework . y + spark * 4 , 4 , 4 ); context . fill (); } if ( Math . random () < . 001 || firework . y < 200 ) firework . phase = ' explode '; } }); window . requestAnimationFrame ( explode ); } </ script > </ body > </ html >

We'll keep the code short and simple, so our fireworks will not look very fancy or realistic - in fact, they will be more similar to the ones you saw on Geocities twenty years ago. But it's still a good coding exercise.The main program [lines 5-31] first declares the variables and then creates an array of the firework objects. Each firework will have its own x and y coordinates, age (time elapsed since the explosion), phase (fly/explode) and an array of sparks.Each spark in turn has its own horizontal (vx) and vertical (vy) velocity, weight, which determines how quickly it falls and a color (determined by red, green and blue components).In [31], we kick off the main animation function - explode [40-75].This function updates and draws each spark of each firework.[44-62] is the explosion phase. In this phase, each spark has a trail of 10 rectangles. We calculate the position of each rectangle [45-48] based on the coordinates of the firework, the velocity of the spark, the 'age' of the explosion and the index of the rectangle. I did not use any ballistic formulas, instead, I came up with this weirdo [48] by trial and error.[49-52] calculates the color of each rectangle, taking into account the fade factor, which is derived from the 'age' of the explosion - the older the explosion, the darker the color.[53-56] draws the rectangleIn [60-61], there is a 5% chance of resetting the firework if the explosion is older than 100 frames.The reset function [33-37] puts the firework back in a random place at the bottom of the screen and the 'fly' phase begins again.In this phase [64-71], the firework moves up the screen [64] and an extremely rudimentary tail of sparks is drawn [65-69].There is a .001 chance that the firework will explode (its phase changes) in a given frame [71]. It will explode for sure once the y coordinate reaches 200.Have fun!Check out these programming tutorials: