firework / index.html
BHW's picture
煙火爆炸範圍很好,但可以在目前現有範圍作為最小值,與在擴大一些之間的範圍做隨機 - Initial Deployment
8c164a6 verified
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全螢幕煙火按鈕</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* 煙火粒子樣式 */
.firework-particle {
position: absolute;
width: 6px;
height: 6px;
border-radius: 50%;
pointer-events: none;
animation: fadeOut 1s forwards;
}
/* 煙火爆炸動畫 */
@keyframes fadeOut {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0.5);
}
}
/* 按鈕懸浮效果 */
.magic-button:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(255, 215, 0, 0.3);
}
.magic-button:active {
transform: translateY(1px);
}
/* 按鈕閃爍效果 */
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.7);
}
70% {
box-shadow: 0 0 0 10px rgba(255, 215, 0, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(255, 215, 0, 0);
}
}
.pulse {
animation: pulse 2s infinite;
}
</style>
</head>
<body class="bg-gray-900 min-h-screen flex items-center justify-center p-4">
<div class="text-center">
<h1 class="text-4xl font-bold text-yellow-400 mb-8">煙火慶典</h1>
<p class="text-gray-300 mb-12 max-w-md mx-auto">按下下方按鈕,觸發全螢幕煙火秀!</p>
<button id="fireworkButton" class="magic-button pulse relative overflow-hidden bg-gradient-to-r from-yellow-500 to-orange-500 text-white font-bold py-4 px-8 rounded-full text-lg shadow-lg transition-all duration-300 transform hover:scale-105">
<span class="relative z-10">點燃煙火 🎆</span>
<span class="absolute inset-0 bg-white opacity-0 group-hover:opacity-10 transition-opacity duration-300"></span>
</button>
<div class="mt-8 text-gray-400 text-sm">
<p>可以多次點擊按鈕創造更多煙火效果</p>
</div>
</div>
<script>
document.getElementById('fireworkButton').addEventListener('click', function(e) {
// 按鈕點擊效果
this.classList.add('animate-ping');
setTimeout(() => {
this.classList.remove('animate-ping');
}, 300);
// 從按鈕位置發射煙火到隨機高處位置
const startX = window.innerWidth / 2;
const startY = window.innerHeight;
const endX = startX + (Math.random() * 400 - 200);
const endY = Math.random() * window.innerHeight * 0.3;
createLaunchTrail(startX, startY, endX, endY);
// 隨機發射更多煙火
for(let i = 0; i < 2; i++) {
setTimeout(() => {
const startX = window.innerWidth / 2 + (Math.random() * 100 - 50);
const startY = window.innerHeight;
const endX = startX + (Math.random() * 400 - 200);
const endY = Math.random() * window.innerHeight * 0.3;
createLaunchTrail(startX, startY, endX, endY);
}, Math.random() * 500);
}
});
function createFirework(x, y) {
// 創建爆炸中心
const explosion = document.createElement('div');
explosion.style.left = x + 'px';
explosion.style.top = y + 'px';
explosion.style.position = 'fixed';
explosion.style.width = '10px';
explosion.style.height = '10px';
explosion.style.borderRadius = '50%';
explosion.style.backgroundColor = getRandomColor();
explosion.style.transform = 'scale(0)';
explosion.style.transition = 'transform 0.5s ease-out';
document.body.appendChild(explosion);
// 觸發爆炸動畫
setTimeout(() => {
explosion.style.transform = 'scale(1)';
explosion.style.opacity = '0';
// 創建粒子
createParticles(x, y);
// 移除爆炸中心
setTimeout(() => {
explosion.remove();
}, 500);
}, 10);
}
function createLaunchTrail(startX, startY, endX, endY) {
const trail = document.createElement('div');
trail.style.position = 'fixed';
trail.style.left = startX + 'px';
trail.style.top = startY + 'px';
trail.style.width = '4px';
trail.style.height = '4px';
trail.style.borderRadius = '50%';
trail.style.backgroundColor = '#FFD700';
trail.style.boxShadow = '0 0 6px 2px rgba(255, 215, 0, 0.7)';
document.body.appendChild(trail);
const duration = 1500;
const startTime = Date.now();
const animateTrail = () => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentX = startX + (endX - startX) * progress;
const currentY = startY + (endY - startY) * progress;
trail.style.left = currentX + 'px';
trail.style.top = currentY + 'px';
if (progress < 1) {
requestAnimationFrame(animateTrail);
} else {
trail.remove();
createParticles(endX, endY);
}
};
requestAnimationFrame(animateTrail);
}
function createParticles(x, y) {
const particleCount = 100; // 增加粒子數量讓爆炸更密集
for(let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.className = 'firework-particle';
particle.style.backgroundColor = getRandomColor();
// 設置初始位置
particle.style.left = x + 'px';
particle.style.top = y + 'px';
// 真正的球形爆炸效果
const angle = Math.random() * Math.PI * 2;
// 使用平方根讓粒子分布更均勻
const radius = Math.sqrt(Math.random()) * (100 + Math.random() * 200); // Random radius between 100-300
const speed = 0.5 + Math.random() * 2;
// 初始位置在圓周上
const initialX = Math.cos(angle) * radius;
const initialY = Math.sin(angle) * radius;
const velocity = {
x: Math.cos(angle) * speed,
y: Math.sin(angle) * speed
};
// 設置初始位置在圓周上
// Start particles small and grow them
const size = 2 + Math.random() * 10; // Slightly larger random particle size
particle.style.width = '0px';
particle.style.height = '0px';
particle.style.left = x + 'px';
particle.style.top = y + 'px';
particle.style.opacity = '0';
particle.style.transition = 'all 0.3s ease-out';
// Stagger the appearance of particles
setTimeout(() => {
particle.style.left = (x + initialX) + 'px';
particle.style.top = (y + initialY) + 'px';
particle.style.width = size + 'px';
particle.style.height = size + 'px';
particle.style.opacity = '1';
}, Math.random() * 300);
// Random animation duration
const duration = 1.5 + Math.random() * 1.5;
particle.style.animationDuration = duration + 's';
document.body.appendChild(particle);
// 粒子移動動畫
let posX = x + initialX;
let posY = y + initialY;
let opacity = 1;
let scale = 1;
const animateParticle = () => {
posX += velocity.x;
// 增加空氣阻力和重力效果
// 更自然的阻力效果
velocity.x *= 0.95;
velocity.y *= 0.95;
velocity.y += 0.05; // 較小的重力
opacity -= 0.015;
scale -= 0.005;
particle.style.left = posX + 'px';
particle.style.top = posY + 'px';
particle.style.opacity = opacity;
particle.style.transform = `scale(${scale})`;
if(opacity > 0) {
requestAnimationFrame(animateParticle);
} else {
particle.remove();
}
};
requestAnimationFrame(animateParticle);
}
}
function getRandomColor() {
const colors = [
'#FF5252', '#FF4081', '#E040FB', '#7C4DFF',
'#536DFE', '#448AFF', '#40C4FF', '#18FFFF',
'#64FFDA', '#69F0AE', '#B2FF59', '#EEFF41',
'#FFFF00', '#FFD740', '#FFAB40', '#FF6E40'
];
return colors[Math.floor(Math.random() * colors.length)];
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=BHW/firework" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>