// theme-sweep-toggle —— 深浅模式扫场
// 同一 dashboard 深浅两版叠放(深版手工映射 G 色板),上层深版用 clip-path
// polygon 15° 斜边从左上扫到右下(先快后缓),边界带 2px 亮线;
// 扫完深版整体 scale 0.995→1 "坐实"。f=70 后全静止(70f)。
import React from 'react';
import { useCurrentFrame, interpolate, Easing } from 'remotion';
const CL = { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' } as const;
// 浅色板 = Fixtures G;深色板手工反转映射
type Pal = {
bg: string; panel: string; line: string; bar: string;
mid: string; card: string; border: string; side: string; sideBar: string;
};
const LIGHT: Pal = {
bg: '#ececea', panel: '#f7f7f6', line: '#dcdcda', bar: '#c2c2c0',
mid: '#8f8f8d', card: '#ffffff', border: '#d8d8d6', side: '#3a3a3a', sideBar: '#5a5a58',
};
const DARK: Pal = {
bg: '#1c1c1b', panel: '#242423', line: '#3a3a38', bar: '#6e6e6c',
mid: '#8f8f8d', card: '#2c2c2b', border: '#454543', side: '#0f0f0e', sideBar: '#6a6a68',
};
// 带色板参数的 dashboard(结构同 Fixtures.FakeDashboard variant A)
const Dash: React.FC<{ p: Pal }> = ({ p }) => (
{Array.from({ length: 7 }).map((_, i) => (
))}
{Array.from({ length: 6 }).map((_, i) => {
const titleW = 45 + (((i + 1) * 37) % 40);
const lines = 2 + ((i + 1) % 3);
return (
{Array.from({ length: lines }).map((_, j) => (
))}
);
})}
);
// 时间轴
const SWEEP0 = 14; // 扫场开始(前 14f 初始静置)
const SWEEP1 = 52; // 扫场结束
const SETTLE0 = 52;
const SETTLE1 = 64; // 坐实结束 → 之后全静止
const SLANT = 1080 * Math.tan((15 * Math.PI) / 180); // ≈ 289px,15° 斜边
export const ThemeSweepToggle: React.FC = () => {
const frame = useCurrentFrame();
// 边界顶端 x:先快后缓(poly(3) out);从左外扫到右外+SLANT 保证底边也扫尽
const p = interpolate(frame, [SWEEP0, SWEEP1], [-20, 1920 + SLANT + 40], {
easing: Easing.out(Easing.poly(3)),
...CL,
});
// 坐实:0.995 → 1
const settle = interpolate(frame, [SETTLE0, SETTLE0 + 1, SETTLE1], [1, 0.995, 1], {
easing: Easing.out(Easing.cubic),
...CL,
});
// 亮线透明度:扫场期间可见,扫完 6f 内淡出
const lineOp = interpolate(frame, [SWEEP0, SWEEP0 + 4, SWEEP1 - 4, SWEEP1 + 2], [0, 1, 1, 0], CL);
const sweeping = frame >= SWEEP0 && frame < SWEEP1 + 2;
return (
{/* 底层浅色版 */}
{/* 上层深色版,clip-path 斜切揭出 */}
{/* 2px 亮线边界(条件卸载) */}
{sweeping && (
)}
);
};