// overhead-tabletop-drop|上帝视角桌面滑降
// perspective(1600px) 内三张"页面卡"rotateX(62°) 平躺成桌面卡阵。
// 0–55f 相机横向滑过(只动 translateX,缓入缓出);55–85f 骤降扎入:
// rotateX 62→0 + 世界 scale 1→2.0(2% 过冲)+ translateX -650→0 三者同跑,
// 中间卡对位落成正视满屏 dashboard。全部动画 f=93 结束,收尾真静止 52f。
// 卡片 996×560(spec 900→996,使 FakeDashboard 0.5185 缩放严丝合缝、
// 落版 16:9 精确对位),间距 140px。
import React from 'react';
import { AbsoluteFill, interpolate, useCurrentFrame, Easing } from 'remotion';
import { FakeDashboard, Card, G } from '../../_fixtures/Fixtures';
const CARD_W = 996;
const CARD_H = 560;
const GAP = 140;
const PITCH = CARD_W + GAP; // 1136
const INNER = CARD_H / 1080; // 0.5185:FakeDashboard 缩到卡内正好铺满
const PAN_END = 55;
const DROP_END = 85;
// 单张"页面卡":白底圆角卡,内容按 INNER 缩放塞满
const PageCard: React.FC<{ x: number; children: React.ReactNode }> = ({ x, children }) => (
);
export const OverheadTabletopDrop: React.FC = () => {
const f = useCurrentFrame();
// 0–55f 横滑:只动 translateX,缓入缓出
const panX = interpolate(f, [0, PAN_END], [700, -650], {
easing: Easing.inOut(Easing.cubic),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
// 55–85f 骤降:角度 / 缩放 / 位移三者同跑,out-cubic + 2% 过冲
const drop = interpolate(f, [PAN_END, DROP_END], [0, 1], {
easing: Easing.out(Easing.cubic),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
const rotX = interpolate(f, [PAN_END, DROP_END, DROP_END + 4, DROP_END + 8], [62, -1.8, 0.6, 0], {
easing: Easing.out(Easing.cubic),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
const scale = interpolate(f, [PAN_END, DROP_END, DROP_END + 7], [1, 2.04, 2.0], {
easing: Easing.out(Easing.cubic),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
const dropX = interpolate(drop, [0, 1], [panX, 0]); // drop 段把 -650 收回 0
const tx = f <= PAN_END ? panX : dropX;
return (
{/* 世界原点 = 屏心;先 in-plane scale,再 rotateX,最后 translateX */}
{/* 桌面:浅灰底 + 网格线,给横滑段提供运动参照 */}
{/* 目标页:落版满屏 */}
);
};