| 1 | <!DOCTYPE html> |
| 2 | <html lang="en" data-theme="aurora"> |
| 3 | <head> |
| 4 | <meta charset="utf-8"><title>Animation + FX Showcase — html-ppt</title> |
| 5 | <link rel="stylesheet" href="../assets/fonts.css"> |
| 6 | <link rel="stylesheet" href="../assets/base.css"> |
| 7 | <link rel="stylesheet" id="theme-link" href="../assets/themes/aurora.css"> |
| 8 | <link rel="stylesheet" href="../assets/animations/animations.css"> |
| 9 | <style> |
| 10 | .fx-stage{ |
| 11 | position:relative; |
| 12 | margin:20px auto 0; |
| 13 | width:min(900px, 92%); |
| 14 | height:380px; |
| 15 | border-radius:var(--radius-lg, 16px); |
| 16 | background:rgba(10,12,22,0.55); |
| 17 | border:1px solid var(--border,#2a2a3a); |
| 18 | box-shadow:var(--shadow-lg, 0 20px 60px rgba(0,0,0,.4)); |
| 19 | overflow:hidden; |
| 20 | } |
| 21 | .fx-label{ |
| 22 | position:absolute;top:14px;left:16px;z-index:5; |
| 23 | font-family:var(--font-mono, ui-monospace,Menlo,monospace); |
| 24 | font-size:11px;letter-spacing:.14em;color:var(--text-3,#a0a0b8); |
| 25 | text-transform:uppercase; |
| 26 | background:rgba(0,0,0,0.35);padding:4px 10px;border-radius:999px; |
| 27 | border:1px solid rgba(255,255,255,0.08); |
| 28 | } |
| 29 | .fx-replay{ |
| 30 | position:absolute;top:12px;right:14px;z-index:5; |
| 31 | appearance:none;cursor:pointer; |
| 32 | padding:7px 14px;border-radius:999px; |
| 33 | background:linear-gradient(135deg, var(--accent,#7c5cff), var(--accent-2,#22d3ee)); |
| 34 | color:#fff;font:600 12px system-ui,sans-serif; |
| 35 | border:0;letter-spacing:.05em; |
| 36 | box-shadow:0 4px 16px rgba(124,92,255,0.35); |
| 37 | } |
| 38 | .fx-replay:hover{ filter:brightness(1.1); transform:translateY(-1px); } |
| 39 | .fx-indicator{position:absolute;top:24px;right:40px;font-family:var(--font-mono);font-size:11px;color:var(--text-3);letter-spacing:.1em} |
| 40 | .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)} |
| 41 | </style> |
| 42 | </head> |
| 43 | <body> |
| 44 | <div class="deck"></div> |
| 45 | |
| 46 | <script> |
| 47 | const FX = [ |
| 48 | ['particle-burst', 'Particles explode from center, gravity + fade, re-bursts every ~2.5s.'], |
| 49 | ['confetti-cannon', 'Colored rotating rects arcing from both bottom corners.'], |
| 50 | ['firework', 'Rockets launch from the bottom and burst into colored sparks.'], |
| 51 | ['starfield', '3D perspective starfield — infinite flythrough.'], |
| 52 | ['matrix-rain', 'Classic green katakana + hex columns raining down.'], |
| 53 | ['knowledge-graph', 'Force-directed graph, 28 labeled nodes, live physics + springs.'], |
| 54 | ['neural-net', '4-6-6-3 feedforward net with pulses traveling along edges.'], |
| 55 | ['constellation', 'Drifting points connect when close — ambient background.'], |
| 56 | ['orbit-ring', '5 concentric rings with dots rotating at different speeds.'], |
| 57 | ['galaxy-swirl', 'Logarithmic spiral with ~800 particles.'], |
| 58 | ['word-cascade', 'Words fall from top and pile up at the bottom.'], |
| 59 | ['letter-explode', 'Letters fly in from random directions, loops.'], |
| 60 | ['chain-react', 'Row of 8 circles — a wave pulse dominoes across them.'], |
| 61 | ['magnetic-field', 'Particles follow sine curves leaving gradient trails.'], |
| 62 | ['data-stream', 'Rows of scrolling hex/binary text, cyberpunk feel.'], |
| 63 | ['gradient-blob', '4 drifting blurred radial gradients (additive blending).'], |
| 64 | ['sparkle-trail', 'Sparkles emit at your cursor (auto-wiggles if idle).'], |
| 65 | ['shockwave', 'Expanding rings emanating from center, looping.'], |
| 66 | ['typewriter-multi', 'Three lines typing concurrently with blinking block cursors.'], |
| 67 | ['counter-explosion', 'Number counts 0 → 2400, bursts particles, resets.'] |
| 68 | ]; |
| 69 | |
| 70 | const CSS_ANIMS = [ |
| 71 | ['fade-up','Translate from +32 px, fade.'], |
| 72 | ['fade-down','Translate from -32 px, fade.'], |
| 73 | ['fade-left','From left.'], |
| 74 | ['fade-right','From right.'], |
| 75 | ['rise-in','Rise + blur-off.'], |
| 76 | ['drop-in','Drop from above.'], |
| 77 | ['zoom-pop','Elastic scale pop.'], |
| 78 | ['blur-in','Blur clears.'], |
| 79 | ['glitch-in','Glitch jitter.'], |
| 80 | ['typewriter','Typewriter reveal.'], |
| 81 | ['neon-glow','Neon pulse.'], |
| 82 | ['shimmer-sweep','Sheen sweep.'], |
| 83 | ['gradient-flow','Gradient flow.'], |
| 84 | ['stagger-list','Staggered children.'], |
| 85 | ['counter-up','Number tick.'], |
| 86 | ['path-draw','SVG strokes draw.'], |
| 87 | ['parallax-tilt','3D hover tilt.'], |
| 88 | ['card-flip-3d','Y-axis flip.'], |
| 89 | ['cube-rotate-3d','Cube rotate.'], |
| 90 | ['page-turn-3d','Page turn.'], |
| 91 | ['perspective-zoom','Pull from -400 Z.'], |
| 92 | ['marquee-scroll','Infinite marquee.'], |
| 93 | ['kenburns','Ken Burns zoom.'], |
| 94 | ['confetti-burst','Pseudo confetti.'], |
| 95 | ['spotlight','Circular clip reveal.'], |
| 96 | ['morph-shape','SVG d morph.'], |
| 97 | ['ripple-reveal','Corner ripple.'] |
| 98 | ]; |
| 99 | |
| 100 | const deck = document.querySelector('.deck'); |
| 101 | const total = FX.length + CSS_ANIMS.length; |
| 102 | |
| 103 | // Build FX slides (1..20) |
| 104 | FX.forEach((f, i) => { |
| 105 | const idx = i + 1; |
| 106 | const [name, desc] = f; |
| 107 | const sec = document.createElement('section'); |
| 108 | sec.className = 'slide'; |
| 109 | sec.setAttribute('data-title', 'fx / ' + name); |
| 110 | |
| 111 | const extraAttrs = name === 'letter-explode' |
| 112 | ? 'data-fx-text-value="' + name.toUpperCase() + '"' |
| 113 | : name === 'counter-explosion' |
| 114 | ? 'data-fx-to="2400"' |
| 115 | : name === 'typewriter-multi' |
| 116 | ? 'data-fx-line1="> initializing knowledge graph..." data-fx-line2="> loading 28 concept nodes" data-fx-line3="> agent ready. awaiting prompt_"' |
| 117 | : ''; |
| 118 | |
| 119 | sec.innerHTML = ` |
| 120 | <span class="fx-indicator">${idx}/${total}</span> |
| 121 | <p class="kicker">FX · canvas · ${String(idx).padStart(2,'0')}</p> |
| 122 | <h1 class="h1"><span class="gradient-text">${name}</span></h1> |
| 123 | <p class="lede">${desc}</p> |
| 124 | <div class="fx-stage"> |
| 125 | <span class="fx-label">data-fx="${name}"</span> |
| 126 | <button class="fx-replay" type="button">Replay</button> |
| 127 | <div class="fx-host" style="position:absolute;inset:0;" data-fx="${name}" ${extraAttrs}></div> |
| 128 | </div> |
| 129 | <div class="deck-footer"><span class="dim2">Press → for next slide</span><span class="slide-number" data-current="${idx}" data-total="${total}"></span></div> |
| 130 | `; |
| 131 | deck.appendChild(sec); |
| 132 | |
| 133 | // Wire Replay button |
| 134 | sec.querySelector('.fx-replay').addEventListener('click', () => { |
| 135 | const host = sec.querySelector('.fx-host'); |
| 136 | const name2 = host.getAttribute('data-fx'); |
| 137 | const attrs = {}; |
| 138 | for (const a of host.attributes) attrs[a.name] = a.value; |
| 139 | const parent = host.parentNode; |
| 140 | // stop existing |
| 141 | if (window.__hpxActive && window.__hpxActive.has(host)){ |
| 142 | try{ window.__hpxActive.get(host).stop(); }catch(e){} |
| 143 | window.__hpxActive.delete(host); |
| 144 | } |
| 145 | const fresh = document.createElement('div'); |
| 146 | for (const k in attrs) fresh.setAttribute(k, attrs[k]); |
| 147 | fresh.style.cssText = host.style.cssText; |
| 148 | parent.replaceChild(fresh, host); |
| 149 | if (window.__hpxReinit) window.__hpxReinit(sec); |
| 150 | }); |
| 151 | }); |
| 152 | |
| 153 | // Build CSS animation slides (legacy, kept for completeness) |
| 154 | CSS_ANIMS.forEach((a, i) => { |
| 155 | const idx = FX.length + i + 1; |
| 156 | const sec = document.createElement('section'); |
| 157 | sec.className = 'slide'; |
| 158 | sec.setAttribute('data-title', a[0]); |
| 159 | sec.innerHTML = ` |
| 160 | <span class="fx-indicator">${idx}/${total}</span> |
| 161 | <p class="kicker">CSS anim · ${String(idx).padStart(2,'0')}</p> |
| 162 | <h1 class="h1"><span class="gradient-text">${a[0]}</span></h1> |
| 163 | <p class="lede">${a[1]}</p> |
| 164 | <div class="anim-box anim-${a[0]}" data-anim="${a[0]}" data-anim-target>${a[0]}</div> |
| 165 | <div class="deck-footer"><span class="dim2">Press A to cycle</span><span class="slide-number" data-current="${idx}" data-total="${total}"></span></div> |
| 166 | `; |
| 167 | deck.appendChild(sec); |
| 168 | }); |
| 169 | </script> |
| 170 | <script src="../assets/runtime.js"></script> |
| 171 | <script src="../assets/animations/fx-runtime.js"></script> |
| 172 | </body></html> |
| 173 |