how to add some FIREWORKS to your website

Shen Huang
Frontend Weekly
Published in
8 min readFeb 4, 2019

It is close to the Chinese New Year which is a time you will see lots of fireworks. Here I will show you a nice little trick that adds some holiday spirit to your own website.

A demonstration can be found here, once you click on anywhere on the screen you will see a firework shooting up from your mouse.

Happy New Year Firework Demo

Now let’s get started! First of all, you will need a webpage, I recommend darker background as fireworks look good in the dark. If you do not have a .html file for your webpage, simply take the following code and save it as a .html.

<!--Copyright to Shen Huang, you can reach me out at shenhuang@live.ca--><!DOCTYPE html>
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<html>
<head>
<title>FIREWORK DEMO</title>
<style>
body {
background-color : #001126;
}
</style>
</head>
<body>
YOUR PRECIOUS HTML CODE GOES HERE
</body>
<script>
YOUR SUPPER COOL SCRIPTS GOES HERE
</script>
</html>

Now we have to set up the animation for the particles. I personally prefer this unicorn magic color transitions, but you can always be creative with the color. Put the CSS code below anywhere between your <style></style> tags.

@keyframes    firework-animation {
0% {background-color : #ff8426;}
25% {background-color : #fffc84;}
50% {background-color : #ff83f4;}
75% {background-color : #83b6ff;}
100% {background-color : #ff8426;}
}
@-webkit-keyframes firework-animation {
0% {background-color : #ff8426;}
25% {background-color : #fffc84;}
50% {background-color : #ff83f4;}
75% {background-color : #83b6ff;}
100% {background-color : #ff8426;}
}
.fireWorkParticle {
z-index : 999;
position: absolute;
height : 5px;
width : 5px;
border-radius : 5px;
animation-name : firework-animation;
animation-timing-function : linear;
animation-duration : 1s;
animation-iteration-count : infinite;
}

Now in order to test and see if the code works, paste the following code anywhere between the <body></body> tags, you should now see a color-shifting particle sitting on the top left corner of the webpage.

<div class = "fireWorkParticle"></div>
Firework Bits on Top Left Corner

But in order for our fireworks to work, we don’t want to manually create every single bit, we would like to do it dynamically. In order to do so first, we create a board in the body to place things. Paste the following code between the <body></body> tags.

<div id = "board"></div>

In between the <script></script> tags, we can now append objects to this board we have just created with the code below. In case you are using the example .html code I have provided, make sure you removed the “YOUR SUPPER COOL SCRIPTS GOES HERE” in order for the scripts to run properly.

var brd = document.createElement("DIV");
document.body.insertBefore(brd, document.getElementById("board"));

Now we also need an array to store all the particles, append the script with the following code.

particles = [];

Then we have to define a function to create the particle so we can reuse it in the future, below are the code.

function newFireworkParticle(x, y, angle)
{
var fwkPtc = document.createElement("DIV");
fwkPtc.setAttribute('class', 'fireWorkParticle');
fwkPtc.position = [];
fwkPtc.position.x = x;
fwkPtc.position.y = y;
fwkPtc.style.left = fwkPtc.position.x + 'px';
fwkPtc.style.top = fwkPtc.position.y + 'px';
brd.appendChild(fwkPtc);
particles.push(fwkPtc);
return fwkPtc;
}

To see if our code worked, we create a particle right after we defined the function.

newFireworkParticle(200, 200);
Firework Bits at (200, 200)

Now in order to have things moving around, we have to first define some physical constant. The fwkPtcIniV below basically means the initial velocity, while fwkPtcIniT means the millisecond time the particle will survive. The variable indicates air resistance and g indicates the gravitational pull.

const fwkPtcIniV = 0.5;
const fwkPtcIniT = 2500;
const a = 0.0005;
const g = 0.0005;

We put the code right below the particle array definition, and we need to rework the firework particle creation code so that it properly accepts its physical properties. The code involves some high school math and physics and will not be explained here.

function newFireworkParticle(x, y, angle)
{
var fwkPtc = document.createElement("DIV");
fwkPtc.setAttribute('class', 'fireWorkParticle');
brd.appendChild(fwkPtc);
fwkPtc.time = fwkPtcIniT;
while(angle > 360)
angle -= 360;
while(angle < 0)
angle += 360;
fwkPtc.velocity = [];
if(angle > 270)
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180);
}
else if(angle > 180)
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180);
}
else if(angle > 90)
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180);
}
else
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180));
}
fwkPtc.position = [];
fwkPtc.position.x = x;
fwkPtc.position.y = y;
fwkPtc.style.left = fwkPtc.position.x + 'px';
fwkPtc.style.top = fwkPtc.position.y + 'px';
if(seeds == null)
seeds = [];
particles.push(fwkPtc);
return fwkPtc;
}

And in order to correctly render it, we need the following code to refresh the position and speed of the particle every 5 milliseconds.

var before = Date.now();
var id = setInterval(frame, 5);
function frame()
{
var current = Date.now();
var deltaTime = current - before;
before = current;
for(i in particles)
{
var fwkPtc = particles[i];
fwkPtc.time -= deltaTime;
if(fwkPtc.time > 0)
{
fwkPtc.velocity.x -= fwkPtc.velocity.x * a * deltaTime;
fwkPtc.velocity.y -= g * deltaTime + fwkPtc.velocity.y * a * deltaTime;
fwkPtc.position.x += fwkPtc.velocity.x * deltaTime;
fwkPtc.position.y -= fwkPtc.velocity.y * deltaTime;
fwkPtc.style.left = fwkPtc.position.x + 'px';
fwkPtc.style.top = fwkPtc.position.y + 'px';
}
else
{
fwkPtc.parentNode.removeChild(fwkPtc);
particles.splice(i, 1);
}
}
}

Once all is done, the following code should create a particle shooting at 30 degrees.

newFireworkParticle(200, 200, 30);
Firework Bits Shooting at a 30 Degree Angle

And a firework star is simply a bunch of firework particles shooting at different angles, it can be accomplished with the following code.

function newFireWorkStar(x, y)
{
var a = 0;
while(a < 360)
{
newFireworkParticle(x, y, a);
a += 15;
}
}

Test with the following code to see if it worked.

newFireWorkStar(200, 200);
Firework Star Demo

Similarly, we can add a seed animation and make it shoot up then explodes into the firework ring we have just created. In order to do so, we need to append the following CSS and JavaScript code.

CSS (Put it between your <style></style>tags)

@keyframes    firework-seed-animation {
0% {background-color : #ff8426;}
25% {background-color : #fffc84;}
100% {background-color : #ff8426;}
}
@-webkit-keyframes firework-seed-animation {
0% {background-color : #ff8426;}
25% {background-color : #fffc84;}
100% {background-color : #ff8426;}
}
.fireWorkSeed {
z-index : 999;
position: absolute;
height : 5px;
width : 5px;
border-radius : 5px;
animation-name : firework-seed-animation;
animation-timing-function : linear;
animation-duration : 0.5s;
animation-iteration-count : infinite;
}

Java Script (Put it between your <script></script> tag)

seeds = [];
function newFireworkSeed(x, y)
{
var fwkSed = document.createElement("DIV");
fwkSed.setAttribute('class', 'fireWorkSeed');
brd.appendChild(fwkSed);
fwkSed.time = fwkSedIniT;
fwkSed.velocity = [];
fwkSed.velocity.x = 0;
fwkSed.velocity.y = fwkSedIniV;
fwkSed.position = [];
fwkSed.position.x = x;
fwkSed.position.y = y;
fwkSed.style.left = fwkSed.position.x + 'px';
fwkSed.style.top = fwkSed.position.y + 'px';
if(seeds == null)
seeds = [];
seeds.push(fwkSed);
return fwkSed;
}

Now we have to modify the animation controller a little bit to make it render the seeds too.

function frame()
{
var current = Date.now();
var deltaTime = current - before;
before = current;
for(i in seeds)
{
var fwkSed = seeds[i];
fwkSed.time -= deltaTime;
if(fwkSed.time > 0)
{
fwkSed.velocity.x -= fwkSed.velocity.x * a * deltaTime;
fwkSed.velocity.y -= g * deltaTime + fwkSed.velocity.y * a * deltaTime;
fwkSed.position.x += fwkSed.velocity.x * deltaTime;
fwkSed.position.y -= fwkSed.velocity.y * deltaTime;
fwkSed.style.left = fwkSed.position.x + 'px';
fwkSed.style.top = fwkSed.position.y + 'px';
}
else
{
newFireWorkStar(fwkSed.position.x, fwkSed.position.y);
fwkSed.parentNode.removeChild(fwkSed);
seeds.splice(i, 1);
}
}
for(i in particles)
{
var fwkPtc = particles[i];
fwkPtc.time -= deltaTime;
if(fwkPtc.time > 0)
{
fwkPtc.velocity.x -= fwkPtc.velocity.x * a * deltaTime;
fwkPtc.velocity.y -= g * deltaTime + fwkPtc.velocity.y * a * deltaTime;
fwkPtc.position.x += fwkPtc.velocity.x * deltaTime;
fwkPtc.position.y -= fwkPtc.velocity.y * deltaTime;
fwkPtc.style.left = fwkPtc.position.x + 'px';
fwkPtc.style.top = fwkPtc.position.y + 'px';
}
else
{
fwkPtc.parentNode.removeChild(fwkPtc);
particles.splice(i, 1);
}
}
}

And in order to make it shoot from a mouse click, we need the following scripts. The cursor offset makes the firework looks like as if it is launching from the pointy end of the cursor, otherwise, the launch location may be slightly off.

const cursorXOffset = 5;
const cursorYOffset = 0;
document.addEventListener("click", newFireWorkOnClick);function newFireWorkOnClick(event)
{
newFireworkSeed(event.pageX - brd.offsetLeft + cursorXOffset, event.pageY - brd.offsetTop + cursorYOffset);
}

And to make the firework look more realistic, we have to alter the code a little bit to add a bit randomness in their initial speed by altering our particle creation code.

const v = 0.3;function newFireworkParticle(x, y, angle)
{
var fwkPtc = document.createElement("DIV");
fwkPtc.setAttribute('class', 'fireWorkParticle');
brd.appendChild(fwkPtc);
fwkPtc.time = fwkPtcIniT;
while(angle > 360)
angle -= 360;
while(angle < 0)
angle += 360;
fwkPtc.velocity = [];
if(angle > 270)
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180) * (1 - Math.random() * v);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180) * (1 - Math.random() * v);
}
else if(angle > 180)
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180) * (1 - Math.random() * v);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180) * (1 - Math.random() * v);
}
else if(angle > 90)
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180) * (1 - Math.random() * v);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180) * (1 - Math.random() * v);
}
else
{
fwkPtc.velocity.x = fwkPtcIniV * Math.sin(angle * Math.PI / 180) * (1 - Math.random() * v);
fwkPtc.velocity.y = fwkPtcIniV * Math.cos(angle * Math.PI / 180) * (1 - Math.random() * v);
}
fwkPtc.position = [];
fwkPtc.position.x = x;
fwkPtc.position.y = y;
fwkPtc.style.left = fwkPtc.position.x + 'px';
fwkPtc.style.top = fwkPtc.position.y + 'px';
if(particles == null)
particles = [];
particles.push(fwkPtc);
return fwkPtc;
}

Meanwhile, we need more particles, and so let’s alter the loop a little bit too to make it generate 3 times more particles.

function newFireWorkStar(x, y)
{
var a = 0;
while(a < 360)
{
newFireworkParticle(x, y, a);
a += 5;
}
}
Complete Firework Demo

And if everything went right, you can now celebrate the success of learning this tutorial with FIREWORKS!!!

In the future, I may add more tutorials on a shooting star, flower blossoms, bubbles, and other effects, or a game embedded in your console like this one shown below, where you get to play it after brining up the developer console with F12. Let me know if you have any special requests.

Demo of a Game Hidden in Console

Have fun and a Happy Chinese New Year with lots of Fireworks!

I have some previous guides on similar projects.

Beginner:

Advanced:

Appendix (Complete code of this project):

To celebrate my first post on Frontend Weekly I am adding a fading effect exclusively to this demo.

--

--