// ===== demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx ===== // corner-spotlight-reveal —— 对标 clickup-30.mp4 41.5–44.6s: // 黑场上,左上角径向聚光从小到大扩张,把白色 Inbox 界面逐步"点亮", // 照到的区域显影、照不到的沉黑,最终全屏亮起。光即转场。 import React from 'react'; import { AbsoluteFill, useCurrentFrame, interpolate, Easing } from 'remotion'; const FONT = '"Avenir Next", "Helvetica Neue", Helvetica, sans-serif'; // 灰阶 Inbox 界面(自绘,替代真 UI) const InboxPanel: React.FC = () => (
Inbox
All
Tasks
Docs
People
Chat
{[0, 1, 2].map((row) => (
))}
); export const CornerSpotlightReveal: React.FC = () => { const frame = useCurrentFrame(); // 聚光半径扩张:全程匀速(用户裁决"整个过程要匀速"——严格 linear,无缓动) // r+feather=1.85r 是光前沿;1.85*1300≈2400 恰在片尾盖满全屏对角, // 保证扩张动作占满全片时长而不是前 1/3 就饱和 const r = interpolate(frame, [0, 100], [160, 1300], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); // 光心沿左上角匀速游移(linear) const cx = interpolate(frame, [0, 96], [140, 420], { extrapolateRight: 'clamp' }); const cy = interpolate(frame, [0, 96], [90, 260], { extrapolateRight: 'clamp' }); // 软边宽度:扩张时边缘更羽化 const feather = r * 0.85; // UI 轻微透视漂移(原片相机贴着界面缓推) const drift = interpolate(frame, [0, 100], [0, 1]); const scale = 1.75 - 0.28 * drift; const tx = -40 + 70 * drift; const ty = -30 + 50 * drift; const mask = `radial-gradient(circle ${r + feather}px at ${cx}px ${cy}px, rgba(255,255,255,1) ${Math.max( 0, ((r - feather * 0.25) / (r + feather)) * 100, )}%, rgba(255,255,255,0) 100%)`; return ( {/* 聚光自身的白热光晕(叠在界面上方,光心最亮) */}
); }; // ===== demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx ===== // glow-wake-sleep-panel v3 —— 扫光方向改为从左向右(用户裁决): // 聚光灯从左向右"扫过"斜置面板;一条带辉光的紫色光线贴着 UI 顶边/边框/ // logo 划过,光到即亮、光走即暗,尾段沉回黑暗(右缘残留蓝紫)。 import React from 'react'; import { AbsoluteFill, useCurrentFrame, interpolate } from 'remotion'; const W = 1250; const H = 860; const R = 26; const ink = '#3a3a3a'; const mid = '#9a9a98'; const line = '#e2e2e0'; const Row: React.FC<{ w: number; icon?: boolean }> = ({ w, icon = true }) => (
{icon &&
}
); const TaskCard: React.FC<{ seed: number }> = ({ seed }) => (
); // 灰阶斜置面板(ClickUp 布局形:侧栏 + Review/Shipped 两列) const Panel: React.FC = () => (
{[0, 1].map((col) => (
{[0, 1, 2].map((i) => )}
))}
); // 贴边紫色光线(多层辉光:宽糊层+中层+亮芯),水平段,中心在 cx const EdgeStreak: React.FC<{ cx: number; y: number; len: number; opacity: number; vertical?: boolean }> = ({ cx, y, len, opacity, vertical = false }) => { const long = { position: 'absolute' as const, left: 0, top: 0, opacity }; const grad = (c: string) => vertical ? `linear-gradient(180deg, rgba(0,0,0,0) 0%, ${c} 45%, ${c} 55%, rgba(0,0,0,0) 100%)` : `linear-gradient(90deg, rgba(0,0,0,0) 0%, ${c} 45%, ${c} 55%, rgba(0,0,0,0) 100%)`; if (vertical) { return (
); } return (
{/* 粉色偏移层:截图里光带紫中带粉 */}
); }; export const GlowWakeSleepPanel: React.FC = () => { const frame = useCurrentFrame(); // 聚光沿面板顶边从左向右匀速扫过(面板本地座标) const sx = interpolate(frame, [4, 120], [-260, W + 260], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const sy = 150; // 聚光照在面板上部 // 全局明暗包络:醒 → 展示 → 睡 const env = interpolate(frame, [0, 16, 100, 130], [0, 1, 1, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); // 尾段右缘残光:最后只剩右缘一线蓝紫 const rightNear = Math.max(0, Math.min(1, (sx - (W - 420)) / 420)); const tailBlue = interpolate(frame, [100, 116, 132], [0, 0.8, 0.25], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); // logo 描光:聚光经过 logo(本地 x≈60)时点亮 const logoGlow = Math.exp(-((sx - 60) ** 2) / (2 * 230 ** 2)) * env; // 摄影机慢漂移:面板随扫光从左上往右下走(对应扫光方向) const drift = interpolate(frame, [0, 132], [-150, 150]); const driftY = interpolate(frame, [0, 132], [-36, 36]); return (
{/* 聚光环境雾光:跟随光头,泛在面板后黑场 */}
{/* 后层重影面板(截图④⑤双层) */}
{/* 重影面板同样受聚光范围控制 */}
{/* 面板本体:聚光范围内显影,范围外沉黑 */}
{/* 尾段右缘蓝紫残光罩 */}
{/* 贴顶边划过的紫色光线(本体) */} {/* 右缘竖直光线:聚光接近右侧时点亮,尾段转蓝紫 */} {/* logo 一圈描光(截图⑤:光经过 logo 时) */}
{/* 光头本体眩光:贴着顶边的亮团 */}
); }; // ===== demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx ===== // slide-spotlight-pan v2 —— 按用户截图 clickup03 重做: // 紫色光线贴着 UI 面板边缘泛光(先绕左上角竖缘、再沿顶边横走), // 聚光头匀速右移,照到处显影、离开处沉暗;面板匀速左滑(相机右摇感)。 // 用户裁决:"紫色的光线是贴着ui界面泛光的,聚光的移动是匀速的"。 import React from 'react'; import { AbsoluteFill, useCurrentFrame, interpolate } from 'remotion'; const ink = '#3c3c3a'; const mid = '#98989a'; const line = '#e4e4e2'; const PW = 3000; const PH = 1400; const TOP = 150; // 面板顶边在屏幕座标的 y const CR = 60; // 面板圆角 const SideRow: React.FC<{ w: number }> = ({ w }) => (
); const Task: React.FC<{ seed: number }> = ({ seed }) => (
); const Col: React.FC<{ accent: string; seed: number; w: number }> = ({ accent, seed, w }) => (
{[0, 1].map((i) => )}
); // 超宽面板内容(放大特写级别):侧栏 + 顶栏 + 三列看板 const WidePanel: React.FC = () => (
); export const SlideSpotlightPan: React.FC = () => { const frame = useCurrentFrame(); // 面板匀速左滑(相机右摇)——严格 linear const slide = interpolate(frame, [0, 132], [180, -1100]); // 聚光头在面板本地座标沿顶边匀速右移——严格 linear // 起点在左上角竖缘(负值=还在左缘竖直段),随后转过角沿顶边走 const head = interpolate(frame, [0, 132], [-360, 2600]); const onTop = Math.max(0, head); // 顶边段进度 const cornerT = Math.min(1, Math.max(0, (head + 360) / 360)); // 竖缘段 0→1 const vertHeadY = TOP + 620 - cornerT * 620; // 左缘光头从下往上爬到角 // 屏幕座标的光头位置 const headScreenX = slide + onTop; // 光头在竖缘阶段贴着面板左缘 const leftEdgeX = slide; // 竖缘光线强度:角前满、转角后衰减 const vGlow = head < 0 ? 1 : Math.max(0, 1 - head / 900); // 顶边光线强度:转角后满 const hGlow = Math.min(1, Math.max(0, (head + 120) / 240)); const grad = (dir: string, c: string) => `linear-gradient(${dir}, rgba(0,0,0,0) 0%, ${c} 42%, ${c} 58%, rgba(0,0,0,0) 100%)`; return ( {/* 面板层:聚光范围内显影 */}
{/* 贴面泛光:光头下方的紫光晕染进 UI 顶部(贴着界面泛光的关键层) */}
{/* 左缘贴面泛光(竖缘阶段) */}
{/* 聚光范围外压暗:以光头为中心的显影罩(面板本地座标,跟光头走) */}
{/* ===== 贴边紫色光线本体(屏幕层,贴着面板边缘) ===== */} {/* 顶边横向光线:三层辉光 + 亮芯,中心=光头 */}
{/* 左上角竖缘光线(起始阶段,贴面板左缘) */}
{/* 顶上方黑檐:光带以上纯黑(截图里顶边之上是黑场) */}
); };