// ===== demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx ===== // before-after-slider-scrub —— 前后对比拉杆 // FakeDashboard 两版叠放:before = 低对比灰蒙版("处理前"),after = 正常清晰版。 // 竖分割杆带圆手柄:从左端 8% 快甩到 70%(overshoot 至 76% 回弹), // 再慢速回扫到 40% 停住。杆经过处 after 揭出(clip-path inset 跟随杆 x)。 // 先快甩后慢扫速度对比是节奏关键。f=110 后全静止(40f)。 import React from 'react'; import { useCurrentFrame, interpolate, Easing } from 'remotion'; import { G, FakeDashboard } from '../../_fixtures/Fixtures'; const CL = { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } as const; // 时间轴(杆位置以画面宽度百分比表示) const T0 = 14; // 前 14f 初始静置,杆停在 8% const FLING = 26; // 快甩:14→26(12f 冲到 76%) const BOUNCE = 38; // 回弹:26→38 落到 70% const HOLD = 56; // 停顿看清 const SCRUB = 104; // 慢扫:56→104(48f 回到 40%)——速度约为快甩的 1/5 const posAt = (f: number): number => { if (f < FLING) return interpolate(f, [T0, FLING], [8, 76], { easing: Easing.out(Easing.cubic), ...CL }); if (f < BOUNCE) return interpolate(f, [FLING, BOUNCE], [76, 70], { easing: Easing.inOut(Easing.cubic), ...CL }); if (f < HOLD) return 70; return interpolate(f, [HOLD, SCRUB], [70, 40], { easing: Easing.inOut(Easing.quad), ...CL }); }; export const BeforeAfterSliderScrub: React.FC = () => { const frame = useCurrentFrame(); const p = posAt(frame); // 杆位置 % const x = (p / 100) * 1920; // 手柄挤压:速度差分驱动(快甩期手柄微拉伸,静止归 1) const v = Math.abs(posAt(frame) - posAt(frame - 1)); // %/frame const squish = 1 + Math.min(v / 8, 1) * 0.18; return (
{/* before:低对比灰蒙版模拟"处理前" */}
{/* after:正常清晰版,杆左侧揭出 */}
{/* 分割杆 + 圆手柄 */}
{/* 左右箭头示意(灰阶三角) */}
{/* 角标:BEFORE / AFTER 灰块标签 */}
{Array.from({ length: 5 }).map((_, i) => (
))}
{Array.from({ length: 5 }).map((_, i) => (
))}
); };