從 Figma 匯入設計
學習如何將 Figma 設計匯出為 SVG,轉換為 React 元件後匯入 Remotion 專案,並為 SVG 元素加入動畫效果。
你可以將 Figma 設計匯出為 SVG 檔案,作為 React 元件匯入 Remotion 專案,然後對其進行動畫製作。
開啟 Figma 設計
本教學以 Streamline 的向量插圖集為範例。你可以使用任何你在 Figma 中製作或引用的設計。
在 Figma 中組織向量元素
如果還沒這麼做,請先在 Figma 中將你想要匯出的元素分組(Group)或加入框架(Frame)。
在 SVG 中,群組會以 <g> 元素表示。如果你想要同時對多個元素進行動畫,預先在 Figma 中將它們分組,可以讓後續的動畫製作更加方便。
匯出為 SVG
你可以透過以下方式將 Figma 設計複製為 SVG 標記:
- 在 Figma 設計中右鍵點擊你想要匯出的元素或群組
- 選擇「Copy/Paste as」選項
- 選擇「Copy as SVG」
接下來,你需要將 SVG 轉換為 React 元件。通常你可以直接將 SVG 標記貼入 React 的 JSX,它就能正常運作。
或者,你也可以使用 SVGR Playground 來可靠地將 SVG 轉換為 React 元件格式。
在 Remotion 中匯入 SVG
將轉換好的元件貼入 Remotion 專案,並在 src/Root.tsx 中註冊一個 <Composition>。
你可以在此範例儲存庫中找到完整的範例。
為 SVG 標記加入動畫
找到你想要動畫的 SVG 元素,為它加入 style 屬性。
以下範例示範如何為包含火箭的 <g> 元素加入動畫。首先建立基本結構,為目標元素加上樣式:
import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion";
export const Rocket: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
return (
<AbsoluteFill
style={{
backgroundColor: "pink",
justifyContent: "center",
alignItems: "center",
}}
>
<svg
width="800"
height="800"
viewBox="0 0 394 394"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="vehicle"
style={{
transformOrigin: "center center",
transformBox: "fill-box",
}}
>
{/* 火箭的路徑元素放在這裡 */}
</g>
</svg>
</AbsoluteFill>
);
};將 { transformOrigin: "center center", transformBox: "fill-box" } 加入元素的樣式,可確保變形的中心點是元素自身的中心,而非整個 SVG 視圖的中心。
建立 Spring 動畫
接下來建立兩個彈簧動畫:一個控制縮放,一個控制位移(向上升空):
import {
AbsoluteFill,
useCurrentFrame,
useVideoConfig,
spring,
interpolate,
} from "remotion";
export const Rocket: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// 縮放動畫:從 0 到 1,立即開始
const scale = spring({
fps,
frame,
config: {
stiffness: 200,
},
});
// 升空動畫:從第 20 幀開始,模擬緩慢啟動後加速
const up = spring({
fps,
frame: frame - 20,
config: {
damping: 20,
mass: 15,
},
});
// 將 up 的值(0 到 1)映射到像素位移(0 到 -3000px)
const launch = `translateY(${interpolate(up, [0, 1], [0, -3000])}px)`;
return (
<AbsoluteFill
style={{
backgroundColor: "pink",
justifyContent: "center",
alignItems: "center",
}}
>
<svg
width="800"
height="800"
viewBox="0 0 394 394"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="vehicle"
style={{
// 同時套用縮放和升空動畫
transform: `scale(${scale}) ${launch}`,
transformOrigin: "center center",
transformBox: "fill-box",
}}
>
{/* 火箭的路徑元素放在這裡 */}
</g>
</svg>
</AbsoluteFill>
);
};動畫說明
scale從0增長到1,讓火箭在開頭從無到有地出現。up從第 20 幀開始,配合高mass(質量)和低damping(阻尼)模擬重型火箭緩慢啟動的效果。launch使用interpolate()將up的值(0 到 1)線性映射到垂直位移(0 到 -3000px),讓火箭向上飛離畫面。
更複雜的 SVG 動畫範例
你可以為 SVG 中的不同元素各自加入獨立的動畫,建立更豐富的效果:
import {
AbsoluteFill,
useCurrentFrame,
useVideoConfig,
spring,
interpolate,
} from "remotion";
export const AnimatedSvg: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// 各元素的獨立動畫
const bodyOpacity = interpolate(frame, [0, 15], [0, 1], {
extrapolateRight: "clamp",
});
const wingSpread = spring({
fps,
frame: frame - 10,
config: { stiffness: 100, damping: 15 },
});
const exhaustScale = spring({
fps,
frame: frame - 5,
config: { stiffness: 300, damping: 10 },
});
return (
<AbsoluteFill
style={{
backgroundColor: "#1a1a2e",
justifyContent: "center",
alignItems: "center",
}}
>
<svg
width="400"
height="400"
viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg"
>
{/* 火箭本體:淡入效果 */}
<g id="body" style={{ opacity: bodyOpacity }}>
{/* 本體路徑 */}
</g>
{/* 火箭翼:展開效果 */}
<g
id="wings"
style={{
transform: `scaleX(${interpolate(wingSpread, [0, 1], [0.2, 1])})`,
transformOrigin: "center center",
transformBox: "fill-box",
}}
>
{/* 翼部路徑 */}
</g>
{/* 引擎噴焰:脈動效果 */}
<g
id="exhaust"
style={{
transform: `scaleY(${interpolate(exhaustScale, [0, 1], [0, 1])})`,
transformOrigin: "top center",
transformBox: "fill-box",
}}
>
{/* 噴焰路徑 */}
</g>
</svg>
</AbsoluteFill>
);
};注意事項
- SVG 坐標系:SVG 的 Y 軸向下為正,因此向上移動要使用負值。
transformBox: "fill-box":務必加入此樣式,否則transformOrigin會相對於整個 SVG 視圖計算,而非元素自身。- 群組與路徑:在 Figma 中良好的圖層命名習慣,可以幫助你在 SVG 程式碼中快速找到要動畫的元素(因為 Figma 會以圖層名稱作為
id)。 - Locofy 整合:如果你想將整個 Figma 設計匯出為 React 元件(不只是 SVG),可以考慮使用 Locofy。