Created
May 30, 2025 18:27
-
-
Save jheitzeb/0171d64628d2a36e75082a0ab5a6bbc7 to your computer and use it in GitHub Desktop.
Fireworks show
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let lastFireworksTime = 0; | |
let originalBodyProperties = {}; | |
function perform_fireworks_show() { | |
console.log("Starting fireworks show"); | |
// Store original body properties | |
originalBodyProperties = { | |
backgroundColor: $("body").css("background-color"), | |
opacity: $("body").css("opacity") | |
}; | |
// First, remove any existing fireworks elements | |
cleanup_fireworks(); | |
// Create our container that will hold all fireworks | |
const container = document.createElement('div'); | |
container.id = 'fireworks-container'; | |
Object.assign(container.style, { | |
position: 'fixed', | |
top: '0', | |
left: '0', | |
width: '100vw', | |
height: '100vh', | |
pointerEvents: 'none', | |
zIndex: '2147483647', // Maximum z-index possible | |
overflow: 'visible' | |
}); | |
document.body.appendChild(container); | |
console.log("Fireworks container created and appended to body"); | |
// Dim the screen with a separate overlay | |
const overlay = document.createElement('div'); | |
overlay.id = 'fireworks-background-overlay'; | |
Object.assign(overlay.style, { | |
position: 'fixed', | |
top: '0', | |
left: '0', | |
width: '100vw', | |
height: '100vh', | |
backgroundColor: '#190000', | |
opacity: '0.9', | |
pointerEvents: 'none', | |
zIndex: '2147483646' // Just below the fireworks container | |
}); | |
document.body.appendChild(overlay); | |
console.log("Background overlay created"); | |
// Debounce | |
const now = Date.now(); | |
if (now - lastFireworksTime < 500) { | |
return; | |
} | |
lastFireworksTime = now; | |
// Play sound if function exists | |
if (typeof play_fireworks_sound === 'function') { | |
play_fireworks_sound(); | |
} | |
// Create fireworks | |
let fireworkCount = 0; | |
const maxFireworks = 10; | |
const displayDuration = 3000; | |
// Create an initial burst | |
for (let i = 0; i < 5; i++) { | |
setTimeout(() => { | |
console.log(`Creating initial firework ${i}`); | |
createFirework(container); | |
}, i * 100); | |
} | |
// Continue creating fireworks | |
const interval = setInterval(() => { | |
console.log(`Creating additional firework ${fireworkCount}`); | |
createFirework(container); | |
fireworkCount++; | |
if (fireworkCount >= maxFireworks) { | |
clearInterval(interval); | |
} | |
}, 200); | |
// End the show after the display duration | |
setTimeout(() => { | |
cleanup_fireworks(); | |
// Restore original body properties | |
$("body").fadeTo(100, originalBodyProperties.opacity || 1); | |
$("body").css("background-color", originalBodyProperties.backgroundColor || ""); | |
console.log("Fireworks show ended, original properties restored"); | |
}, displayDuration); | |
} | |
// please download https://aitinkerers.org/assets/sounds/fireworks2.m4a and rehost it | |
function play_fireworks_sound() { | |
play_mp3("fireworks2.m4a", 0.8); | |
} | |
function createFirework(container) { | |
const viewportWidth = window.innerWidth; | |
const viewportHeight = window.innerHeight; | |
// Launch position | |
const startX = Math.random() * (viewportWidth * 0.8) + (viewportWidth * 0.1); | |
const startY = viewportHeight; | |
// Explosion position | |
const endX = startX + (Math.random() * 200 - 100); | |
const endY = viewportHeight * 0.3 + (Math.random() * viewportHeight * 0.4); | |
// Create firework element | |
const firework = document.createElement('div'); | |
firework.className = 'firework'; | |
Object.assign(firework.style, { | |
position: 'absolute', | |
width: '6px', | |
height: '6px', | |
borderRadius: '50%', | |
backgroundColor: 'white', | |
boxShadow: '0 0 10px 2px white', | |
left: `${startX}px`, | |
top: `${startY}px` | |
}); | |
container.appendChild(firework); | |
console.log(`Firework created at ${startX},${startY} heading to ${endX},${endY}`); | |
// Animate the firework's ascent | |
const animation = firework.animate([ | |
{ transform: 'translate(0, 0)', opacity: 1 }, | |
{ transform: `translate(${endX - startX}px, ${endY - startY}px)`, opacity: 0.8 } | |
], { | |
duration: 700, | |
easing: 'cubic-bezier(0.5, 0, 0.5, 1)' | |
}); | |
animation.onfinish = () => { | |
// Create explosion when firework reaches top | |
createExplosion(container, endX, endY); | |
firework.remove(); | |
}; | |
} | |
function createExplosion(container, x, y) { | |
console.log(`Creating explosion at ${x},${y}`); | |
// Pick a color for this explosion | |
const hue = Math.floor(Math.random() * 360); | |
// Create particles | |
for (let i = 0; i < 30; i++) { | |
const particle = document.createElement('div'); | |
particle.className = 'particle'; | |
Object.assign(particle.style, { | |
position: 'absolute', | |
width: '4px', | |
height: '4px', | |
borderRadius: '50%', | |
backgroundColor: `hsl(${hue}, 100%, 60%)`, | |
boxShadow: `0 0 8px 2px hsl(${hue}, 100%, 70%)`, | |
left: `${x}px`, | |
top: `${y}px` | |
}); | |
container.appendChild(particle); | |
// Determine particle trajectory | |
const angle = (Math.PI * 2 * i) / 30; | |
const distance = 30 + Math.random() * 70; | |
const duration = 800 + Math.random() * 400; | |
const particleX = Math.cos(angle) * distance; | |
const particleY = Math.sin(angle) * distance; | |
// Animate particle | |
particle.animate([ | |
{ transform: 'translate(0, 0) scale(1)', opacity: 1 }, | |
{ transform: `translate(${particleX}px, ${particleY}px) scale(0)`, opacity: 0 } | |
], { | |
duration: duration, | |
easing: 'cubic-bezier(0, 0.5, 0.5, 1)' | |
}).onfinish = () => particle.remove(); | |
} | |
} | |
function cleanup_fireworks() { | |
console.log("Cleaning up fireworks"); | |
// Remove container and all fireworks | |
const container = document.getElementById('fireworks-container'); | |
if (container) container.remove(); | |
// Remove background overlay | |
const overlay = document.getElementById('fireworks-background-overlay'); | |
if (overlay) overlay.remove(); | |
// Remove any stray fireworks or particles | |
document.querySelectorAll('.firework, .particle').forEach(el => el.remove()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment