動畫資訊圖表 是做什麼的?
建立一個經過設計的資訊圖表——包含圖標、幾個關鍵數字、簡短文字和簡單形狀,並具有真實的視覺層級——然後依序為其加入動畫,讓每個元素都能獲得展現的時刻。技巧在於先構圖,再編舞:一個靜態佈局本身就能傳達資訊,再透過錯開的揭示方式,引導視線精確地到達你想要的位置。
使用時機
- 混合佈局的解說內容:「3 個步驟了解 X」、「運作原理」、「數字會說話」、統計卡片網格。
- 在單一設計場景中,依序揭示圖標 + 統計 + 標籤 + 連接線。
- 象形圖/圖標動畫、關鍵數字遞增計數、步驟之間的流程連接線。
此技能負責的是經過構圖的資訊圖表。如果主要內容是圖表(例如長條圖競賽、折線圖/面積圖動畫、由 CSV 驅動的圖形),請使用 chart-animation——並在此處將其圖表作為一個區塊整合到資訊圖表中,而非重新構建。
唯一原則:先設計靜態框架
一個優秀的動畫資訊圖表,首先是一個優秀的靜態資訊圖表,只是它碰巧會動。在加入任何一個關鍵影格之前,先設計並平衡好整個構圖——每個圖標、每個數字和每個標籤都位於最終位置。之後的動畫僅控制何時顯示這些已放置好的元素;它絕不決定佈局。這可以防止最常見的失敗:元素飛向從未設計過的位置,使得最終的靜止畫面看起來像是偶然的。
範圍要緊湊:一個核心洞見,3–5 個輔助數據點,持續時間 30–90 秒。超過五個相互競爭的元素,依序揭示就會變成混亂。
視覺層級 → 揭示順序
揭示順序即代表層級。視線會跟隨出現的順序,因此請按照重要性順序為元素加入動畫,而不是版面順序。將每個元素對應到一個層級,然後逐層揭示。
| 層級 | 元素 | 揭示方式 | 動畫效果 |
|---|---|---|---|
| 1 | 區段標題 / 核心洞見 | 首先,單獨出現 | 淡入 + 微微上升 |
| 2 | 圖標(錨定每個項目) | 每個項目,領先其群組 | 彈出 / 縮放過衝 |
| 3 | 關鍵數字(計數器) | 緊接在其圖標之後 | 數字遞增,漸出 |
| 4 | 標籤 / 說明文字 | 在數字下方穩定顯示 | 淡入,無戲劇性動作 |
| 5 | 連接線 / 流程線 | 在項目完成時連結它們 | 繪製(路徑長度) |
在靜態層級中,使用尺寸、粗細和顏色;在動畫層級中,使用時間和動態效果。一次只專注一個元素——絕對不要同時讓兩個數字進行遞增計數。
錯開:鏈式反應
在同層級的項目之間加入固定的延遲(錯開)來揭示它們,使整個群組看起來像一個序列,而不是一次閃現。每個元素的動畫都應作為當前影格的純函數來驅動——永遠不要使用真實時間或某個函式庫的動畫循環——這樣渲染結果才能是確定的。
import { useCurrentFrame, spring, useVideoConfig } from "remotion";
const STAGGER = 8; // 同層級元素之間的影格數(30fps 下約 0.27 秒)
function Item({ index, children }) {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const local = frame - index * STAGGER; // 此項目的專屬時鐘
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 會超過 1 然後收斂 → 活潑
<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), // "收斂到一個數字"
});
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.2 秒 |
| 每個項目(圖標彈出 → 計數器 → 標籤) | 1.2–2.0 秒 |
| 連接線繪製 | 0.4–0.6 秒,與下一個項目重疊 |
| 最終構圖停留(可截圖) | 2–3 秒 |
最後以完整的靜態資訊圖表靜止停留 2–3 秒來結束——觀眾帶走的是最終的完整框架,所以讓它平靜下來,不要有任何動畫干擾。
輸出檢查清單
- 靜態佈局已在任何關鍵影格之前設計並平衡;最終的靜止畫面看起來是有意為之的。
- 一個核心洞見,3–5 個數據點,持續時間 30–90 秒。
- 揭示順序遵循視覺層級(標題 → 圖標 → 數字 → 標籤 → 連接線),而非版面順序。
- 同層級項目以一致的 6–10 個影格錯開方式鏈式呈現,並使用統一的進入曲線。
- 圖標以彈簧過衝效果彈出;數字使用漸出效果加上
tabular-nums字體進行遞增計數;一次只有一個數字在動畫。 - 連接線以繪製方式出現,引導視線進入下一個揭示內容。
- 每個值都是
useCurrentFrame()的純函數;沒有使用任何函式庫的計時器。 - 最終構圖畫面停留時間 ≥2 秒。
交付與驗證(渲染靜態幀 → 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() 的純函數,因此你可以在無頭模式下渲染任何精確的影格,無需使用 seek 工具。資訊圖表包含關鍵數字,因此靜態幀檢查可以在你浪費一次編碼之前,捕捉到錯誤的統計數據或錯開效果導致元素跑出畫面的問題。
輸出合約:
- 一個 Remotion 專案,已註冊場景(
<Composition>+ zodschema+defaultProps),所有動畫都由影格驅動(沒有計時器 /Date.now()/Math.random())。 - 可交付成果 = 渲染好的
out/*.mp4(加上專案原始碼,以便使用者可以使用新的統計數據/圖標重新渲染)。 - 持續時間取決於數據(N 個項目 × 每個項目的時間預算)?請在
calculateMetadata中計算,而不是手動設定。
驗證循環——渲染靜態幀 → 檢查 → 編碼。 首先渲染單個影格(成本低,無需影片編碼),然後只在佈局和數字都正確後才進行編碼。
# 1. 影格精確的靜態幀——使用最終的 props。選擇能捕捉到每個層級的影格:
npx remotion still Infographic out/f-title.png --frame=20 --props='{"items":[...]}' # 標題 + 第一個彈出
npx remotion still Infographic out/f-mid.png --frame=90 --props='{"items":[...]}' # 中間鏈式反應
npx remotion still Infographic out/f-end.png --frame=149 --props='{"items":[...]}' # 最終構圖停留(= durationInFrames - 1)
# 2. 檢查每個 PNG——準確性(每個關鍵數字精確,標籤/說明文字正確,圖標是正確的圖形)
# 以及瑕疵(文字溢出、圖標超出畫面、被裁切的危險區域、缺失字體、連接線指向錯誤的項目、
# 在某個層級應該已經穩定時卻有被部分揭示的元素)。
# 3. 只有在靜態幀檢查通過後,才進行編碼:
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 步驟的「運作原理」資訊圖表,包含錯開的圖標彈出、漸出計數的統計數字、繪製式的連接線、一個主時間軸映射,以及「使其資料驅動」(模板 × 資料)的 props 模式。包含一個無依賴的內聯 SVG 變體,供非 Remotion 使用。