
SVG path 指令解析:貝茲曲線、S/T 接點與橢圓弧 A
SVG path 用移動、直線、曲線與封閉指令描述形狀。讀取 M10,10 C20,20 40,20 50,10 時,先分清目前點、控制點與終點,就能理解路徑。本文依照 SVG 2 的 Paths 章(2018 年 10 月 4 日候選推薦標準)與 SVG 1.1 的橢圓弧實作附註,說明幾何與編輯時的限制。
日文原文發布: 2026-04-25
10 類指令與大小寫規則
表格若超出畫面寬度,可左右捲動。
| 指令 | 參數 | 用途 |
|---|---|---|
| M / m | x y | 移動,不畫線 |
| L / l | x y | 直線 |
| H / h | x | 水平線 |
| V / v | y | 垂直線 |
| C / c | x1 y1 x2 y2 x y | 三次貝茲曲線 |
| S / s | x2 y2 x y | 依前一段 C/S 反射控制點 |
| Q / q | x1 y1 x y | 二次貝茲曲線 |
| T / t | x y | 依前一段 Q/T 反射控制點 |
| A / a | rx ry rotation large-arc sweep x y | 橢圓弧 |
| Z / z | 無 | 封閉目前子路徑 |
大寫使用絕對座標,小寫使用相對於目前點的座標;Z/z 沒有座標參數,兩者作用相同。同一指令可連續給參數,例如 L 10,20 30,40 50,60 畫出三段直線。M 後第二組起的座標視為 L。
Z 將路徑封閉,描邊會使用接合處理;只用 L 回到起點,仍可能保留開放路徑的端點樣式,兩者不完全相同。
三次貝茲曲線的四個控制點
三次貝茲曲線由 P₀、P₁、P₂、P₃ 決定,參數 t ∈ [0,1]:
B(t) = (1-t)³ P₀ + 3(1-t)² t P₁ + 3(1-t) t² P₂ + t³ P₃Bernstein 基底的權重在此範圍內非負,總和為 1。曲線通過 P₀ 與 P₃,一般不通過中間的 P₁、P₂;整條曲線位於全部四個控制點的凸包內。平移、旋轉或縮放控制點,曲線也會跟著做相同的仿射變換。
端點導數為 B′(0)=3(P₁−P₀)、B′(1)=3(P₃−P₂)。若向量為零,不能只靠這個式子決定切線方向。C 指令以目前點作 P₀,三組參數依序給出 P₁、P₂、P₃。
用 de Casteljau 演算法求值與分割
de Casteljau 反覆使用線性內插來求曲線上的點,通常比直接展開多項式更穩定,但仍有浮點捨入誤差。以下為虛擬碼:
function deCasteljau(P0, P1, P2, P3, t):
Q0 = lerp(P0, P1, t) // (1-t)P0 + t P1
Q1 = lerp(P1, P2, t)
Q2 = lerp(P2, P3, t)
R0 = lerp(Q0, Q1, t)
R1 = lerp(Q1, Q2, t)
return lerp(R0, R1, t)利用中間結果可在指定 t 處分成兩條貝茲曲線,在數學上保持原形狀。t=0.5 的分割可作為編輯器「在曲線中加入節點」的基礎,但不能據此斷言每套編輯器的所有操作都使用同一實作。
S/T 何時會反射控制點?
只有前一個指令是 C 或 S 時,S 才會把前段最後的控制點對目前點做中心反射,作為新段第一個控制點;否則第一個控制點就是目前點。T 也只有接在 Q 或 T 後才反射,其他情況以目前點為控制點。
reflectedX = 2 * currentX - previousControlX
reflectedY = 2 * currentY - previousControlY
M 0,0 C 10,10 30,10 40,20 S 60,10 70,20
M 0,0 C 10,10 30,10 40,20 C 50,30 60,10 70,20這兩條路徑相同。相同次數、各段都以 t∈[0,1] 參數化時,反射會使接點的一階導數相同;不能省略前一指令的條件,將 S/T 當成任何接點都平滑的保證。
橢圓弧 A 的七個參數
A rx ry x-axis-rotation large-arc-flag sweep-flag x y- rx、ry 是橢圓兩軸的半徑;x-axis-rotation 是以度為單位的橢圓旋轉角。
- large-arc-flag 為 0 選不大於 180 度的弧,為 1 選不小於 180 度的弧;半圓時可能重合。
- sweep-flag 為 0 走負角度方向,為 1 走正角度方向;在一般 y 軸向下的 SVG 座標中,看起來分別是逆時針與順時針。
- x、y 指定終點。
通常有兩個通過端點的候選橢圓,各自又可選兩段弧,最多四種組合;半徑修正後可能出現相同形狀。負半徑取絕對值,任一半徑為零則畫直線,起終點相同則省略圓弧。因此不能用一個 A 表示完整的圓。
從端點形式換成中心形式
SVG 1.1 附錄 F.6.5 說明端點、半徑與旗標如何換成中心、起始角與掃掠角。x1、y1 是起點,x2、y2 是終點,rx、ry 是半徑,phi 對應旋轉角 φ,fA 是 large-arc-flag,fS 是 sweep-flag。以下先排除同點與零半徑,將半徑取絕對值,並將旋轉角 φ 從度換成弧度:
xp = cos(phi)*(x1-x2)/2 + sin(phi)*(y1-y2)/2
yp = -sin(phi)*(x1-x2)/2 + cos(phi)*(y1-y2)/2
lambda = (xp/rx)^2 + (yp/ry)^2
if lambda > 1:
rx *= sqrt(lambda)
ry *= sqrt(lambda)
sign = (fA != fS) ? 1 : -1
factor = sign * sqrt(max(0,
(rx^2*ry^2 - rx^2*yp^2 - ry^2*xp^2) /
(rx^2*yp^2 + ry^2*xp^2)))
cxp = factor * rx*yp/ry
cyp = factor * -ry*xp/rx
cx = cos(phi)*cxp - sin(phi)*cyp + (x1+x2)/2
cy = sin(phi)*cxp + cos(phi)*cyp + (y1+y2)/2
start = atan2((yp-cyp)/ry, (xp-cxp)/rx)
sweep = atan2((-yp-cyp)/ry, (-xp-cxp)/rx) - start
if !fS and sweep > 0: sweep -= 2*pi
if fS and sweep < 0: sweep += 2*pi先旋轉到橢圓座標系,再以 λ 判斷半徑是否足以連接端點;λ>1 時兩個半徑同乘 √λ。接著選取中心符號,轉回原座標,最後依 sweep-flag 修正角度方向。
虛擬碼中的 ^ 表示乘方,不是 JavaScript 的 XOR 運算子。max(0, …) 處理捨入造成的小幅負值。這段是解釋公式的虛擬碼,並非完整數值函式庫;極端值仍可能溢位,也不能用來保證特定編輯器的內部演算法。
用四種方式描述圓
以下以 (100,100) 為圓心、半徑 50,比較 circle 元素、兩段 A、四段 C 與四段 Q。後兩者是近似:
<circle cx="100" cy="100" r="50"/>
<path d="M 50,100 A 50,50 0 0 1 150,100 A 50,50 0 0 1 50,100"/>
<path d="M 100,50 C 127.614237,50 150,72.385763 150,100 C 150,127.614237 127.614237,150 100,150 C 72.385763,150 50,127.614237 50,100 C 50,72.385763 72.385763,50 100,50"/>
<path d="M 100,50 Q 150,50 150,100 Q 150,150 100,150 Q 50,150 50,100 Q 50,50 100,50"/>四段 C 使用經典係數 κ=4(√2−1)/3,未捨入時最大徑向誤差約為半徑的 0.0273%。它讓端點與中點落在圓上,並非每種誤差指標下的最佳係數。四段 Q 的近似誤差更大;多項式貝茲曲線一般不等於真正圓弧。
SVGO 的 convertShapeToPath 可透過 convertArcs 設定轉換 circle/ellipse,但不是「一律轉成四段 C」。改變元素表示也不一定縮小檔案。
G⁰、G¹、C¹、C² 的差異
表格若超出畫面寬度,可左右捲動。
| 條件 | 接點要求 |
|---|---|
| G⁰ | 位置相同,未保證沒有尖角 |
| G¹ | 位置與切線方向相同,假設接點正則 |
| C¹ | 位置與一階導數相同 |
| C² | 滿足 C¹,且二階導數相同 |
各段的參數範圍皆取 [0,1]。幾何上的曲率連續不等於 C²;S/T 的反射也只在上述條件下保證一階導數相同。SVG path 沒有直接表示 B-spline 或 NURBS 的指令,需要轉成可表示的分段或近似。
縮短 path 時要保留哪些條件?
- 省略重複指令,例如 L 10,10 L 20,20 改成 L 10,10 20,20。
- 比較絕對與相對座標,選擇較短的表示。
- 在符合反射條件時用 S/T 縮寫。
- 減少小數位、轉換基本形狀或合併可合併的路徑。
省略指令與捨入座標是不同操作。捨入會改變形狀,合併路徑也可能影響填色、標記、動畫與外部參照。保留原檔,依實際縮放比例與使用情境比較,不保證固定縮減率或完全相同的外觀。
重點整理
- path 有 10 類指令,M 的連續參數與 Z/z 有各自規則。
- 貝茲曲線可由控制點求值,de Casteljau 也可用於分割。
- S/T 的反射取決於前一指令。
- A 要處理退化情況、半徑修正、旗標與座標方向。
- 圓形近似與座標捨入不能當作精確保形。
參考資料與來源
編輯說明
本文使用 AI 協助編輯,並於發布前由編輯確認。內容仍可能包含事實、解讀或時效上的錯誤;進行重要判斷前,請查閱所列的一手資料或官方文件。

