blue-button-explode / index.html
victor's picture
victor HF Staff
Update from HuggingChat
1ebcb2e verified
Raw
History Blame Contribute Delete
9.52 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Green Button Explode</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 32px;
font-family: 'Segoe UI', system-ui, sans-serif;
background: linear-gradient(135deg, #0a1f0f 0%, #1a3d24 100%);
overflow: hidden;
cursor: default;
}
/* Screen shake animation */
@keyframes shake {
0%, 100% { transform: translate(0, 0); }
10% { transform: translate(-12px, 8px); }
20% { transform: translate(10px, -10px); }
30% { transform: translate(-8px, 6px); }
40% { transform: translate(8px, -6px); }
50% { transform: translate(-6px, -8px); }
60% { transform: translate(6px, 8px); }
70% { transform: translate(-4px, 4px); }
80% { transform: translate(4px, -4px); }
90% { transform: translate(-2px, 2px); }
}
.shake { animation: shake 0.6s ease; }
.flash {
position: fixed;
inset: 0;
background: #fff;
pointer-events: none;
opacity: 0;
z-index: 999;
}
@keyframes flashAnim {
0% { opacity: 0; }
15% { opacity: 0.7; }
100% { opacity: 0; }
}
.flash.active { animation: flashAnim 0.5s ease; }
/* Button container */
#button-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
/* The green button */
#blue-button {
padding: 28px 80px;
font-size: 32px;
font-weight: 800;
letter-spacing: 2px;
text-transform: uppercase;
color: #fff;
background: linear-gradient(180deg, #22c55e 0%, #15803d 100%);
border: none;
border-radius: 16px;
cursor: pointer;
box-shadow:
0 8px 0 #166534,
0 12px 28px rgba(22, 101, 52, 0.5),
inset 0 2px 0 rgba(255,255,255,0.3);
transition: transform 0.1s, box-shadow 0.1s, opacity 0.15s;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
user-select: none;
position: relative;
z-index: 10;
}
#blue-button:hover {
background: linear-gradient(180deg, #4ade80 0%, #16a34a 100%);
transform: translateY(-2px);
box-shadow:
0 10px 0 #166534,
0 16px 32px rgba(22, 101, 52, 0.6),
inset 0 2px 0 rgba(255,255,255,0.4);
}
#blue-button:active {
transform: translateY(4px);
box-shadow:
0 4px 0 #166534,
0 6px 16px rgba(22, 101, 52, 0.4),
inset 0 2px 0 rgba(255,255,255,0.2);
}
#blue-button.exploding {
opacity: 0;
transform: scale(1.3);
transition: opacity 0.15s, transform 0.15s;
}
/* Respawn button */
#respawn {
padding: 16px 48px;
font-size: 20px;
font-weight: 700;
color: #fff;
background: linear-gradient(180deg, #059669 0%, #047857 100%);
border: none;
border-radius: 12px;
cursor: pointer;
box-shadow: 0 6px 0 #065f46, 0 8px 20px rgba(6,95,70,0.4);
transition: transform 0.1s, box-shadow 0.1s;
display: none;
}
#respawn:hover { transform: translateY(-2px); box-shadow: 0 8px 0 #065f46, 0 10px 24px rgba(6,95,70,0.5); }
#respawn:active { transform: translateY(3px); box-shadow: 0 3px 0 #065f46, 0 5px 12px rgba(6,95,70,0.3); }
/* Particle canvas */
#particles {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
pointer-events: none;
z-index: 100;
}
.label {
color: rgba(255,255,255,0.5);
font-size: 14px;
letter-spacing: 1px;
text-transform: uppercase;
margin-top: 8px;
}
</style>
</head>
<body>
<canvas id="particles"></canvas>
<div class="flash" id="flash"></div>
<div id="button-container">
<button id="blue-button">CLICK ME</button>
</div>
<button id="respawn">RESPAWN</button>
<div class="label">Click the button to explode it</div>
<script>
const canvas = document.getElementById('particles');
const ctx = canvas.getContext('2d');
const btn = document.getElementById('blue-button');
const respawn = document.getElementById('respawn');
const flash = document.getElementById('flash');
let particles = [];
let exploded = false;
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resize();
window.addEventListener('resize', resize);
// Particle class
class Particle {
constructor(x, y, color, vx, vy, size, life) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.size = size;
this.color = color;
this.life = life;
this.maxLife = life;
this.gravity = 0.3;
this.rotation = Math.random() * Math.PI * 2;
this.rotSpeed = (Math.random() - 0.5) * 0.4;
this.shape = Math.random() > 0.4 ? 'circle' : 'square';
}
update() {
this.x += this.vx;
this.y += this.vy;
this.vy += this.gravity;
this.vx *= 0.99;
this.rotation += this.rotSpeed;
this.life--;
}
draw() {
const alpha = Math.max(0, this.life / this.maxLife);
ctx.save();
ctx.globalAlpha = alpha;
ctx.translate(this.x, this.y);
ctx.rotate(this.rotation);
ctx.fillStyle = this.color;
if (this.shape === 'circle') {
ctx.beginPath();
ctx.arc(0, 0, this.size, 0, Math.PI * 2);
ctx.fill();
} else {
ctx.fillRect(-this.size, -this.size, this.size * 2, this.size * 2);
}
// Glow
ctx.shadowBlur = 12;
ctx.shadowColor = this.color;
ctx.beginPath();
if (this.shape === 'circle') {
ctx.arc(0, 0, this.size * 0.6, 0, Math.PI * 2);
} else {
ctx.fillRect(-this.size * 0.6, -this.size * 0.6, this.size * 1.2, this.size * 1.2);
}
ctx.fill();
ctx.restore();
}
}
// Shockwave ring
class Ring {
constructor(x, y, color, maxRadius, lineWidth) {
this.x = x;
this.y = y;
this.radius = 0;
this.maxRadius = maxRadius;
this.color = color;
this.lineWidth = lineWidth;
this.life = 30;
this.maxLife = 30;
}
update() {
this.radius += (this.maxRadius - this.radius) * 0.18;
this.life--;
}
draw() {
const alpha = Math.max(0, this.life / this.maxLife);
ctx.save();
ctx.globalAlpha = alpha;
ctx.strokeStyle = this.color;
ctx.lineWidth = this.lineWidth * alpha;
ctx.shadowBlur = 20;
ctx.shadowColor = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, Math.max(0.1, this.radius), 0, Math.PI * 2);
ctx.stroke();
ctx.restore();
}
}
let rings = [];
function explode() {
if (exploded) return;
exploded = true;
const rect = btn.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
const cy = rect.top + rect.height / 2;
// Flash
flash.classList.remove('active');
void flash.offsetWidth;
flash.classList.add('active');
// Shake
document.body.classList.remove('shake');
void document.body.offsetWidth;
document.body.classList.add('shake');
// Button vanish
btn.classList.add('exploding');
// Colors — green palette
const colors = [
'#22c55e', '#15803d', '#4ade80', '#16a34a', '#86efac',
'#dcfce7', '#166534', '#6ee7b7', '#34d399', '#ffffff'
];
// Burst particles
const count = 180;
for (let i = 0; i < count; i++) {
const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5;
const speed = Math.random() * 18 + 6;
const vx = Math.cos(angle) * speed;
const vy = Math.sin(angle) * speed - Math.random() * 4;
const size = Math.random() * 8 + 3;
const color = colors[Math.floor(Math.random() * colors.length)];
const life = Math.floor(Math.random() * 40 + 50);
particles.push(new Particle(cx, cy, color, vx, vy, size, life));
}
// Extra debris (smaller, faster)
for (let i = 0; i < 60; i++) {
const angle = Math.random() * Math.PI * 2;
const speed = Math.random() * 28 + 10;
const vx = Math.cos(angle) * speed;
const vy = Math.sin(angle) * speed - Math.random() * 6;
const size = Math.random() * 4 + 1;
const color = colors[Math.floor(Math.random() * colors.length)];
const life = Math.floor(Math.random() * 30 + 40);
particles.push(new Particle(cx, cy, color, vx, vy, size, life));
}
// Shockwave rings — green
rings.push(new Ring(cx, cy, '#4ade80', 250, 8));
setTimeout(() => rings.push(new Ring(cx, cy, '#86efac', 180, 5)), 80);
setTimeout(() => rings.push(new Ring(cx, cy, '#ffffff', 120, 3)), 160);
// Sparkles
for (let i = 0; i < 30; i++) {
const angle = Math.random() * Math.PI * 2;
const speed = Math.random() * 6 + 2;
const vx = Math.cos(angle) * speed;
const vy = Math.sin(angle) * speed - Math.random() * 3;
const size = Math.random() * 3 + 2;
const color = '#ffffff';
const life = Math.floor(Math.random() * 20 + 30);
particles.push(new Particle(cx, cy, color, vx, vy, size, life));
}
// Show respawn after delay
setTimeout(() => { respawn.style.display = 'inline-block'; }, 400);
}
function respawnButton() {
exploded = false;
btn.classList.remove('exploding');
respawn.style.display = 'none';
}
// Animation loop
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Rings
rings = rings.filter(r => r.life > 0);
for (const r of rings) { r.update(); r.draw(); }
// Particles
particles = particles.filter(p => p.life > 0);
for (const p of particles) { p.update(); p.draw(); }
requestAnimationFrame(animate);
}
animate();
btn.addEventListener('click', explode);
respawn.addEventListener('click', respawnButton);
</script>
</body>
</html>