diff --git a/fireworks.css b/fireworks.css index b978c2e..5314a2b 100644 --- a/fireworks.css +++ b/fireworks.css @@ -1,57 +1,66 @@ -/* container for fireworks */ .fireworks { - pointer-events: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - overflow: hidden; - z-index: 10; /* put it on top */ - } - - /* every firework particle */ - .firework { - position: absolute; - width: 6px; - height: 6px; - border-radius: 50%; - background: rgba(255, 255, 255, 0.9); /* standard colors */ - animation: explode 2.5s ease-out forwards, colorShift 2.5s linear infinite; - /*animation: explode 1s ease-out forwards;*/ - transform-origin: center; - } - - /* animation for the explosion */ - @keyframes explode { - 0% { - transform: scale(0.5); - opacity: 1; - } - 100% { - transform: translate(var(--x), var(--y)) scale(0.4); - opacity: 0; - } - } - -/* colors for the fireworks */ -@keyframes colorShift { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 10; + + /* activate the following for fixed positioning */ + /*position: fixed;*/ + /*overflow: hidden;*/ +} + +.rocket-trail { + position: absolute; + left: var(--trailX); + top: var(--trailStartY); + width: 4px; + + /* activate the following for rocket trail */ + height: 60px; + background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); + filter: blur(2px); + + /* activate the following for rocket trail as a point */ + /*height: 4px;*/ + /*background: white;*/ + /*border-radius: 50%; + box-shadow: 0 0 8px 2px white;*/ + + animation: rocket-trail-animation 1s linear forwards; +} + +@keyframes rocket-trail-animation { 0% { - background: rgba(255, 0, 0, 1); /* Kräftiges Rot */ - } - 20% { - background: rgba(0, 255, 0, 1); /* Kräftiges Grün */ - } - 40% { - background: rgba(0, 0, 255, 1); /* Kräftiges Blau */ - } - 60% { - background: rgba(255, 255, 0, 1); /* Gelb */ - } - 80% { - background: rgba(255, 0, 255, 1); /* Magenta */ + transform: translateY(0); + opacity: 1; } 100% { - background: rgba(0, 255, 255, 1); /* Türkis */ + transform: translateY(calc(var(--trailEndY) - var(--trailStartY))); + opacity: 0; } +} + +/* Animation for the particles */ +@keyframes fireworkParticle { + 0% { + opacity: 1; + transform: translate(0, 0); + } + 100% { + opacity: 0; + transform: translate(var(--x), var(--y)); + } +} + +.firework { + position: absolute; + width: 5px; + height: 5px; + background: white; + border-radius: 50%; + animation: fireworkParticle 1.5s ease-out forwards; + filter: blur(1px); } \ No newline at end of file diff --git a/fireworks.js b/fireworks.js index e712b37..18fa9c0 100644 --- a/fireworks.js +++ b/fireworks.js @@ -1,7 +1,24 @@ const fireworks = true; // enable/disable fireworks +const scrollFireworks = true; // enable fireworks to scroll with page content const particlesPerFirework = 50; // count of particles per firework +const minFireworks = 3; // minimum number of simultaneous fireworks +const maxFireworks = 6; // maximum number of simultaneous fireworks +const intervalOfFireworks = 3200; // interval for the fireworks in milliseconds + +// array of color palettes for the fireworks +const colorPalettes = [ + ['#ff0000', '#ff7300', '#ff4500'], // red's + ['#0040ff', '#5a9bff', '#b0d9ff'], // blue's + ['#47ff00', '#8eff47', '#00ff7f'], // green's + ['#ffd700', '#c0c0c0', '#ff6347'], // gold, silver, red + ['#ff00ff', '#ff99ff', '#800080'], // magenta's + ['#ffef00', '#ffff99', '#ffd700'], // yellow's + ['#ff4500', '#ff6347', '#ff7f50'], // orange's + ['#e3e3e3', '#c0c0c0', '#7d7c7c'], // silver's +]; let msgPrinted = false; // flag to prevent multiple console messages +let spacing = 0; // spacing between fireworks // function to check and control fireworks function toggleFirework() { @@ -41,69 +58,97 @@ observer.observe(document.body, { attributes: true // observe changes to attributes (e.g. class changes) }); -// function to add random fireworks -function launchFirework() { + +// Function to create a rocket trail +function createRocketTrail(x, startY, endY) { const fireworkContainer = document.querySelector('.fireworks'); - if (!fireworkContainer) return; + const rocketTrail = document.createElement('div'); + rocketTrail.classList.add('rocket-trail'); + fireworkContainer.appendChild(rocketTrail); - // some colors for the fireworks - const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff', '#ffffff']; + // Set position and animation + rocketTrail.style.setProperty('--trailX', `${x}px`); + rocketTrail.style.setProperty('--trailStartY', `${startY}px`); + rocketTrail.style.setProperty('--trailEndY', `${endY}px`); - // random position on the screen - const x = Math.random() * window.innerWidth * 0.8 + window.innerWidth * 0.1; - const y = Math.random() * window.innerHeight * 0.7 + window.innerHeight * 0.15; - //const x = Math.random() * window.innerWidth * 0.7 + window.innerWidth * 0.15; // Mittiger - //const y = Math.random() * window.innerHeight * 0.5 + window.innerHeight * 0.25; // Mittiger + // Remove the element after the animation + setTimeout(() => { + fireworkContainer.removeChild(rocketTrail); + }, 2000); // Duration of the animation +} +// Function for particle explosion +function createExplosion(x, y) { + const fireworkContainer = document.querySelector('.fireworks'); + // Choose a random color palette + const chosenPalette = colorPalettes[Math.floor(Math.random() * colorPalettes.length)]; - // create particles for the firework for (let i = 0; i < particlesPerFirework; i++) { const particle = document.createElement('div'); particle.classList.add('firework'); - // random angle and distance - const angle = Math.random() * 2 * Math.PI; // 0 to 360 degrees - const distance = Math.random() * 150 + 100; // 50 to 150 pixels + const angle = Math.random() * 2 * Math.PI; // Random direction + const distance = Math.random() * 180 + 100; // Random distance const xOffset = Math.cos(angle) * distance; const yOffset = Math.sin(angle) * distance; - // get random color - const color = colors[Math.floor(Math.random() * colors.length)]; - - const colorDelay = Math.random() * 2; // Zufällige Verzögerung bis 2 Sekunden - - // set particle properties particle.style.left = `${x}px`; particle.style.top = `${y}px`; particle.style.setProperty('--x', `${xOffset}px`); particle.style.setProperty('--y', `${yOffset}px`); - particle.style.background = color; + particle.style.background = chosenPalette[Math.floor(Math.random() * chosenPalette.length)]; - particle.style.animationDelay = `${colorDelay}s`; - - // add particle to the container fireworkContainer.appendChild(particle); - // remove particle after animation ends so the DOM doesn't get filled with particles after 3 seconds - setTimeout(() => { - particle.remove(); - }, 3000); // Animationduration about 2.5 seconds + // Remove particle after the animation + setTimeout(() => particle.remove(), 3000); } } -// automaticly start fireworks -function startFireworks() { - fireworksInterval = setInterval(() => { - const randomCount = Math.random() * 3 + 2; // 2 to 5 fireworks simultaneously - for (let i = 0; i < randomCount; i++) { - launchFirework(); - } - }, 1800) // firework every 600 mil second +// Function for the firework with trail +function launchFirework() { + const fireworkContainer = document.querySelector('.fireworks'); + if (!fireworkContainer) return; + + // Random horizontal position + const x = Math.random() * window.innerWidth; // Any value across the entire width + + // Trail starts at the bottom and ends at a random height around the middle + let startY, endY; + if (scrollFireworks) { + // Y-position considers scrolling + startY = window.scrollY + window.innerHeight; // Bottom edge of the window plus the scroll offset + endY = Math.random() * window.innerHeight * 0.5 + window.innerHeight * 0.2 + window.scrollY; // Area around the middle, but also with scrolling + } else { + startY = window.innerHeight; // Bottom edge of the window + endY = Math.random() * window.innerHeight * 0.5 + window.innerHeight * 0.2; // Area around the middle + } + + // Create trail + createRocketTrail(x, startY, endY); + + // Create explosion + setTimeout(() => { + createExplosion(x, endY); // Explosion at the end height + }, 1000); // or 1200 } -// initialize snowflakes and add random snowflakes after the DOM is loaded +// Start the firework routine +function startFireworks() { + fireworksInterval = setInterval(() => { + const randomCount = Math.floor(Math.random() * maxFireworks) + minFireworks; + for (let i = 0; i < randomCount; i++) { + setTimeout(() => { + launchFirework(); + }, i * 200); // 200ms delay between fireworks + } + }, intervalOfFireworks); // Interval between fireworks +} + +// Initialize fireworks and add random fireworks after the DOM is loaded document.addEventListener('DOMContentLoaded', () => { if (!fireworks) return; // exit if fireworks are disabled startFireworks(); -}); \ No newline at end of file + toggleFirework(); +}); diff --git a/test-site.html b/test-site.html new file mode 100644 index 0000000..50347a4 --- /dev/null +++ b/test-site.html @@ -0,0 +1,21 @@ + + +
+ + +