# 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)