// Variant 1 — Convergence // 분리된 3개 워크스페이스 카드(Web/Security/Marketing)가 wave와 함께 // 중앙으로 모여 WAVEPIX 로고로 통합. 마지막 정적 슬로건. function ServiceCard({ title, korTitle, subtitle, icon, color, accent, lines, miniContent }) { return (
{icon}
{title}
{korTitle}
{miniContent}
); } function MiniLog({ items, color }) { return (
{items.map((it, i) => (
{it.t} {it.m}
))}
); } function MiniLine({ color }) { return ( ); } function Variant1() { const time = useTime(); const T = time; // Phase windows // 0.0–1.0 intro fade // 1.0–5.5 3 cards drift apart, scrolling content (separated) // 5.5–8.5 cards converge to center // 8.5–11.5 logo emerges, slogan // 11.5–15 hold logo + outgoing wave (loop bridge) // Card positions: starts spread out (wide), converges to center stack const sepStart = 1.0; const sepEnd = 5.5; const convStart = 5.5; const convEnd = 8.2; // separation progress: 0..1 over [sepStart, sepEnd] const sep = clamp((T - sepStart) / (sepEnd - sepStart), 0, 1); const sepEased = Easing.easeOutCubic(sep); // convergence: 0..1 over [convStart, convEnd] const conv = clamp((T - convStart) / (convEnd - convStart), 0, 1); const convE = Easing.easeInOutCubic(conv); // Combined offset: each card has a separated x and a converged center // At sep=1 conv=0 → spread; at conv=1 → all at center, scaled down + faded const cards = [ { title: 'WEB', korTitle: '홈페이지 관리', color: WP.blue600, accent: `linear-gradient(90deg, ${WP.blue600}, ${WP.cyan500})`, icon: , baseX: 200, targetX: 780, baseY: 380, targetY: 400, miniContent: ( <>
), }, { title: 'SECURITY', korTitle: 'AI 보안 관제', color: WP.navy700, accent: `linear-gradient(90deg, ${WP.navy700}, ${WP.blue500})`, icon: , baseX: 780, targetX: 780, baseY: 380, targetY: 400, miniContent: ( ), }, { title: 'MARKETING', korTitle: '마케팅 AI', color: WP.orange500, accent: `linear-gradient(90deg, ${WP.orange500}, ${WP.orange400})`, icon: , baseX: 1360, targetX: 780, baseY: 380, targetY: 400, miniContent: ( <>
이번 주 노출
+38%
), }, ]; // Spread amounts (px). At sep=1: spread fully. As conv ramps, all → center. // Use additive: separated_position * (1 - conv) + target * conv // But we also want a "settling" feel: cards begin already in roughly final spread // Logo phase const logoStart = 8.0; const logoEnd = 11.5; const logoP = clamp((T - logoStart) / (logoEnd - logoStart), 0, 1); const logoE = Easing.easeOutCubic(logoP); // Slogan phase const sloganStart = 9.5; const sloganP = clamp((T - sloganStart) / 1.5, 0, 1); const sloganE = Easing.easeOutCubic(sloganP); // Hold/loop fade (last 1.5s fade signature wave again to bridge) const outroStart = 13.5; const outroP = clamp((T - outroStart) / 1.5, 0, 1); // Background: starts soft white, after convergence transitions to navy gradient const bgT = clamp((T - convStart - 0.6) / 2.0, 0, 1); const bgE = Easing.easeInOutCubic(bgT); // Wave intensity ramps up at convergence const waveAmp = clamp((T - 4.5) / 2.5, 0, 1) * (1 - clamp((T - 12.5) / 1.5, 0, 0.7)); return (
{/* Light background base */}
{/* Navy gradient overlay (fades in at convergence) */}
{/* Dot grid (more visible on dark) */}
0.5 ? WP.white : WP.ink900} spacing={40}/>
{/* Wave layer behind cards */}
0.5 ? WP.cyan500 : WP.blue400}/>
{/* Convergence flash - signature wave sweeps across at conv moment */} {T > 5.3 && T < 7.5 && (
)} {/* Top label fade out */}
분리된 디지털 업무
홈페이지 · 보안 · 마케팅
{/* Cards */} {cards.map((card, i) => { // separated position const sepX = card.baseX + (card.targetX === 780 && i !== 1 ? 0 : 0); // We define spread offset const spreadOffsets = [-560, 0, 560]; const xSpread = 960 + spreadOffsets[i] * sepEased; const ySpread = 460 + Math.sin(T * 0.5 + i) * 4 * sepEased; // converged final const finalX = 960; const finalY = 460; // mix const x = xSpread * (1 - convE) + finalX * convE; const y = ySpread * (1 - convE) + finalY * convE; // scale & opacity during convergence: shrink & fade as they merge const scale = 1 * (1 - convE * 0.6); const opacity = sep * (1 - logoE); // entry stagger const stagger = i * 0.18; const entry = clamp((T - sepStart - stagger) / 0.6, 0, 1); const entryE = Easing.easeOutCubic(entry); const entryY = (1 - entryE) * 30; const entryOp = entry; return (
); })} {/* Convergence pulse (radial flash at center) */} {T > 6.8 && T < 9.0 && (
)} {/* WAVEPIX logo + slogan */}
WAVEPIX
{/* Slogan */}
AI로 중심을 잡고, 한발 앞서갑니다.
홈페이지 관리 · AI 보안 관제 · 마케팅 AI — 하나의 파트너로
{/* Sub-marker dot row */}
{[ { c: WP.blue400, l: 'WEB' }, { c: WP.cyan500, l: 'SECURITY' }, { c: WP.orange500, l: 'MARKETING' }, ].map((it, i) => (
{it.l}
))}
{/* Loop bridge — outgoing signature wave matching intro */} {T > 13.0 && (
)}
); } window.Variant1 = Variant1;