> 技术文档 > css 发射烟花的动画

css 发射烟花的动画


动画1

主要功能:
真实的发射轨迹 - 烟花从底部发射到指定位置
物理引擎效果 - 包含重力、摩擦力、缓动函数
多彩爆炸效果 - 多种颜色的粒子爆炸
渐变消失 - 粒子逐渐变淡并缩小
交互控制 - 点击、按钮控制等多种方式
技术亮点:
面向对象设计 - 使用ES6类封装烟花逻辑
高性能渲染 - 使用requestAnimationFrame优化动画
真实物理模拟 - 重力、速度、摩擦力计算
视觉效果增强 - 发光效果、缩放动画、透明度变化
响应式设计 - 适配不同屏幕尺寸
控制方式:
点击屏幕 - 在点击位置发射烟花
发射烟花按钮 - 随机位置发射
自动发射按钮 - 开启连续发射模式
停止发射按钮 - 停止自动发射
清空画面按钮 - 清除所有烟花效果
烟花效果包括发射轨迹、爆炸粒子、重力下落、渐变消失等真实物理效果,营造出高质量的视觉体验。

<!DOCTYPE html><html lang=\"zh-CN\"><head> <meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <title>高质量烟花动画</title> <style> body { margin: 0; padding: 0; background-color: #000; overflow: hidden; height: 100vh; display: flex; justify-content: center; align-items: center; font-family: Arial, sans-serif; } .fireworks-container { position: relative; width: 100%; height: 100%; } .firework { position: absolute; width: 5px; height: 5px; border-radius: 50%; pointer-events: none; } .controls { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 100; background: rgba(0, 0, 0, 0.7); padding: 15px; border-radius: 10px; color: white; text-align: center; } button { background: linear-gradient(45deg, #ff6b6b, #ffa502); border: none; color: white; padding: 10px 20px; margin: 5px; border-radius: 25px; cursor: pointer; font-weight: bold; transition: all 0.3s ease; } button:hover { transform: scale(1.05); box-shadow: 0 0 15px rgba(255, 255, 255, 0.5); } .title { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); color: white; font-size: 2em; text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #e60073, 0 0 40px #e60073; animation: glow 2s ease-in-out infinite alternate; } @keyframes glow { from { text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #e60073, 0 0 40px #e60073; } to { text-shadow: 0 0 20px #fff, 0 0 30px #ff4da6, 0 0 40px #ff4da6, 0 0 50px #ff4da6; } } </style></head><body> <div class=\"title\">🎆 高质量烟花秀 🎆</div> <div class=\"fireworks-container\" id=\"fireworksContainer\"></div> <div class=\"controls\"> <button onclick=\"launchFirework()\">发射烟花</button> <button onclick=\"startAutoLaunch()\">自动发射</button> <button onclick=\"stopAutoLaunch()\">停止发射</button> <button onclick=\"clearFireworks()\">清空画面</button> </div> <script> class Firework { constructor(container) { this.container = container; this.particles = []; this.colors = [ \'#ff0000\', \'#00ff00\', \'#0000ff\', \'#ffff00\', \'#ff00ff\', \'#00ffff\', \'#ff7700\', \'#ff0077\', \'#7700ff\', \'#00ff77\', \'#ffaa00\', \'#ff00aa\' ]; } launch(x, y) { // 创建烟花发射轨迹 const rocket = document.createElement(\'div\'); rocket.className = \'firework\'; rocket.style.left = `${x}px`; rocket.style.top = `${window.innerHeight}px`; rocket.style.backgroundColor = this.getRandomColor(); rocket.style.boxShadow = `0 0 10px ${this.getRandomColor()}`; this.container.appendChild(rocket); // 发射动画 const startTime = Date.now(); const duration = 1000 + Math.random() * 500; const targetY = y; const animateRocket = () => { const elapsed = Date.now() - startTime; const progress = Math.min(elapsed / duration, 1); // 使用缓动函数让运动更自然 const easeOutQuad = 1 - Math.pow(1 - progress, 2); const currentY = window.innerHeight - (window.innerHeight - targetY) * easeOutQuad; rocket.style.top = `${currentY}px`; rocket.style.opacity = 1 - progress * 0.5; if (progress < 1) { requestAnimationFrame(animateRocket); } else { // 发射完成,爆炸效果 this.explode(x, targetY); rocket.remove(); } }; requestAnimationFrame(animateRocket); } explode(x, y) { const particleCount = 100 + Math.floor(Math.random() * 50); for (let i = 0; i < particleCount; i++) { const particle = document.createElement(\'div\'); particle.className = \'firework\'; const angle = Math.random() * Math.PI * 2; const speed = 2 + Math.random() * 5; const size = 2 + Math.random() * 3; const color = this.getRandomColor(); particle.style.width = `${size}px`; particle.style.height = `${size}px`; particle.style.left = `${x}px`; particle.style.top = `${y}px`; particle.style.backgroundColor = color; particle.style.boxShadow = `0 0 ${size * 2}px ${color}`; this.container.appendChild(particle); // 粒子动画参数 const particleData = { element: particle, x: x, y: y, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed, gravity: 0.05, friction: 0.98, life: 1.0, decay: 0.01 + Math.random() * 0.02, size: size }; this.particles.push(particleData); } } updateParticles() { for (let i = this.particles.length - 1; i >= 0; i--) { const p = this.particles[i]; // 更新位置 p.x += p.vx; p.y += p.vy; p.vy += p.gravity; p.vx *= p.friction; p.vy *= p.friction; // 更新生命值 p.life -= p.decay; // 更新元素位置和透明度 p.element.style.left = `${p.x}px`; p.element.style.top = `${p.y}px`; p.element.style.opacity = p.life; p.element.style.transform = `scale(${p.life})`; // 移除死亡粒子 if (p.life <= 0) { p.element.remove(); this.particles.splice(i, 1); } } } getRandomColor() { return this.colors[Math.floor(Math.random() * this.colors.length)]; } clear() { this.particles.forEach(p => p.element.remove()); this.particles = []; } } // 全局变量 const container = document.getElementById(\'fireworksContainer\'); const firework = new Firework(container); let autoLaunchInterval = null; // 点击发射烟花 container.addEventListener(\'click\', (e) => { firework.launch(e.clientX, e.clientY); }); // 手动发射按钮 function launchFirework() { const x = Math.random() * window.innerWidth; const y = Math.random() * window.innerHeight * 0.6; firework.launch(x, y); } // 自动发射 function startAutoLaunch() { if (autoLaunchInterval) return; autoLaunchInterval = setInterval(() => { const x = Math.random() * window.innerWidth; const y = Math.random() * window.innerHeight * 0.6; firework.launch(x, y); }, 800); } // 停止自动发射 function stopAutoLaunch() { if (autoLaunchInterval) { clearInterval(autoLaunchInterval); autoLaunchInterval = null; } } // 清空画面 function clearFireworks() { firework.clear(); } // 粒子更新循环 function update() { firework.updateParticles(); requestAnimationFrame(update); } // 启动更新循环 update(); // 页面加载完成后开始自动发射 window.addEventListener(\'load\', () => { setTimeout(() => { startAutoLaunch(); }, 1000); }); </script></body></html>

动画2

<!DOCTYPE html><html lang=\"zh-CN\"><head> <meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <title>CSS烟花动画</title> <style> body { background-color: #000; overflow: hidden; height: 100vh; display: flex; justify-content: center; align-items: center; } .firework { position: absolute; width: 5px; height: 5px; border-radius: 50%; box-shadow: 0 0 10px 2px; animation: explode 1s ease-out forwards; opacity: 0; } @keyframes explode { 0% { transform: translate(0, 0); opacity: 1; } 100% { transform: translate(var(--tx), var(--ty)); opacity: 0; } } .launch-area { position: absolute; bottom: 20%; width: 100%; text-align: center; } .launch-btn { padding: 10px 20px; background: linear-gradient(45deg, #ff3366, #ff9933); color: white; border: none; border-radius: 30px; font-size: 16px; cursor: pointer; box-shadow: 0 0 15px rgba(255, 51, 102, 0.7); transition: all 0.3s; } .launch-btn:hover { transform: scale(1.05); box-shadow: 0 0 20px rgba(255, 51, 102, 0.9); } </style></head><body> <div class=\"launch-area\"> <button class=\"launch-btn\" onclick=\"launchFirework()\">发射烟花</button> </div> <script> function launchFirework() { const colors = [\'#ff3366\', \'#ff9933\', \'#33ccff\', \'#9933ff\', \'#33ff66\']; const fireworkCount = 50; for (let i = 0; i < fireworkCount; i++) { const firework = document.createElement(\'div\'); firework.className = \'firework\'; // 随机颜色 const color = colors[Math.floor(Math.random() * colors.length)]; firework.style.backgroundColor = color; firework.style.boxShadow = `0 0 10px 2px ${color}`; // 随机位置偏移 const angle = Math.random() * Math.PI * 2; const distance = 50 + Math.random() * 100; const tx = Math.cos(angle) * distance; const ty = Math.sin(angle) * distance; firework.style.setProperty(\'--tx\', `${tx}px`); firework.style.setProperty(\'--ty\', `${ty}px`); // 随机起始位置(在屏幕中央附近) const startX = 50 + (Math.random() - 0.5) * 20; const startY = 50 + (Math.random() - 0.5) * 20; firework.style.left = `${startX}%`; firework.style.top = `${startY}%`; // 随机动画延迟和持续时间 firework.style.animationDelay = `${Math.random() * 0.2}s`; firework.style.animationDuration = `${0.5 + Math.random() * 0.5}s`; document.body.appendChild(firework); // 动画结束后移除元素 firework.addEventListener(\'animationend\', function () { firework.remove(); }); } } </script></body></html>

免费论坛社区