// 爆花确认(pop-burst-confirm)——确认时刻的三连爆 // 半屏大对勾 icon(圆底+勾):先缩 0.6x 蓄力 3f → 弹 1.35x 过冲 → 落回 1x, // 释放帧同帧中心射出 10 根短线粒子(径向飞出后消失)+ 一圈描边圆环从 // icon 边缘扩到 2.5 倍直径淡出;随后 "Deployed" 小标签弹出。 // 节拍:0–20 静置(空心圆待确认)→ 20–23 缩 0.6x → 23–27 蓄力 3f → // 27 释放(勾画出+粒子+圆环)→ 27–44 过冲落回 → 40–50 标签弹出 → 55 后真静止 65f。 // 帧确定,无随机源(粒子角度抖动用 sin 散列)。 import React from 'react'; import { useCurrentFrame, interpolate, Easing } from 'remotion'; import { G } from '../../_fixtures/Fixtures'; const AMBER = '#b45309'; const POP = 27; // 释放帧 const DUR = 120; export const PopBurstConfirm: React.FC = () => { const f = useCurrentFrame(); // icon 缩放:蓄力→过冲→落回 const scale = (() => { if (f <= 20) return 1; if (f <= 23) return interpolate(f, [20, 23], [1, 0.6], { easing: Easing.in(Easing.quad) }); if (f <= POP) return 0.6; if (f <= 33) return interpolate(f, [POP, 33], [0.6, 1.35], { easing: Easing.out(Easing.cubic) }); return interpolate(f, [33, 44], [1.35, 1], { extrapolateRight: 'clamp', easing: Easing.out(Easing.back(2)), }); })(); // 对勾:释放帧起 8f 内画出(dashoffset 滑窗) const checkT = interpolate(f, [POP, POP + 8], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.out(Easing.cubic), }); // 粒子:释放帧起 14f 径向飞出(幅度加码到 190px 保半屏可感) const pt = interpolate(f, [POP, POP + 14], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const pDist = 210 + 190 * Easing.out(Easing.cubic)(pt); const pLen = 46 * (1 - pt); // 圆环:释放帧起 20f 从 icon 边缘扩到 2.5 倍直径淡出 const rt = interpolate(f, [POP, POP + 20], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const ringR = 200 + 300 * Easing.out(Easing.cubic)(rt); const ringO = 0.85 * (1 - rt); const ringW = 16 - 12 * rt; // 标签:40f 弹出(back 超调) const tagT = interpolate(f, [40, 50], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', easing: Easing.out(Easing.back(2.6)), }); const CX = 960; const CY = 470; return (
{/* 扩散圆环(不随 icon 缩放) */} {rt > 0 && rt < 1 && ( )} {/* 粒子:10 根短线径向飞出,角度带 sin 散列微抖 */} {pt > 0 && pt < 1 && ( {Array.from({ length: 10 }).map((_, i) => { const ang = ((i * 36 + 9 * Math.sin(i * 7.31)) * Math.PI) / 180; const x1 = 700 + Math.cos(ang) * pDist; const y1 = 700 + Math.sin(ang) * pDist; const x2 = 700 + Math.cos(ang) * (pDist + pLen); const y2 = 700 + Math.sin(ang) * (pDist + pLen); return ( ); })} )} {/* 主体 icon:圆底 + 对勾(半屏特写 ~480px) */} {checkT > 0 && ( )} {/* Deployed 小标签 */} {tagT > 0 && (
Deployed
)}
); };