# SVG 自學微筆記(09) - 路徑
###### tags: `2023` `SVG 自學微筆記`
> SVG 自學微筆記完! (๑´ㅂ`๑)
> 學習資源: [W3Schools](https://www.w3schools.com/graphics/svg_intro.asp)、其他網路資料
說到SVG中最複雜的東西,路徑(Path)絕對是一個大魔王,它有太多的commands可以用來定義路徑。透過Path雖然可以繪製效果不錯的SVG圖形,但是要自己定義一個個坐標點,再去把它們完美的串連在一起,實在是件非常困難的事。
W3Schools的SVG Path教學在最後提到,因為Path太複雜的關係,建議使用SVG Editor做圖形的設計,而非自己動手刻SVG的Path。儘管如此,稍微了解如何使用Path也能幫助看懂SVG圖形背後的邏輯與規則。
## SVG: 路徑
| 指令 | 意義(英) | 意義(中) |
| -------- | -------- | -------- |
| M | moveto | 移動路徑初始點 |
| L | lineto | 從當前點連線到另一點 |
| H | horizontal lineto | 從當前點水平連線到相同y坐標的一點 |
| V | vertical lineto | 從當前點垂直連線到相同x坐標的一點 |
| C | curveto | 從當前點畫貝茲曲線到指定點 (畫最基礎的貝茲曲線) |
| S | smooth curveto | 從當前點畫貝茲曲線到指定點 (與C同時使用,用處是鏡射前一個控制點) |
| Q | quadratic Bézier curve | 從當前點畫二次貝茲曲線到指定點 (共用控制點) |
| T | smooth quadratic Bézier curveto | 從當前點畫二次貝茲曲線到指定點 (與Q同時使用,用處是鏡射前一個共用控制點) |
| A | elliptical Arc | 畫橢圓圓弧 |
| Z | closepath | 關閉路徑 |
1. 要繪製貝茲曲線需要使用到"控制點"這個東西,至於控制點又是什麼呢? 簡單來說,可以把控制點視為控制曲線彎曲程度的點。
2. SVG Path的Commands有大小寫之分,大寫代表絕對位置(absolutely positioned),小寫則是相對位置(relatively positioned)。以`M 100 0 L 100 150`和`M 100 0 l 0 150`為例,兩者都是從(100,0)連線到(100,150),相對位置與絕對位置不同,它是以前一點做為出發位置並相對移動多少,可以想成在x、y上做加法計算。
### 範例1 - 基礎線
* M (moveto)
* 有2個可以帶入的參數x、y
* 移動起始點的座標
* L (lineto)
* 有2個可以帶入的參數x、y
* 從上一點連線到當前這一點
* Z (closepath)
* 沒有參數
* 關閉路徑,沒關閉路徑的話,描邊(Stroke)會有破洞
**有關閉路徑:**
![](https://i.imgur.com/mq9bHys.png)
移動初始點到(50,50),然後連線到(200,200),再連線到(50,200),最後關閉路徑。
```html=
<svg width="500" height="500">
<path d="M 50 50 L 200 200 L 50 200 Z" stroke="pink" stroke-width="4" ></path>
</svg>
```
**沒關閉路徑:**
![](https://i.imgur.com/BndRCD9.png)
移動初始點到(50,50),然後連線到(200,200),再連線到(50,200),最後不關閉路徑。
```html=
<svg width="500" height="500">
<path d="M 50 50 L 200 200 L 50 200" stroke="pink" stroke-width="4" ></path>
</svg>
```
### 範例2 - 水平線、鉛直線
* H
* 有1個可帶入參數x
* 從上一點水平連線到當前的x坐標
* V
* 有1個可帶入參數y
* 從上一點垂直連線到當前的y坐標
![](https://i.imgur.com/NOxSRuH.png)
藍色水平線,移動初始點到(50,50),然後水平連線到(200,50)。
紅色鉛直線,移動初始點到(100,60),然後垂直連線到(100,200)。
```html=
<svg width="500" height="500">
<path d="M 50 50 H 200" stroke="blue" stroke-width="4" ></path>
<path d="M 100 60 V 200" stroke="red" stroke-width="4" ></path>
</svg>
```
### 範例3 - 曲線、平滑曲線 (C、S不共用控制點)
* C
* 有6個可以帶入的參數x1、y1、x2、y2、x、y
* x1、y1是貝茲曲線的第一個控制點
* x2、y2是貝茲曲線的第二個控制點
* x、y是曲線的終點
![](https://i.imgur.com/2S3zytO.png)
(圖片取自[SVG 研究之路 (4) - Path 基礎篇](https://www.oxxostudio.tw/articles/201406/svg-04-path-1.html))
要畫出曲線,我們會需要透過控制點幫忙把曲線的彎曲弧度"拉"出來,上圖有2個控制點分別是(40,40)和(60,40),曲線始於(0,0)在(100,0)結束。
```html=
<svg width="500" height="500">
<path d="M 0 0 C 40 40 60 40 100 0" stroke="blue" fill="transparent"></path>
</svg>
```
* S
* 通常與C同時做使用
* 有4個可以帶入的參數x2、y2、x、y
* x1、y1是鏡射前一個控制點 (以相同斜率產生,不必帶入參數)
* x2、y2是貝茲曲線的第二個控制點
* x、y是曲線的終點
![](https://i.imgur.com/5aB2wGJ.png)
(圖片取自[SVG 研究之路 (4) - Path 基礎篇](https://www.oxxostudio.tw/articles/201406/svg-04-path-1.html))
要畫出曲線,我們會需要透過控制點幫忙把曲線的彎曲弧度"拉"出來,透過S可以只設定第二個控制點,而第一個控制點可以直接鏡射C的第二個控制點。
上圖使用C產生(0,0)到(100,0)的曲線,並使用S產生(100,0)到(200,0)的曲線,S那邊我們只給(150,-40)這個控制點,另外的控制點則直接複製(鏡射)前個控制點(60,40)的斜率產生,鏡射產生的控制點為(140,-40)。
```html=
<svg width="500" height="500">
<path d="M 0 0 C 40 40 60 40 100 0 S150 -40 200 0"
stroke="blue" fill="transparent"></path>
</svg>
```
### 範例4 - 二次曲線、平滑曲線 (Q、T共用控制點)
* Q
* 可以想成共用控制點的C
* 因為共用控制點,所以只需要一個控制點
* 有4個可以帶入的參數x1、y1、x、y
* x1、y1是貝茲曲線的第一個控制點(共用)
* x、y是曲線的終點
![](https://i.imgur.com/PyufhHr.png)
(圖片取自[SVG 研究之路 (4) - Path 基礎篇](https://www.oxxostudio.tw/articles/201406/svg-04-path-1.html))
與前面畫出曲線都要用到二個控制點不同,使用Q我們可以指定一個共用的控制點就得以畫出曲線。上圖我們將(50,50)定為共用控制點,曲線始於(0,0)在(100,0)結束。
```html=
<svg width="500" height="500">
<path d="M 0 0 Q 50 50 100 0" stroke="blue" fill="transparent"></path>
</svg>
```
* T
* 可以想成共用控制點的S
* 因為共用控制點,所以只需要一個控制點
* 有2個可以帶入的參數x、y
* x1、y1是鏡射前一個共用控制點 (以相同斜率產生,不必帶入參數)
* x、y是曲線的終點
![](https://i.imgur.com/OZRMIDV.png)
(圖片取自[SVG 研究之路 (4) - Path 基礎篇](https://www.oxxostudio.tw/articles/201406/svg-04-path-1.html))
T和S有十分相似的地方,它們都會鏡射前一個控制點,可以減少自訂控制點的數量。而兩者間的不同之處在於,T是共用控制點,而控制點是複製(鏡射)前一個共用控制點(50,50)斜率產生,鏡射產生的共用控制點為(150,-50)
```html=
<svg width="500" height="500">
<path d="M 0 0 Q 50 50 100 0 T 200 0"
stroke="blue" fill="transparent"></path>
</svg>
```
**A**比上面所有的指令都還要複雜,有興趣可以看這篇文章[SVG 研究之路 (5) - Path 進階篇](https://www.oxxostudio.tw/articles/201406/svg-05-path-2.html)或其他資料自行研究,這邊就不再細說。
## SVG: 編輯器
相信看完上面的所有內容,應該絕大多數人都不想自己用Path去刻SVG圖形吧? 這個時候,我們可以借助網路上各種大大小小的SVG Editor,透過GUI拖拉產生圖形的方式,使用網站自動產生的SVG原始碼,而不必花時間完全搞懂上面這些指令在做什麼。不過使用網路上的資源固然方便,也別忽略潛藏的資安風險!
[Boxy SVG Editor](https://boxy-svg.com/app) 就是我在網路上隨便找到的一個SVG編輯器,在畫布裡面編輯圖形,下面的視窗就會自動產生SVG Path的原始碼供參考。
![](https://i.imgur.com/bPXz9JI.png)
之後可能會出番外篇,用短篇說說我為什麼開始接觸、學習SVG。
## 參考資料
[SVG Path - W3Schools](https://www.w3schools.com/graphics/svg_path.asp)
[SVG 研究之路 (4) - Path 基礎篇](https://www.oxxostudio.tw/articles/201406/svg-04-path-1.html)
[SVG 研究之路 (5) - Path 進階篇](https://www.oxxostudio.tw/articles/201406/svg-05-path-2.html)