Introduction:
Hey everyone! Today, I created an animated countdown using HTML, CSS, JavaScript, and the Animin library (utilizing animin.min.js) for fireworks effects. An animated countdown is very useful for wishing birthdays, anniversaries, and festive occasions. So, this is a very simple yet highly useful effect.
1. Create index.html file:
- Link all JS and CSS files to HTML
Code Block Example
This is the index.html file code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<script src="anime.min.js"></script>
<script src="p5.js"></script>
<title>Animated Countdown</title>
</head>
<body>
<div class="counter">
<div class="nums">
<span class="in">5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
<span>0</span>
</div>
<h4>Get Ready</h4>
</div>
<div class="final">
<h1>GO</h1>
<button id="replay">
<span>Boom Boom Boom!!!</span>
</button>
</div>
<script src="script.js"></script>
<script>
</script>
</body>
</html>
2. Create style.css file:
- Create the CSS file and name it style.css, then save it.
- And then link the style.css filt to index.html like this <link href="style.css" rel="stylesheet">
This is the style.css file code
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
* {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
margin: 0;
height: 100vh;
overflow: hidden;
background-color: #000;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
background-position: top right;
animation: mymove 15s infinite;
}
@keyframes mymove {
50% {background-position: center;}
}
h4 {
font-size: 20px;
margin: 5px;
text-transform: uppercase;
}
.counter {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.counter.hide {
transform: translate(-50%, -50%) scale(0);
animation: hide 0.2s ease-out;
}
@keyframes hide {
0% {
transform: translate(-50%, -50%) scale(1);
}
100% {
transform: translate(-50%, -50%) scale(0);
}
}
.final {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
text-align: center;
}
.final.show {
transform: translate(-50%, -50%) scale(1);
animation: show 0.2s ease-out;
}
@keyframes show {
0% {
transform: translate(-50%, -50%) scale(0);
}
30% {
transform: translate(-50%, -50%) scale(1.4);
}
100% {
transform: translate(-50%, -50%) scale(1);
}
}
.nums {
color: #3498db;
font-size: 50px;
position: relative;
overflow: hidden;
width: 250px;
height: 50px;
}
.nums span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(120deg);
transform-origin: bottom center;
}
.nums span.in {
transform: translate(-50%, -50%) rotate(0deg);
animation: goIn 0.5s ease-in-out;
}
.nums span.out {
animation: goOut 0.5s ease-in-out;
}
@keyframes goIn {
0% {
transform: translate(-50%, -50%) rotate(120deg);
}
30% {
transform: translate(-50%, -50%) rotate(-20deg);
}
60% {
transform: translate(-50%, -50%) rotate(10deg);
}
100% {
transform: translate(-50%, -50%) rotate(0deg);
}
}
@keyframes goOut {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
60% {
transform: translate(-50%, -50%) rotate(20deg);
}
100% {
transform: translate(-50%, -50%) rotate(-120deg);
}
}
#replay{
background-color: #3498db;
border-radius: 3px;
border: none;
color: aliceblue;
padding: 5px;
text-align: center;
display: inline-block;
cursor: pointer;
transition: all 0.3s;
}
#replay span{
cursor: pointer;
display: inline-block;
position: relative;
transition: 0.3s;
}
#replay span:after{
content: '\00bb';
position: absolute;
opacity: 0;
top: 0;
right: -20px;
transition: 0.5s;
}
#replay:hover span{
padding-right: 25px;
}
#replay:hover span:after{
opacity: 1;
right: 0;
}
3. Create script.js file:
let fireworks = [];
function setup() {
createCanvas(windowWidth, windowHeight);
}
function startFireworks() {
setInterval(() => {
fireworks.push(new Firework());
}, 1000);
// Show the popup after 3 seconds
setTimeout(() => {
createPopup();
}, 3000);
}
function draw() {
background(0, 25);
for (let i = fireworks.length - 1; i >= 0; i--) {
fireworks[i].update();
fireworks[i].show();
if (fireworks[i].done()) {
fireworks.splice(i, 1);
}
}
}
class Firework {
constructor() {
this.x = random(width);
this.y = height;
this.exploded = false;
this.explosionTimer = 0;
this.vx = random(-1, 1);
this.vy = random(-20, -15);
this.explosionRadius = random(50, 150);
this.explosionColor = color(random(255), random(255), random(255));
this.missileTrail = [];
this.explosionTrail = [];
}
update() {
if (!this.exploded) {
// Update missile position
this.x += this.vx;
this.y += this.vy;
this.vy += 0.5;
this.missileTrail.push(createVector(this.x, this.y));
if (this.vy >= 0) {
this.explode();
}
} else {
for (let particle of this.explosionTrail) {
particle.update();
}
this.explosionTimer++;
}
}
show() {
if (!this.exploded) {
noFill();
strokeWeight(3);
stroke(255, 150);
beginShape();
for (let pt of this.missileTrail) {
vertex(pt.x, pt.y);
}
endShape();
} else {
for (let particle of this.explosionTrail) {
particle.show();
}
}
}
explode() {
for (let i = 0; i < 100; i++) {
let angle = random(TWO_PI);
let speed = random(2, 10);
this.explosionTrail.push(new Particle(this.x, this.y, angle, speed, this.explosionRadius, this.explosionColor));
}
this.exploded = true;
}
done() {
return this.exploded && this.explosionTimer > 60;
}
}
class Particle {
constructor(x, y, angle, speed, explosionRadius, explosionColor) {
this.x = x;
this.y = y;
this.vx = cos(angle) * speed;
this.vy = sin(angle) * speed;
this.explosionRadius = explosionRadius;
this.explosionColor = explosionColor;
this.alpha = 255;
this.size = random(2, 8);
}
update() {
this.x += this.vx;
this.y += this.vy;
this.alpha -= 5;
}
show() {
noStroke();
fill(this.explosionColor.levels[0], this.explosionColor.levels[1], this.explosionColor.levels[2], this.alpha);
ellipse(this.x, this.y, this.size, this.size);
}
}
const nums = document.querySelectorAll('.nums span')
const counter = document.querySelector('.counter')
const finalMessage = document.querySelector('.final')
const replay = document.querySelector('#replay')
runAnimation()
function resetDOM() {
counter.classList.remove('hide')
finalMessage.classList.remove('show')
nums.forEach((num) => {
num.classList.value = ''
})
nums[0].classList.add('in')
}
function runAnimation() {
nums.forEach((num, idx) => {
const nextToLast = nums.length - 1
num.addEventListener('animationend', (e) => {
if (e.animationName === 'goIn' && idx !== nextToLast) {
num.classList.remove('in')
num.classList.add('out')
} else if (e.animationName === 'goOut' && num.nextElementSibling) {
num.nextElementSibling.classList.add('in')
} else {
counter.classList.add('hide')
finalMessage.classList.add('show')
startFireworks();
}
})
})
}
replay.addEventListener('click', () => {
setup()
resetDOM()
runAnimation()
})
Preview...