├── index.html
├── fireworks.css
└── fireworks.js
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Fireworks
9 |
10 |
11 | Click the Firework!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/fireworks.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | background: radial-gradient(circle, #020111, #000000);
4 | overflow: hidden;
5 | height: 100vh;
6 | cursor: pointer;
7 | font-family: "Arial", sans-serif;
8 | color: white;
9 | text-align: center;
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 | flex-direction: column;
14 | }
15 |
16 | /* Add large instruction text */
17 | .instructions {
18 | font-size: 2rem;
19 | font-weight: bold;
20 | z-index: 10;
21 | color: #ff9671;
22 | text-shadow: 1px -1px 7px rgb(142 142 142 / 80%);
23 | }
24 |
25 | .projectile {
26 | position: absolute;
27 | width: 12px;
28 | height: 12px;
29 | background: white;
30 | border-radius: 50%;
31 | box-shadow: 0 0 20px rgba(255, 255, 255, 0.8),
32 | 0 0 30px rgba(255, 255, 255, 0.6), 0 0 40px rgba(255, 255, 255, 0.4);
33 | }
34 |
35 | .particule {
36 | position: absolute;
37 | font-size: 2rem;
38 | font-family: "Cursive", serif;
39 | font-weight: bold;
40 | color: white;
41 | transform: scale(0);
42 | opacity: 0;
43 | }
44 |
45 | .sparkle {
46 | position: absolute;
47 | width: 6px;
48 | height: 6px;
49 | border-radius: 50%;
50 | background: white;
51 | transform: scale(0);
52 | opacity: 0;
53 | }
54 |
--------------------------------------------------------------------------------
/fireworks.js:
--------------------------------------------------------------------------------
1 | const colors = [
2 | "#ff6f91",
3 | "#ff9671",
4 | "#ffc75f",
5 | "#f9f871",
6 | "#ff4c4c",
7 | "#ffcc00"
8 | ];
9 | const letters = "I LOVE YOU";
10 | let letterIndex = 0;
11 |
12 | function getRandomLetter() {
13 | const letter = letters.charAt(letterIndex);
14 | letterIndex = (letterIndex + 1) % letters.length;
15 | return letter;
16 | }
17 |
18 | function createFirework(x, y) {
19 | const launchHeight =
20 | Math.random() * (window.innerHeight / 4) + window.innerHeight / 4;
21 | const projectile = document.createElement("div");
22 | projectile.classList.add("projectile");
23 | document.body.appendChild(projectile);
24 | projectile.style.left = `${x}px`;
25 | projectile.style.top = `${y}px`;
26 |
27 | anime({
28 | targets: projectile,
29 | translateY: -launchHeight,
30 | duration: 1200,
31 | easing: "easeOutQuad",
32 | complete: () => {
33 | projectile.remove();
34 | createBurst(x, y - launchHeight);
35 | }
36 | });
37 | }
38 |
39 | function createBurst(x, y) {
40 | const numLetters = 15;
41 | const numSparkles = 50;
42 |
43 | // Letters
44 | for (let i = 0; i < numLetters; i++) {
45 | createParticle(x, y, false);
46 | }
47 |
48 | // Sparkles
49 | for (let i = 0; i < numSparkles; i++) {
50 | createParticle(x, y, true);
51 | }
52 | }
53 |
54 | function createParticle(x, y, isSparkle) {
55 | const el = document.createElement("div");
56 | el.classList.add(isSparkle ? "sparkle" : "particule");
57 | const instruction = document.querySelector('.instructions').style.display = 'none';
58 |
59 | if (!isSparkle) {
60 | el.textContent = getRandomLetter();
61 | el.style.color = colors[Math.floor(Math.random() * colors.length)];
62 | } else {
63 | el.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
64 | }
65 |
66 | el.style.left = `${x}px`;
67 | el.style.top = `${y}px`;
68 | document.body.appendChild(el);
69 |
70 | animateParticle(el, isSparkle);
71 | }
72 |
73 | function animateParticle(el, isSparkle) {
74 | const angle = Math.random() * Math.PI * 2;
75 | const distance = anime.random(100, 200);
76 | const duration = anime.random(1200, 2000);
77 | const fallDistance = anime.random(20, 80);
78 | const scale = isSparkle ? Math.random() * 0.5 + 0.5 : Math.random() * 1 + 0.5;
79 |
80 | anime
81 | .timeline({
82 | targets: el,
83 | easing: "easeOutCubic",
84 | duration: duration,
85 | complete: () => el.remove()
86 | })
87 | .add({
88 | translateX: Math.cos(angle) * distance,
89 | translateY: Math.sin(angle) * distance,
90 | scale: [0, scale],
91 | opacity: [1, 0.9]
92 | })
93 | .add({
94 | translateY: `+=${fallDistance}px`,
95 | opacity: [0.9, 0],
96 | easing: "easeInCubic",
97 | duration: duration / 2
98 | });
99 | }
100 |
101 | document.addEventListener("click", (e) => {
102 | createFirework(e.clientX, e.clientY);
103 |
104 | });
105 |
106 | window.onload = function () {
107 | const centerX = window.innerWidth / 2;
108 | const centerY = window.innerHeight / 2;
109 | createFirework(centerX, centerY);
110 | };
111 |
--------------------------------------------------------------------------------