Remotion 标注组件实战:把箭头、框选和脉冲写进时间轴
【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion
给演示视频做标注,逐帧截图手画箭头和框,对位费时且粗糙。Remotion 视频标注的本质是:箭头、框选、高亮全部是@remotion/shapes里的 React 组件,直接排进时间轴。读完后你能独立搭出一段"框选 + 箭头指引 + 脉冲高亮"的标注场景并验收出片。
需求拆解:先列清单,再碰代码
动手前,把视频里每个要指认的点过一遍,标注诉求基本落在三类,每类都有现成组件(源码在 packages/shapes/src/components/):
| 诉求类别 | 组件 | 用途 |
|---|---|---|
| 圈出重点区域 | Rect、Circle、Ellipse | 半透明填充 + 描边,把目标从画面里"摘"出来 |
| 给目标配一句说明 | Callout | 自带指针尾巴的标签气泡 |
| 指向某个元素 | Arrow | 内置up/down/left/right四个朝向 |
先列这个清单不是走形式:它直接决定两个后续关键参数——每个标注的位置(style里的left/top)和出现时机(from和durationInFrames填几)。清单上每个标注没有这两组数字,后面就没法填。
帧号提前写死
顺手定好全局基准:分辨率 1920×1080、30fps,此时 1 秒 = 30 帧。所有标注坐标都按这套像素体系算,帧号在清单阶段就算好(比如"箭头从第 30 帧出现、停留 45 帧"),避免渲染前临时凑数导致节奏错乱。
选型原则与参数直觉
选型一句话概括:谁表达意图最省字,就用谁。区域用矩形,点状目标用圆形,说明文字用Callout——比"矩形 + 三角形"手拼少写一半代码。
一个反直觉的设计:Arrow没有任何"从哪到哪"的坐标参数。它只有length(总长)、shaftWidth(箭杆宽)、headLength(箭头长)、headWidth(箭头宽)和direction枚举,画出来的是一根标准箭头,指向哪个元素全靠摆放位置解决:
<Arrow length={260} shaftWidth={26} headLength={70} direction="up" />够用组件就四个:Rect、Circle、Callout、Arrow。包里的Star、Heart、Pie、Spark这类几何体在此场景下用不上,别为了"用全"硬塞。
最小可运行的静态版本
标注层本质是叠在画面上方的一层 SVG,先让零动画的第一帧成立,再谈动效:
import {AbsoluteFill} from 'remotion'; import {Arrow, Rect, Circle, Callout} from '@remotion/shapes'; export const AnnotationLayer = () => { return ( <AbsoluteFill> {/* 框选:半透明黑底把代码块与画面分离,白色描边提高对比 */} <Rect width={420} height={160} cornerRadius={18} fill="rgba(0,0,0,0.25)" stroke="white" strokeWidth={6} // 形状参数只管"是什么形状",摆放位置一律走 style style={{position: 'absolute', left: 120, top: 240}} /> {/* 气泡:说明文字容器,指针朝下压住目标区域 */} <Callout width={320} height={140} pointerDirection="down" pointerLength={50} pointerBaseWidth={70} fill="#ffd60a" style={{position: 'absolute', left: 140, top: 60}} /> {/* 指引:箭头方向由枚举决定,位置靠 style 对准按钮 */} <Arrow length={260} shaftWidth={26} headLength={70} direction="up" fill="#ffd60a" style={{position: 'absolute', left: 980, top: 560}} /> {/* 高亮:半透明圆压住关键按钮,先静态确认圆心位置 */} <Circle radius={70} fill="rgba(255,214,10,0.35)" style={{position: 'absolute', left: 860, top: 470}} /> </AbsoluteFill> ); };新手高频三坑
- 定位别找 x / y 参数:形状参数全是"形状本身"的属性(宽高、圆角、朝向),摆放统一走
style的left/top,心智模型一致。 cornerRadius与edgeRoundness二选一:前者用圆弧切角,后者用贝塞尔曲线磨边,同时传会互相打架。- 颜色靠 SVG 属性透传:
fill、stroke、strokeWidth都是标准 SVG path 属性,直接写在组件上,无需额外包装。
两个动效维度
定时显隐:出现时机
形状组件内部包了一层Sequence,直接接收时间轴参数,不用自己再包:
<Arrow from={30} // 第 30 帧(1 秒)才出现 durationInFrames={45} // 持续 45 帧后自动隐藏 length={260} direction="up" fill="#ffd60a" />帧数换算就一条:30fps 下 1 秒 = 30 帧,"2 秒后出现、停 1.5 秒"写成from={60}+durationInFrames={45}。
插值动画:持续运动
脉冲的本质是半径随时间周期变化,一个interpolate就够:
const frame = useCurrentFrame(); const pulse = interpolate(frame, [0, 15, 30], [1, 1.25, 1], { extrapolateRight: 'sine-in-out', }); return <Circle radius={70 * pulse} fill="rgba(255,214,10,0.35)" />;想做"淡入 + 滑入"这类多属性同时变化的入场,用 packages/animation-utils/src/transformation-helpers/ 里的interpolateStyles在两个 style 对象间直接插值(颜色和 CSS 函数值都能处理),配makeTransform拼变换串,比手写模板字符串更不易错。
组装与验收
图层组织策略
底层放画面(重素材建议用offthreadVideo承载),标注层整体叠在上层;每个独立标注保留自己的name,在 Studio 时间轴里就能逐个拖动、单独隐藏,排查问题时定位更快。
验收清单
- 开
debug查路径:形状组件支持debug属性,会把贝塞尔控制点直接画出来;箭头弧度不对、Callout指针歪了,一眼可见。 - 版本号对齐:所有
remotion与@remotion/*包用同一精确版本,安装时加--save-exact,版本错位是渲染报"神秘错误"的常见原因。 - 逐段播放确认:标注不出安全区、
from入场帧不跳、durationInFrames结束瞬间无残留图形。 - 换帧率重算:如果最终渲染帧率不是 30,所有帧号参数按比例重算,别沿用 30fps 的数字。
收束:行动清单
- 装包并对齐版本:
npm install @remotion/shapes --save-exact,确认与项目里其余 remotion 包同号。 - 拿一段既有录屏,按"框选 / 气泡 / 指引"三类列出标注清单,标好出现帧号。
- 用静态版本代码搭标注层,先在 Studio 里逐帧确认第一帧位置正确。
- 给每个标注填
from/durationInFrames,再挑一个重点目标加脉冲或淡入。 - 按验收清单过一遍:开
debug查路径、查版本、逐段播放,然后渲染出片。
想深入:组件参数与源码看 packages/shapes/,路径与几何底层在 packages/paths/,插值工具函数在 packages/animation-utils/,完整文档集中在 packages/docs/。
【免费下载链接】remotion🎥 Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考