关于 animated-infographic
animated-infographic 是使用 Remotion 设计并制作信息图动画的技能,面向视频创作者。它先规划清晰的静态构图,再按层级依次呈现图标、数字、标签和连接线。
主要功能
- 01规划静态信息图构图
- 02按层级错开呈现元素
- 03使用弹簧效果呈现图标
- 04缓动数字递增
- 05动画化连接线与流程线
- 06按帧检查渲染结果
适用场景
- 01制作分步骤呈现的三步说明
- 02以统计卡片网格展示关键数字
- 03为图标、数字和流程连接线添加动画
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ iart-ai/ data-animation-skills --skill animated-infographic安装后在 Claude Code 中输入/animated-infographic确认已加载。
附带文件README.mdreferences/sequenced-infographic.md
详细介绍
动态信息图
制作一张经过设计的信息图——将图标、几个关键数字、简短文字和简单图形巧妙排布,营造清晰的视觉层级;然后按顺序为其添加动画,让每个元素都有自己的高光时刻。创作的核心是先构图,再编排:静态布局本身就要易于理解,再通过错落有致的层层呈现,引导视线精准地落在你想要的位置。
适用场景
- 混合布局的说明图:“分 3 步了解 X”“工作原理”“数据一览”、统计卡片网格。
- 将图标 + 统计数据 + 标签 + 连接线作为一个整体设计场景,按顺序呈现。
- 象形图/图标动画、关键数字递增计数、步骤间的流程连接线。
此技能负责制作构图式信息图。如果图表本身就是内容(例如柱状图竞赛、动态折线图/面积图、由 CSV 驱动的图表),请使用 chart-animation——并将其图表作为一个整体嵌入此处的信息图中,而不是重新制作。
唯一准则:先设计静态画面
出色的动态信息图,本质上是一张恰好会动的出色静态信息图。先排布并平衡完整构图——每个图标、数字和标签都要处于最终位置——然后再添加任何关键帧。动画只负责控制这些已就位元素的出现时机,绝不决定布局。这样可以避免最常见的问题:元素飞向从未经过设计的位置,导致最终定格画面看起来像是意外拼凑出来的。
严格控制范围:在 30–90 秒内呈现一个核心观点和3–5 个辅助数据点。相互争夺注意力的元素超过 5 个,层层呈现就会显得杂乱。
视觉层级 → 呈现顺序
呈现顺序就是层级。视线会跟随元素的出现,因此要按重要性而非布局顺序为元素添加动画。为每个元素指定一个层级,然后逐层呈现。
| 层级 | 元素 | 呈现方式 | 动效 |
|---|---|---|---|
| 1 | 章节标题/核心观点 | 最先单独呈现 | 淡入 + 轻微上移 |
| 2 | 图标(锚定每个条目) | 每个条目依次呈现,作为该组的开场 | 弹出/缩放过冲 |
| 3 | 关键数字(计数器) | 紧随对应图标 | 递增计数,缓出 |
| 4 | 标签/说明文字 | 在数字下方稳定呈现 | 淡入,不做夸张动效 |
| 5 | 连接线/流程线 | 随条目完成逐步连接 | 沿路径绘制 |
静态层级通过大小、字重和颜色体现;动画层则通过时机和动效呈现。一次只突出一个元素——绝不要同时让两个数字计数。
错开:层层呈现
让同级条目之间以固定间隔(即错开)依次出现,使整组内容呈现为一个序列,而非瞬间闪现。让每个元素都由当前帧通过纯函数计算——绝不使用墙上时钟时间或库的动画循环——确保渲染结果具有确定性。
import { useCurrentFrame, spring, useVideoConfig } from "remotion";
const STAGGER = 8; // frames between siblings (~0.27s @30fps)
function Item({ index, children }) {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const local = frame - index * STAGGER; // this item's own clock
const enter = spring({ frame: local, fps, config: { damping: 14, mass: 0.6 } });
return (
<div style={{ opacity: enter, transform: `translateY(${(1 - enter) * 24}px)` }}>
{children}
</div>
);
}
错开 6–10 帧会显得干脆利落;超过约 15 帧则会拖沓。所有同级元素使用同一条入场曲线,让层层呈现显得沉稳自信,而非杂乱无章。
图标动画:弹出效果
图标是每个条目的视觉锚点,因此要为其设计最有力的入场效果——通过缩放过冲(“弹出”)后稳定下来。使用低阻尼弹簧营造弹跳感;绝不要使用线性缩放(看起来很机械)。
const pop = spring({ frame: local, fps, config: { damping: 10, stiffness: 180, mass: 0.5 } });
// pop overshoots past 1 then settles → lively
<g transform={`scale(${pop})`} style={{ transformOrigin: "center" }}>{icon}</g>
对于象形图填充(例如“10 人中有 7 人”),按相同间隔逐个呈现单元,并用遮罩裁切不完整的单元,而不是缩放它。
关键数字:平稳到位的计数器
先对底层数字进行插值并添加缓动,再在渲染时格式化。必须做到两点:格式化前先取整,并使用 tabular-nums,避免数字变化时布局抖动。(与 chart-animation 共用的技巧——货币/百分比格式变体请参阅其计数器章节。)
import { interpolate, Easing } from "remotion";
const raw = interpolate(frame - delay, [0, 30], [0, 1287], {
extrapolateLeft: "clamp", extrapolateRight: "clamp",
easing: Easing.out(Easing.cubic), // "settling on a number"
});
const label = new Intl.NumberFormat("en-US").format(Math.round(raw)); // "1,287"
// CSS: font-variant-numeric: tabular-nums; line-height: 1;
标题数字使用缓出会有逐渐到位的感觉;线性变化则像机械里程表。每个数字显示约 0.5 秒后,再开始呈现下一条目。
连接线与流程
连接线将卡片网格变成一个流程。通过绘制路径来动画呈现线条/箭头,并与其指向的项目结束显示时同步——这种动效能告诉观众“接下来请看这里”。
const pathRef = useRef();
const len = pathRef.current?.getTotalLength?.() ?? 0;
const draw = interpolate(frame - delay, [0, 18], [0, 1], { extrapolateRight: "clamp" });
<path ref={pathRef} d="M40,0 C40,30 40,30 40,60" fill="none" stroke="#444" strokeWidth={3}
strokeDasharray={len} strokeDashoffset={len * (1 - draw)} />
在连接的两个项目之间绘制连接线,在源项目出现后、目标项目出现前的空档中呈现——让线条引导视线移向下一次揭示。
分段节奏
为每个元素分配时间,而不是把时间花在逐秒打磨上。观众一次只能追踪一个运动中的对象。
| 节拍 | 时长 |
|---|---|
| 标题停留(让观众看清) | 0.8–1.2s |
| 每个项目(图标弹出 → 计数 → 标签) | 1.2–2.0s |
| 绘制连接线 | 0.4–0.6s,与下一个项目的动画重叠 |
| 最终完整画面停留(便于截图) | 2–3s |
最后让完整的静态信息图保持不动 2–3s——重点是组装完成的画面,所以要让它稳定呈现,不要有其他动效干扰。
输出检查清单
- 在设置任何关键帧之前,先设计好静态布局并调整平衡;最终停留帧看起来要经过精心设计。
- 一个核心观点、3–5 个数据点、30–90s。
- 揭示顺序遵循层级(标题 → 图标 → 数字 → 标签 → 连接线),而不是布局顺序。
- 同级元素以一致的 6–10 帧间隔依次出现,并使用同一条入场曲线。
- 图标以带弹簧回弹效果的方式弹出;数字采用缓动递增,并使用
tabular-nums;一次只动画一个数字。 - 绘制连接线,引导视线移向下一次揭示。
- 每个值都必须是
useCurrentFrame()的纯函数;不使用库定时器。 - 最终完整画面停留 ≥2s。
交付与验证(渲染静帧 → MP4)
随附辅助脚本(
scripts/):使用scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png拼接静帧,然后使用scripts/probe-mp4.sh out.mp4 [WxH] [fps]验证编码结果。请参阅scripts/README.md。
Remotion 具有逐帧确定性——每个图标弹出、计数器数值和连接线绘制效果都是 useCurrentFrame() 的纯函数,因此无需定位工具,即可在无头模式下渲染任意精确帧。信息图包含关键数字,因此检查静帧可以在你浪费时间编码之前,及时发现统计数据错误或错开的动画落在画布之外的问题。
输出要求:
- 一个已注册场景的 Remotion 项目(
<Composition>+ zodschema+defaultProps),所有动效均由帧驱动(不使用定时器/Date.now()/Math.random())。 - 交付内容 = 渲染后的
out/*.mp4(以及项目本身,方便用户使用新统计数据/图标重新渲染)。 - 时长取决于数据(N 个项目 × 每项预算)?在
calculateMetadata中计算,不要手动填写。
验证流程——渲染静帧 → 检查 → 编码。 先渲染单帧(成本低,无需视频编码),确认布局和数字无误后再进行编码。
# 1. Frame-exact stills — with the SHIPPED props. Pick frames that catch each tier:
npx remotion still Infographic out/f-title.png --frame=20 --props='{"items":[...]}' # title + first pop
npx remotion still Infographic out/f-mid.png --frame=90 --props='{"items":[...]}' # mid cascade
npx remotion still Infographic out/f-end.png --frame=149 --props='{"items":[...]}' # final composed hold (= durationInFrames - 1)
# 2. Inspect each PNG — FIDELITY (every key number exact, labels/captions correct, icons the right glyph)
# AND artifacts (text overflow, icon off-canvas, clipped safe-area, missing font, connector pointing
# at the wrong item, half-revealed element where a tier should be settled).
# 3. Only after the stills check out, encode:
npx remotion render Infographic out/infographic.mp4 --props='{"items":[...]}'
- 使用
npx remotion compositions查看durationInFrames/fps;最终完整画面停留帧是关键帧——确认画面看起来经过精心设计,而不是仍处于逐项揭示的过程中。 - 数据驱动/批量渲染:批量渲染所有变体之前,先通过静帧验证一组有代表性的 props(统计数据 + 标签)——一次发现计数器或布局问题,而不是在 N 个变体中反复踩坑。
- 免费生成 README 演示 GIF:
npx remotion render Infographic out/demo.gif --codec=gif。
完成前:
npx remotion still在标题帧、逐项揭示过程中的帧和最终停留帧均能干净渲染——无错误、无缺失字体/图标。- 每个关键数字都必须精确无误(已舍入,使用
tabular-nums),并且每一帧中的所有元素都位于安全区域内。 - 仅使用帧驱动——不使用
Date.now()/Math.random()/库定时器(确保在 CI 中保持确定性)。 - 实际交付的 props 能正确渲染(不只是
defaultProps)——统计数据、图标和标签均正确。 - 完整 MP4 已编码且可以播放;(可选)为 README 渲染 GIF。
参考文件
references/sequenced-infographic.md— 一个完整且可运行的 Remotion 场景:一张包含 3 个步骤的“工作原理”信息图,采用错峰图标弹出、缓动递增统计数字、逐步绘制连接线、主时间轴映射,以及数据驱动(模板 × 数据)的属性模式。还包括一个无需依赖的内联 SVG 变体,可用于非 Remotion 场景。