├── 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 | --------------------------------------------------------------------------------