173 lines
7.5 KiB
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>
|