htmlewislulu-html-ppt-skill/templates/animation-showcase.html

173 lines
7.5 KiB
HTML

<!DOCTYPE html>
<html lang="en" data-theme="aurora">
<head>
<meta charset="utf-8"><title>Animation + FX Showcase — html-ppt</title>
<link rel="stylesheet" href="../assets/fonts.css">
<link rel="stylesheet" href="../assets/base.css">
<link rel="stylesheet" id="theme-link" href="../assets/themes/aurora.css">
<link rel="stylesheet" href="../assets/animations/animations.css">
<style>
.fx-stage{
position:relative;
margin:20px auto 0;
width:min(900px, 92%);
height:380px;
border-radius:var(--radius-lg, 16px);
background:rgba(10,12,22,0.55);
border:1px solid var(--border,#2a2a3a);
box-shadow:var(--shadow-lg, 0 20px 60px rgba(0,0,0,.4));
overflow:hidden;
}
.fx-label{
position:absolute;top:14px;left:16px;z-index:5;
font-family:var(--font-mono, ui-monospace,Menlo,monospace);
font-size:11px;letter-spacing:.14em;color:var(--text-3,#a0a0b8);
text-transform:uppercase;
background:rgba(0,0,0,0.35);padding:4px 10px;border-radius:999px;
border:1px solid rgba(255,255,255,0.08);
}
.fx-replay{
position:absolute;top:12px;right:14px;z-index:5;
appearance:none;cursor:pointer;
padding:7px 14px;border-radius:999px;
background:linear-gradient(135deg, var(--accent,#7c5cff), var(--accent-2,#22d3ee));
color:#fff;font:600 12px system-ui,sans-serif;
border:0;letter-spacing:.05em;
box-shadow:0 4px 16px rgba(124,92,255,0.35);
}
.fx-replay:hover{ filter:brightness(1.1); transform:translateY(-1px); }
.fx-indicator{position:absolute;top:24px;right:40px;font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.1em}
.anim-box{margin:24px auto 0;width:640px;height:240px;border-radius:var(--radius-lg);background:var(--grad-soft);display:flex;align-items:center;justify-content:center;font-size:44px;font-weight:800;color:var(--text-1);box-shadow:var(--shadow-lg);border:1px solid var(--border)}
</style>
</head>
<body>
<div class="deck"></div>
<script>
const FX = [
['particle-burst', 'Particles explode from center, gravity + fade, re-bursts every ~2.5s.'],
['confetti-cannon', 'Colored rotating rects arcing from both bottom corners.'],
['firework', 'Rockets launch from the bottom and burst into colored sparks.'],
['starfield', '3D perspective starfield — infinite flythrough.'],
['matrix-rain', 'Classic green katakana + hex columns raining down.'],
['knowledge-graph', 'Force-directed graph, 28 labeled nodes, live physics + springs.'],
['neural-net', '4-6-6-3 feedforward net with pulses traveling along edges.'],
['constellation', 'Drifting points connect when close — ambient background.'],
['orbit-ring', '5 concentric rings with dots rotating at different speeds.'],
['galaxy-swirl', 'Logarithmic spiral with ~800 particles.'],
['word-cascade', 'Words fall from top and pile up at the bottom.'],
['letter-explode', 'Letters fly in from random directions, loops.'],
['chain-react', 'Row of 8 circles — a wave pulse dominoes across them.'],
['magnetic-field', 'Particles follow sine curves leaving gradient trails.'],
['data-stream', 'Rows of scrolling hex/binary text, cyberpunk feel.'],
['gradient-blob', '4 drifting blurred radial gradients (additive blending).'],
['sparkle-trail', 'Sparkles emit at your cursor (auto-wiggles if idle).'],
['shockwave', 'Expanding rings emanating from center, looping.'],
['typewriter-multi', 'Three lines typing concurrently with blinking block cursors.'],
['counter-explosion', 'Number counts 0 → 2400, bursts particles, resets.']
];
const CSS_ANIMS = [
['fade-up','Translate from +32 px, fade.'],
['fade-down','Translate from -32 px, fade.'],
['fade-left','From left.'],
['fade-right','From right.'],
['rise-in','Rise + blur-off.'],
['drop-in','Drop from above.'],
['zoom-pop','Elastic scale pop.'],
['blur-in','Blur clears.'],
['glitch-in','Glitch jitter.'],
['typewriter','Typewriter reveal.'],
['neon-glow','Neon pulse.'],
['shimmer-sweep','Sheen sweep.'],
['gradient-flow','Gradient flow.'],
['stagger-list','Staggered children.'],
['counter-up','Number tick.'],
['path-draw','SVG strokes draw.'],
['parallax-tilt','3D hover tilt.'],
['card-flip-3d','Y-axis flip.'],
['cube-rotate-3d','Cube rotate.'],
['page-turn-3d','Page turn.'],
['perspective-zoom','Pull from -400 Z.'],
['marquee-scroll','Infinite marquee.'],
['kenburns','Ken Burns zoom.'],
['confetti-burst','Pseudo confetti.'],
['spotlight','Circular clip reveal.'],
['morph-shape','SVG d morph.'],
['ripple-reveal','Corner ripple.']
];
const deck = document.querySelector('.deck');
const total = FX.length + CSS_ANIMS.length;
// Build FX slides (1..20)
FX.forEach((f, i) => {
const idx = i + 1;
const [name, desc] = f;
const sec = document.createElement('section');
sec.className = 'slide';
sec.setAttribute('data-title', 'fx / ' + name);
const extraAttrs = name === 'letter-explode'
? 'data-fx-text-value="' + name.toUpperCase() + '"'
: name === 'counter-explosion'
? 'data-fx-to="2400"'
: name === 'typewriter-multi'
? 'data-fx-line1="> initializing knowledge graph..." data-fx-line2="> loading 28 concept nodes" data-fx-line3="> agent ready. awaiting prompt_"'
: '';
sec.innerHTML = `
<span class="fx-indicator">${idx}/${total}</span>
<p class="kicker">FX · canvas · ${String(idx).padStart(2,'0')}</p>
<h1 class="h1"><span class="gradient-text">${name}</span></h1>
<p class="lede">${desc}</p>
<div class="fx-stage">
<span class="fx-label">data-fx="${name}"</span>
<button class="fx-replay" type="button">Replay</button>
<div class="fx-host" style="position:absolute;inset:0;" data-fx="${name}" ${extraAttrs}></div>
</div>
<div class="deck-footer"><span class="dim2">Press → for next slide</span><span class="slide-number" data-current="${idx}" data-total="${total}"></span></div>
`;
deck.appendChild(sec);
// Wire Replay button
sec.querySelector('.fx-replay').addEventListener('click', () => {
const host = sec.querySelector('.fx-host');
const name2 = host.getAttribute('data-fx');
const attrs = {};
for (const a of host.attributes) attrs[a.name] = a.value;
const parent = host.parentNode;
// stop existing
if (window.__hpxActive && window.__hpxActive.has(host)){
try{ window.__hpxActive.get(host).stop(); }catch(e){}
window.__hpxActive.delete(host);
}
const fresh = document.createElement('div');
for (const k in attrs) fresh.setAttribute(k, attrs[k]);
fresh.style.cssText = host.style.cssText;
parent.replaceChild(fresh, host);
if (window.__hpxReinit) window.__hpxReinit(sec);
});
});
// Build CSS animation slides (legacy, kept for completeness)
CSS_ANIMS.forEach((a, i) => {
const idx = FX.length + i + 1;
const sec = document.createElement('section');
sec.className = 'slide';
sec.setAttribute('data-title', a[0]);
sec.innerHTML = `
<span class="fx-indicator">${idx}/${total}</span>
<p class="kicker">CSS anim · ${String(idx).padStart(2,'0')}</p>
<h1 class="h1"><span class="gradient-text">${a[0]}</span></h1>
<p class="lede">${a[1]}</p>
<div class="anim-box anim-${a[0]}" data-anim="${a[0]}" data-anim-target>${a[0]}</div>
<div class="deck-footer"><span class="dim2">Press A to cycle</span><span class="slide-number" data-current="${idx}" data-total="${total}"></span></div>
`;
deck.appendChild(sec);
});
</script>
<script src="../assets/runtime.js"></script>
<script src="../assets/animations/fx-runtime.js"></script>
</body></html>