// ===== demos/camera/crash-zoom-punch/CrashImpactReal.tsx ===== // crash-impact 急推撞停——同 crash-zoom 的急推,到位瞬间不回弹而是 // 撞停震屏:高频抖 + 指数衰减 6f,然后真静止。对比点:重量感 vs 弹性感。 import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion'; import { CameraMotionBlur } from '@remotion/motion-blur'; import layout from '../../_textures/live-layout.json'; export const CRASHIMPACT_DUR = 120; const TARGET = { cx: 960, cy: 772 }; const VIEW_Y = 180; const HIT = 46; const Scene: React.FC = () => { const frame = useCurrentFrame(); const zoom = interpolate(frame, [40, HIT], [1, 2.5], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.bezier(0.55, 0, 0.7, 1), }); const cx = interpolate(frame, [40, HIT], [960, TARGET.cx], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad), }); const cy = interpolate(frame, [40, HIT], [VIEW_Y + 540, TARGET.cy], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad), }); // 撞停震屏:amp 14px 指数衰减 ~6f 收干(可感幅度,参考轮 #2 可感档) const since = frame - HIT; const env = since >= 0 ? 14 * Math.exp(-since / 1.8) : 0; const sx = env * Math.sin(since * 3.3); const sy = env * 0.7 * Math.sin(since * 4.1 + 0.9); return ( ); }; export const CrashImpactReal: React.FC = () => { const frame = useCurrentFrame(); // blur 只包急推段;撞停震屏段保持清晰抖动 return frame >= 38 && frame <= HIT ? ( ) : ( ); }; // ===== demos/camera/crash-zoom-punch/CrashZoomReal.tsx ===== // crash-zoom 急推——真实 projects 页全景一拍推到 card4(高清纹理槽位)。 // 节拍:0–40 全景 hold → 40–46 急推 6f(ease-in,峰值放大 2.6x)→ // 46–51 过冲回弹(2.6→2.45)→ 51–120 特写 hold 真静止。 // blur 只包 40–46 急推段(轮 A 规律:极速段 samples 20)。 import { AbsoluteFill, Img, interpolate, staticFile, useCurrentFrame, Easing } from 'remotion'; import { CameraMotionBlur } from '@remotion/motion-blur'; import layout from '../../_textures/live-layout.json'; export const CRASHZOOM_DUR = 120; // card4 中心(页面空间):x=781+357/2≈960, y=616+312/2=772 const TARGET = { cx: 960, cy: 772 }; const VIEW_Y = 180; // 全景观察窗顶(页面 y) const Scene: React.FC = () => { const frame = useCurrentFrame(); const zoom = interpolate(frame, [40, 46, 51], [1, 2.6, 2.45], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.bezier(0.55, 0, 0.7, 1), }); const cx = interpolate(frame, [40, 46], [960, TARGET.cx], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad), }); const cy = interpolate(frame, [40, 46], [VIEW_Y + 540, TARGET.cy], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.in(Easing.quad), }); return ( {/* 高清目标卡覆盖原位,放大后文字仍锐(Q2) */} ); }; export const CrashZoomReal: React.FC = () => { const frame = useCurrentFrame(); return frame >= 38 && frame <= 48 ? ( ) : ( ); };