SVG 動畫完整教學:用 CSS 與 JavaScript 打造互動式向量動效
在前端設計的世界裡,SVG 動畫是一個被嚴重低估的技能。很多設計師只把 SVG 當成 icon 的格式,殊不知它其實是一個完整的動畫系統。跟 Canvas 比起來,SVG 是 DOM 的一部分,每個元素都可以被 CSS 選中、被 JavaScript 操作、甚至能回應使用者事件。
我自己在做前端切版的時候,大概有三成的動效都是用 SVG 實現的,特別是 icon 動畫、路徑描繪、數據圖表這類東西。如果你已經掌握了CSS Scroll-Driven Animations,那 SVG 動畫會讓你的武器庫更加完整。
為什麼選擇 SVG 做動畫?
SVG 動畫有幾個獨特的優勢:
- 向量圖形:不管怎麼縮放都不會模糊,完美支援 Retina 螢幕
- 檔案超小:一個有動畫的 SVG icon 通常只有幾 KB
- 可存取性:SVG 元素可以加上
aria-label和role,對螢幕閱讀器友善 - 互動性:每個 SVG 元素都是 DOM 節點,可以綁定事件
- CSS 控制:可以用 CSS 的 transition、animation、transform 來控制動畫
什麼時候不適合用 SVG?當你的動畫涉及大量的粒子、複雜的物理模擬、或是超過數千個元素的同時動畫時,Canvas 或 WebGL 會是更好的選擇。
SVG 動畫前的基礎知識
要做 SVG 動畫,你至少需要理解以下幾個基礎元素:
基本形狀:<rect>、<circle>、<ellipse>、<line>、<polygon>、<polyline>。
路徑 <path>:SVG 最強大的元素。用 d 屬性定義路徑,包含移動(M)、直線(L)、曲線(C、Q)、弧線(A)等指令。幾乎所有複雜的 SVG 圖形都是用 <path> 畫的。
群組 <g>:把多個元素組成群組,方便一起做 transform。
viewBox:定義 SVG 的座標系統。比如 viewBox="0 0 100 100" 表示 SVG 內部用 100x100 的座標,不管實際 DOM 大小如何。
用 CSS 製作 SVG 動畫
SVG 元素可以直接用 CSS 來做動畫。你可以對 SVG 元素設定 transition、animation,以及常見的 transform、opacity、fill、stroke 等屬性。
一個簡單的 hover 變色動畫:
svg circle {
fill: #3498db;
transition: fill 0.3s ease;
}
svg circle:hover {
fill: #e74c3c;
}
用 @keyframes 做旋轉動畫:
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
animation: spin 1s linear infinite;
transform-origin: center;
}
這裡有個重要的細節:SVG 的 transform-origin 預設是 SVG viewBox 的左上角(0, 0),而不是像 HTML 元素那樣預設在中心。所以旋轉動畫一定要記得設定 transform-origin: center。
stroke-dashoffset 路徑描繪動畫
這是 SVG 動畫最經典也最酷的技巧。原理是利用 stroke-dasharray 和 stroke-dashoffset 這兩個屬性來模擬路徑被「畫出來」的效果。
步驟如下:
- 用 JavaScript 取得路徑的總長度:
path.getTotalLength() - 設定
stroke-dasharray等於路徑總長度(整條線變成一個完整的 dash) - 設定
stroke-dashoffset也等於路徑總長度(dash 被完全偏移,看起來不見了) - 動畫讓
stroke-dashoffset從總長度變為 0(dash 逐漸出現)
/* CSS */
.draw-path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw 2s ease forwards;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}
這個技巧可以用在 Logo 描繪動畫、地圖路線動畫、手寫字效果等等。配合View Transitions API,在頁面切換時觸發 SVG 路徑動畫,效果會非常驚艷。
用 JavaScript 控制 SVG 動畫
CSS 動畫適合簡單的循環和狀態切換,但如果需要更精細的控制——比如根據滾動位置、滑鼠位置或資料變化來驅動動畫——就需要 JavaScript 出場了。
最基本的做法是直接操作 SVG 元素的屬性:
const circle = document.querySelector('circle');
let radius = 50;
function animate() {
radius = 50 + Math.sin(Date.now() / 500) * 20;
circle.setAttribute('r', radius);
requestAnimationFrame(animate);
}
animate();
進階一點,你可以用 Web Animations API(WAAPI)來控制 SVG 動畫,它提供了比 CSS animation 更精細的播放控制(暫停、倒轉、調速)。
SMIL 動畫:SVG 原生動畫語法
SVG 有自己的原生動畫語法叫做 SMIL(Synchronized Multimedia Integration Language),用 <animate>、<animateTransform>、<animateMotion> 等元素直接寫在 SVG 裡面。
<circle cx="50" cy="50" r="20">
<animate attributeName="r" values="20;30;20" dur="1s" repeatCount="indefinite" />
</circle>
SMIL 的優點是不需要 CSS 或 JavaScript,動畫直接嵌在 SVG 檔案裡。但缺點是 IE 完全不支援(不過 2026 年了,誰還管 IE 呢),而且控制彈性不如 CSS/JS。
實戰:打造互動式 SVG 圖表
讓我們用前面學到的技巧,做一個互動式的圓環進度圖表。需求是:一個環形圖,當使用者滑鼠 hover 時,環形會從 0% 動畫到目標百分比,旁邊顯示數字。
核心實作邏輯:
- 用
<circle>畫一個底色圓環和一個進度圓環 - 進度圓環用
stroke-dasharray和stroke-dashoffset來控制顯示比例 - 用 JavaScript 監聽 hover 事件,觸發
stroke-dashoffset的動畫 - 同時用
requestAnimationFrame讓中間的數字跟著動
這種互動式圖表在 Dashboard 頁面中非常常見。如果你想讓整個佈局的響應式設計更好,可以搭配 Tailwind CSS v4 來處理外層容器的樣式。
SVG 動畫效能優化
SVG 動畫的效能通常很好,但以下情況需要注意:
- 避免動畫
d屬性:改變路徑資料會觸發重排,效能很差。如果需要形狀變形,用transform代替 - 優先動畫
transform和opacity:這兩個屬性可以被 GPU 加速 - 用
will-change:對頻繁動畫的元素加上will-change: transform提示瀏覽器預先優化 - 減少 DOM 元素:如果你的 SVG 有上千個
<path>,考慮用<use>來複用
實用工具與函式庫推薦
- GSAP(GreenSock):業界標準的動畫引擎,對 SVG 的支援非常強大
- Lottie:如果你的團隊有 After Effects 設計師,Lottie 可以直接匯入 AE 的 SVG 動畫
- Snap.svg:專門用來操作 SVG DOM 的函式庫
- SVG.js:輕量但功能完整的 SVG 操作庫
- SVGO:SVG 最佳化工具,可以大幅壓縮檔案大小
結語
SVG 動畫是前端設計師不可或缺的技能。從簡單的 CSS transition 到複雜的 JavaScript 控制,SVG 提供了無限的創作可能。特別是 stroke-dashoffset 路徑描繪技巧,幾乎在每個現代網站中都能找到它的身影。
建議你接著去看看CSS Anchor Positioning,學會怎麼用原生 CSS 做定位,搭配 SVG 動畫可以做出更精緻的 Tooltip 和 Popover 效果。
你可能也喜歡
探索其他領域的精選好文