SVG入門—如何手寫SVG

富途web開發團隊發表於2018-04-11

歡迎關注富途web開發團隊 ,缺人從眾

小編剛來公司的時候,有個需求需要做一個圖形動畫,當時本來想使用圖片做的。Toobug看了需求後,就說可以使用SVG做呀。小編當時對與SVG一點都不會呀。Toobug看我那無辜的表情,說沒事。我這有一本書 《SVG精髓》(作者:就是Toobug),你拿去看看,邊學邊做唄。

好吧,小編後面就看了一個星期的SVG精髓,現在也算入門了吧。

那麼今天小編也不是讓大家來買書的,只希望我們團隊 WillWang 翻譯的這篇SVG入門文章會對大家入門SVG有幫助。

正文

可縮放向量圖形的一大優勢(除了它們可以被無限縮放而沒有質量損失之外)是一旦你知道了基本的原理,無需開啟繪圖程式你就能很容易地手寫出一些簡單的形狀。

只要很少的幾行程式碼你就可以擁有你的自定義圖示,而且你還很清楚每個圖示是怎麼組合出來的。當你建立自己的 SVG 時,你可以確保以最有效的方式來編寫它們,並且當你在站點中使用它們時,你擁有最大的控制權。

在本教程中,我們將涵蓋手寫 SVG 的所有基本原理,但我不會用一個僅僅是丟出一系列相關形狀和屬性的文章來煩你們。相反,你們會通過實踐來學習如何手寫 SVG,建立出本教程開頭那張圖片上所列的6個圖示(線上示例)。在此過程中,你將會用到手寫 SVG 所需的所有基本元素。

說到那些基本元素,讓我們快速地介紹一下他們每一個的情況。

這些是你即將建立的圖示
這些是你即將建立的圖示

基本的 SVG 元素

你可以深入 SVG 複雜的細節,但這對我們即將建立的圖示不是必須的。以下列表涵蓋了我們將用到的構建塊。

  • <svg> 包裹並定義整個向量圖。<svg> 標籤之於向量圖就如同 <html> 標籤之於一個 web 頁面。
  • <line> 建立一條直線。
  • <polyline> 建立折線。
  • <rect> 建立矩形。
  • <ellipse> 建立圓和橢圓。
  • <polygon> 建立多邊形。
  • <path> 通過指定點以及點和點之間的線來建立任意形狀。
  • <defs> 定義一個可複用的圖形。初始情況下 <defs> 裡面的內容是不可見的。<defs> 標籤之於向量圖就如同 <head> 標籤之於一個 web 頁面。
  • <g> 將多種形狀組合起來。將組合後的形狀置於 <defs> 中可以讓它能夠被複用。
  • <symbol> 類似於一個組合,但是擁有一些額外的特性。通常被置於 <defs> 標籤中便於複用。
  • <use> 獲取在 <defs> 中定義的複用物件並在 SVG 中顯示出來。

當我們繼續閱讀並建立我們的圖示時,我們將以上面所看到的元素列表的順序進行。

起始檔案

在我們開始之前,從這個 GitHub 倉庫取一份起始檔案。你可以下載一個 .zip 格式的檔案或者直接將這個倉庫 clone 到本地。

我們將從一個已經包含了一些基本的 HTMLCSS 的檔案開始。這會給我們即將建立的 SVG 以一些樣式,也會在頁面上準備一些小網格。我們將會在這些網格上建立我們的圖示,希望它能在你放置你的 SVG 時幫助你確定座標。

當你開啟 Starter Files 目錄下的檔案 handcodedsvg.html 時,你應當會看到如下圖所示的樣子:

起始檔案

xy 值概述

在網站的二維平面上,用 x 代表橫軸,y 代表縱軸。每個座標軸上的位置都用數字表示。使用遞增的 x 值來讓物體右移,使用遞減的 x 值來讓物體左移。同樣地,使用遞增的 y 值來讓物體下移,使用遞減的 y 值來讓物體上移。

一個常用的表示某一點的 x 值和 y 值的簡寫是 (x, y)。例如,一個在 x 軸上的值為 10,在 y 軸上的值為 50 的點可以寫成 (10, 50)。在本教程中,我將不時地使用這個簡寫形式。

注意到我們網格中的那兩條最粗的線了嗎?我們將 SVG 的左上角與那兩條直線相交的地方對齊放置。因此,這個交點將在我們的 SVG 中代表 x=0y=0,即(0, 0) 的位置。

網格背景

每條最細的網格線之間相距 10px,中等粗細的線之間相距 100px。因此若我們想將一個物體從一箇中等粗細的線向下移動到另一箇中等粗細的線,我們只需把 y 軸上的值增加 100px

如果這聽起來仍然有點不清楚,不用擔心,在我們進行建立 SVG 圖示的實際操作時你就會明白了。

預設的 SVG 樣式

注意在初始的 HTML 檔案中有一些內嵌的 CSS 設定了我們即將建立的圖示的預設樣式。

svg {
  stroke: #000;
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}
複製程式碼

上述 CSS 設定了我們的圖示是無填充的,粗細 5px 的黑色線條繪製,邊角平滑。

1. 設定 SVG

建立任何 SVG 的第一步是寫下一個 <svg></svg> 元素。你所期望你的 SVG 顯示的所有內容都必須放在這個標籤內部。在這個元素上可以使用一些屬性,但為了保持簡單,我們只使用寬度和高度。

將下面的程式碼新增到你的 HTML 文件的 <body> 標籤裡去:

<svg width="750" height="500">

</svg>
複製程式碼

注意:在我們的起始檔案中的 CSS 會將這個 SVG 向下和向右各偏移 100px,以此保證 SVG 的左上角被置於背景網格中兩條最粗的直線的交點處。在本教程的 CodePen 演示中的值也可能會稍有不同——但可以隨意地對它們進行操作。

2. 建立 左對齊 圖示

讓我們從使用 <line> 元素建立這個左對齊圖示開始:

左對齊圖示

你會用到 line 元素的4個屬性:

  • x1:起點的水平軸座標
  • y1:起點的豎直軸座標
  • x2:終點的水平軸座標
  • y2:終點的豎直軸座標

綜上,你會使用屬性 x1y1 來設定直線的起點,使用屬性 x2y2 來設定直線的終點。

讓我們建立我們的圖示的第一條線,即頂部的那條。我們打算讓線長 45px,然而我們使用的 5px 粗細的筆畫會在我們的線條外增加一些額外的畫素。因此我們需要將線條向右下角偏移 3px 以確保所有因 stroke 產生的額外畫素都不會被剪掉。

基於上述原因,我們從 x 軸的座標 3y 軸的座標 3 處開始我們的直線。我們可以用屬性 x1="3" y1="3" 來設定線的起點為 (3, 3)

我們打算讓線長 45px,所以在起點的 x 軸座標值 3 上加上 45 得到 x2 的值為 48。我們想讓直線在水平軸上的相同位置結束,因此設定 y2 等於 3,也就是與 y1 相等的值。通過屬性 x2="48" y2="3" 設定了線的終點 (48, 3)

這第一根線的完整程式碼看起來應該是這樣的:

<line x1="3" y1="3" x2="48" y2="3"></line>
複製程式碼

檢視你瀏覽器中的預覽,你會看到一條長 45px 的圓潤黑線。

現在我們可以繼續給我們的圖示新增接下來的三條線。我們打算最終畫出四條線。第一和第三根線長 45px,第二和第四根線長 62px。我們還想要在每條線之間有 16px 的垂直間距。

我們可以通過如下的程式碼得到這個圖示:

<line x1="3" y1="3" x2="48" y2="3"></line>
<line x1="3" y1="19" x2="65" y2="19"></line>
<line x1="3" y1="35" x2="48" y2="35"></line>
<line x1="3" y1="51" x2="65" y2="51"></line>
複製程式碼

注意:每條線的 y 值以 16px 遞增來建立所需的垂直間距。

再看一看你的瀏覽器預覽,你應該看到所有的四條線。你也可以直接在下面的 codepen 中編輯 SVG:

程式碼詳情:codepen.io/new4/

在我們繼續之前先註釋掉你的圖示

有了這些程式碼,你的第一個圖示就已經完成了。我們已經準備好繼續去建立下一個圖示了,我們想在網格的相同位置上建立這個圖示,但現在 左對齊 圖示占著這個位置。因此,現在需要註釋掉它的程式碼來清理空間。稍後當我們將圖示轉換為可重用部件時,我們會回過頭來恢復被註釋掉的程式碼。

你需要對我們之後建立的每一個圖示做同樣的事情,即在完成建立之後將其註釋掉。出於這個原因,在每個圖示的程式碼之上新增一個小提示或許是個不錯的注意,這樣在之後回顧的時候你就知道哪個是哪個了。

3. 建立一個 插入 圖示

對於這個圖示,讓我們使用直線 <line> 元素衍生而來的折線元素:即 <polyline>。我們將會使用它來建立一個指向右方的插入符。

插入符

<polyline> 元素只有一個屬性:points。在這裡你會使用一對對的數字來設定一系列的點。點和點之間的線段會自動繪製出來。數值對就簡單地一個接一個的被寫在點屬性裡。可以使用逗號分隔,但這不是必須的。為了便於閱讀,你可能還想在程式碼中將每一對值寫成一行。

我們會在上一個圖示的起始點處開始我們的 插入 圖示,那就是 (3, 3),這確保了我們的筆畫和線的端頭不會被剪掉。我們想讓第二個點向右移動,並向下移 25px,那麼我們把它設為 (30,28)。我們的第三個點應該與第一個點垂直對齊,同時再向下移動 25px,所以它應被設為 (3,53)

你可以把這些點新增到 <polyline>points 屬性中去,如下:

<polyline points="
  3 3
  30 28
  3 53
"></polyline>
複製程式碼

如果你想要更簡潔的程式碼,你也可以把上面的程式碼寫成:

<polyline points="3 3, 30 28, 3 53"></polyline>
複製程式碼

或者

<polyline points="3 3 30 28 3 53"></polyline>
複製程式碼

看一看你的瀏覽器預覽,你會看到你的 插入 圖示的顯示:另一個圖示就這樣完成了!

程式碼詳情:codepen.io/new4/

同樣地,在進入下一個圖示之前先註釋掉當前這個圖示,並給它加上一個能讓你知道它是什麼圖示的小提示。

4. 建立一個 瀏覽器 圖示

現在我們有了線條,讓我們從矩形(<rect>)開始建立一些形狀。我們將把它與一些 <line> 結合起來建立一個 瀏覽器 圖示。

瀏覽器

長方形和正方形可以通過 <rect> 元素來建立。<rect> 有4個需要提供值的屬性:

  • x:左上角的 x 軸座標值
  • y:左上角的 y 軸座標值
  • width:矩形的寬度
  • height:矩形的高度

注意:你也可以使用屬性 rxry 來指定矩形的圓角半徑。

我們要建立一個矩形,它的左上角有 3px 的偏移量,同樣是為了避免描邊的截斷,所以我們會用到 x="3" y="3" 的屬性值。我們希望它是寬 80px,高 60px 的,所以我們用到 width="80" height="60" 的屬性值。

因此我們完整的矩形程式碼就應該是:

<rect x="3" y="3" width="80" height="60"></rect>
複製程式碼

儲存程式碼,到瀏覽器裡面進行預覽。你應該看到一個整潔的小矩形。

現在我們所要做的就是在頂部新增一條水平線,還有在靠近左上角的地方加上一條豎線,就像你在本節開始時所看到影像中的那樣。我們將使用與之前繪製線段相同的過程,完整的 瀏覽器 圖示程式碼看起來應該是這樣的:

<rect x="3" y="3" width="80" height="60"></rect>
<line x1="3" y1="19" x2="83" y2="19"></line>
<line x1="20" y1="3" x2="20" y2="17"></line>
複製程式碼

花點時間檢視一下這兩條線段的屬性所提供的座標,你可以稍微改變一下它們的值來看看它們在這個圖示中是如何工作的。

程式碼詳情:codepen.io/new4/

5. 建立一個 警示 圖示

現在我們可以控制矩形的建立,我們再試試使用 <ellipse>。我們將使用兩個 <ellipse> 以及一個 <line> 來建立這個 警示 的圖示。

警示

類似於矩形,<ellipse> 元素也需要4個屬性,然而這些屬性和矩形的不同。我們使用的是水平和豎直半徑而不是寬度和高度,同樣地,我們通過中心而不是通過指定左上角來進行定位。

  • cx:中心位置在 x 軸上的座標
  • cy:中心位置在 y 軸上的座標
  • rx:沿 x 軸向的半徑,也就是它會把圖形分割成上下兩部分
  • ry:沿 y 軸向的半徑,也就是它會把圖形分割成左右兩部分

我們想要一個寬 80px80px 的正圓,這意味著在兩個軸上它的半徑均為 40px。我們用 rx="40" ry="40" 來設定這個值。

我們還想要這個圓處於與圖上那兩條最粗的線平齊的位置。假定我們的圓寬高均是 80px,那麼放置圓心的位置就是 40px。同時為了避免圖示被截斷,需要 3px 的偏移量,那麼圓的中心點就在兩軸的 43px 處。我們用屬性 cx="43" cy="43" 來設定這個值。

將這些設定的屬性值放在一起,就得到如下程式碼:

<ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
複製程式碼

檢視你的瀏覽器預覽,現在在你的頁面上應該能看到一個圓。

現在我們要新增第二個圓,建立感嘆號底部的那個點。我們將以同樣的方式建立它,唯一的區別是我們將使用內聯樣式來設定黑色的填充:

<ellipse style="fill:black;" cx="43" cy="65" rx="5" ry="5"></ellipse>
複製程式碼

最後,我們只需要新增感嘆號另外的線段部分。同樣地,我們使用的技術與我們之前建立線段的一樣,唯一的區別是我們將使用內聯風格來將筆畫的寬度從 5px 增加到 8px

警示 圖示的完整程式碼如下:

程式碼詳情:codepen.io/new4/

6. 建立一個 播放 圖示

現在我們已經有一些如矩形和橢圓形這樣外形相對固定的形狀,我們準備使用 <polygon> 元素來生成我們自己的形狀。從八邊形到五角星,我們可以用這個元素建立出我們想要的多邊形。不過,我們現在就把事情弄清楚並建立一個三角形。我們將把它與一個 <ellipse> 元素組合在一起來建立一個 播放 圖示:

播放

<polygon> 元素和 <polyline> 元素幾乎一樣。他們都只有一個 points 屬性,採用一對對的值的形式來設定每一個點從而組成一個形狀。不同之處在於,折線 <polyline> 不是閉合的而多邊形 <polygon> 是自動閉合的。

讓我們從下面這個圓開始,我們的多邊形會放在它裡面。我們使用的圓與我們在警告圖示裡面使用的相同:

<ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
複製程式碼

現在我們來建立多邊形。我們將會放置三個點,這些點之間會自動生成線段來建立一個三角形。點將是 (35,23)(60,43)(35,63)。如此,我們的多邊形程式碼將會是:

<polygon points="35 23, 60 43, 35 63" />
複製程式碼

播放 圖示的完整程式碼如下:

程式碼詳情:codepen.io/new4/

7. 建立一個 下載 圖示

現在,我們將學習最複雜的,但同時也是最靈活的生成 SVG 圖形的方法,即 <path> 元素。建立一個路徑有點像建立一個多邊形,每次僅需將你的形狀的一部分展示出來。然而,在路徑中你直接建立每一個點,自定義每一條線,你還可以選擇在點之間建立曲線而不是直線。

路徑可以用來建立任何東西,但如果超出一定程度的複雜性之後,你最好還是使用向量設計應用程式,而不是手寫程式碼。出於這個原因,我們將重點關注一小部分路徑功能,並使用它來建立這個 下載 圖示:

下載

從技術上講,你可以使用多邊形來建立上面這個形狀,但是這個箭頭可以很好地幫助我們弄清楚路徑元素是怎麼工作的。

我們將會只用到 <path> 的屬性 dd 代表 data,在這裡,你將定義路徑的所有點和線。在這個屬性裡,設定路徑點和在點之間建立連線的命令是由諸如 ML 這樣的單個字母來提供的,然後是一組 x 和/或 y 座標。

這樣的命令有很多,但本文只是介紹 <path> 的使用,我們將只介紹一些在手動編碼時可以實際使用的命令。

  • M 表示移動到(moveto)。它用 x 值和 y 值來給定一條新的路徑的起始點。可以想象成把你的滑鼠放在畫布上的某一點以準備開始繪畫。大寫的 M 表示移動到一個絕對座標集合(小寫的 m 表示移動到一個相對座標集合)。
  • L 表示劃線到(lineto)。從當前位置到新的位置畫一條線。大寫的 L 表示移動到一個絕對座標集合(小寫的 l 表示移動到一個相對座標集合)。
  • Z 表示閉合路徑。通過在當前點和路徑的起始點之間畫一條直線來閉合形狀。

你一定要看下這三個命令(以及我們將用它們建立的圖示)作為入門 <path> 元素的讀物。要真正掌握它,你可以自行去熟悉路徑的所有命令

編寫你的 下載 圖示

要對 下載 圖示路徑進行編碼,建議先新增一個空路徑元素:

<path d="
 
"></path>
複製程式碼

從這裡開始,一次新增一個命令,儲存並檢視圖示形狀的進展,這樣你就可以看到它是如何被建立出來的。我還建議將每個命令寫成一行以提高可讀性。

  • 首先,我們移動到點 (18, 3) 處,這是我們的箭頭開始的位置。為了完成這個動作,需要在路徑的屬性 d 中增加命令 M 18 3
  • 接著我們想使用 L 命令來從起始點開始沿著 x 軸畫出一條 28px 的線段。為了完成這個動作,我們給屬性 d 新增第二個命令:L 46 3。檢視你瀏覽器預覽,你會看到一條水平的短橫線。
  • 現在用 L 46 40 直接向下畫一條 37px 的線。
  • 然後用 L 61 40 直接向右進 15px
  • 接下來,我們要開始建立箭頭點。我們需要向左下方畫一條斜線。我們用 L 32 68 完成它。
  • 然後用 L 3 40 畫一條向左上方的斜線。
  • 現在我們用 L 18 40 來向右邊畫一條線以完成我們的箭頭。
  • 為了使我們的形狀閉合,我們無需通過指定一個點來畫一條直線。我們所要做的就是新增 Z 命令,它會自動閉合我們的形狀。

最終的箭頭圖示程式碼如下:

<path d="
  M 18 3
  L 46 3
  L 46 40
  L 61 40
  L 32 68
  L 3 40
  L 18 40
  Z
"></path>
複製程式碼

關於使用 <path> 的更多資訊可以檢視本文末尾附上的引用文章。

程式碼詳情:codepen.io/new4/

8. 新增 <defs> 元素

我們已經完成了6個圖示的編碼工作,現在我們可以在我們的 SVG 中準備好放置和重用它們。

為了做到這個,我們要將我們的6個圖示程式碼(目前已經被註釋掉了)用 <defs></defs> 包裹起來:

<defs>
<!-- 到目前為止,你建立的所有圖示都在這裡 -->
</defs>
複製程式碼

這樣做會告訴系統,目前我們完成的所有圖示在我們明確地去使用它們之前預設都是隱藏的。

現在,你可以去掉對每個圖示的註釋,它們不會出現在頁面上。

9. 用 <g> 建立組合物件

有兩種方法可以使我們的圖示隨時可用:將它們轉換為組合,或轉換為模板。我們將把前面的一半圖示轉換成組合,然後把剩下的一半變成模板,這樣我們就可以說明他們之間的區別。

要把我們的一個圖示轉換成一個組合,我們要做的就是用標籤 <g></g> 來包裹它。為了使這個組合可用,我們還需要給它一個唯一的ID

例如:

<g id="leftalign">
    <!-- 左對齊圖示 -->
    <line x1="3" y1="3" x2="48" y2="3"></line>
    <line x1="3" y1="19" x2="65" y2="19"></line>
    <line x1="3" y1="35" x2="48" y2="35"></line>
    <line x1="3" y1="51" x2="65" y2="51"></line>
</g>
複製程式碼

<g></g> 將你最開始建立的3個圖示分別包裹起來,並新增上唯一ID,如下:

<g id="leftalign">
    <!-- 左對齊圖示 -->
    <line x1="3" y1="3" x2="48" y2="3"></line>
    <line x1="3" y1="19" x2="65" y2="19"></line>
    <line x1="3" y1="35" x2="48" y2="35"></line>
    <line x1="3" y1="51" x2="65" y2="51"></line>
</g>

<g id="rightcaret">
    <!-- 插入圖示 -->
    <polyline points="
    3 3
    30 28
    3 53
    "></polyline>
</g>

<g id="browser">
    <!-- 瀏覽器圖示 -->
    <rect x="3" y="3" width="80" height="60"></rect>
    <line x1="3" y1="19" x2="83" y2="19"></line>
    <line x1="20" y1="3" x2="20" y2="17"></line>
</g>
複製程式碼

10. 使用 <use> 來放置組合

<defs> 元素內部我們現在有三個圖示被定義成組合,我們準備在 SVG 中使用它們。為了使用它們,我們需要做的就是新增一個 <use> 元素(確保在 <defs> 元素以外且之後的地方新增它),並設定一個 href 屬性指向想要的那個圖示的 ID

例如,新增下面的程式碼來使用 左對齊 圖示:

<use href="#leftalign"></use>
複製程式碼

通過指定 xy 的值來將圖示放置到特定的位置:

<use href="#leftalign" x="100" y="100"></use>
複製程式碼

新增所有三個圖示並把它們分開排放的程式碼看起來是這樣的:

<use href="#leftalign" x="100" y="100"></use>
<use href="#rightcaret" x="300" y="100"></use>
<use href="#browser" x="500" y="100"></use>
複製程式碼

檢視瀏覽器,你應該會看到這樣的三個圖示:

組合

11. 使用 symbols 建立模板物件

除了組合之外,你也可以使用模板來定義你的圖示。模板幾乎和組合一樣,但是你可以獲得額外的設定來控制視口(viewbox)和長寬比。

如果你想要把我們目前建立的圖示設定為居中,這將非常有用。我們將把剩下的三個圖示轉換成模板,然後使它們垂直填充100畫素高的空間,並在這個空間中水平居中。

我們以與建立組合相同的方式來建立我們的模板,只是將我們最後三個圖示的程式碼包裹進 <symbol></symbol> 模板中。我們也需要給每個模板加一個唯一的 ID

但是我們也需要新增一個叫做 viewBox 的屬性。該屬性讓我們可以定義每個模板的可見部分應該是什麼。當瀏覽器能夠訪問這些資訊時,它就可以正確地縮放和排列模板。

我們需要給 viewBox 屬性4個值。前兩個定義圖示的左上角,第三和第四分別定義它的寬度和高度。

從我們的 警示 圖示開始,它的寬高都是 86px,所以我們設定它的 viewBox 屬性值為 0 0 86 86,如下:

<symbol id="alert" viewBox="0 0 86 86">
    <!-- 警示圖示 -->
    <ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
    <ellipse style="fill:black;" cx="43" cy="65" rx="5" ry="5"></ellipse>
    <line style="stroke-width: 8;" x1="43" y1="19" x2="43" y2="48"></line>
</symbol>
複製程式碼

播放 圖示的寬高也是 86px下載 圖示寬 64px71px。因此我們圖示模板相應的程式碼應該是:

<symbol id="alert" viewBox="0 0 86 86">
    <!-- 警示圖示 -->
    <ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
    <ellipse style="fill:black;" cx="43" cy="65" rx="5" ry="5"></ellipse>
    <line style="stroke-width: 8;" x1="43" y1="19" x2="43" y2="48"></line>
</symbol>

<symbol id="play" viewBox="0 0 86 86">
    <!-- 播放圖示 -->
    <ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
    <polygon points="35 23, 60 43, 35 63" />
</g>

<symbol id="download" viewBox="0 0 64 71">
    <!-- 下載圖示 -->
    <path d="
    M 18 3
    L 46 3
    L 46 40
    L 61 40
    L 32 68
    L 3 40
    L 18 40
    Z
    "></path>
</symbol>
複製程式碼

12. 使用 <use> 來放置模板

現在,我們可以像使用我們的組合一樣使用我們的模板圖示。不過我們也會提供已經設好了寬高屬性為 100px 的圖示:

<use href="#alert" x="100" y="200" width="100" height="100"></use>
<use href="#play" x="300" y="200" width="100" height="100"></use>
<use href="#download" x="500" y="200" width="100" height="100"></use>
複製程式碼

你會看到每個基於模板的圖示都整齊地填充並居中在長寬 100px 的空間內:

模板

試著給使用基於組合圖示的 <use> 元素上新增寬高的屬性。你會發現沒什麼變化。這是因為瀏覽器依靠的是 viewBox 的值(組合沒有這個值)來確定如何縮放圖示。

總結

以下是完整的程式碼:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Hand Coded SVG</title>
  <style>
    html,
    body {
      height: 100%;
      width: 100%;
      background: #e9e9e9;
    }

    body {
      margin: 0;
      text-align: center;
    }

    .grid {
      width: 750px;
      height: 500px;
      margin: 0 auto;
      padding-top: 100px;
      padding-left: 100px;
      background-image: url('grid.png');
      position: relative;
    }

    .grid::before {
      content: "";
      border-left: 1px solid #7c7cea;
      position: absolute;
      top: 0;
      left: 100px;
      width: 750px;
      height: 600px;
    }

    .grid::after {
      content: "";
      border-top: 1px solid #7c7cea;
      position: absolute;
      top: 100px;
      left: 0;
      width: 850px;
      height: 500px;
    }

    svg {
      stroke: rgb(0, 0, 0);
      stroke-width: 5;
      stroke-linecap: round;
      stroke-linejoin: round;
      fill: none;
    }
  </style>
</head>

<body>
  <div class="grid">
    <svg width="750" height="500">
      <defs>
        <g id="leftalign">
          <!-- Left align icon made with lines -->
          <line x1="3" y1="3" x2="48" y2="3"></line>
          <line x1="3" y1="19" x2="65" y2="19"></line>
          <line x1="3" y1="35" x2="48" y2="35"></line>
          <line x1="3" y1="51" x2="65" y2="51"></line>
        </g>

        <g id="rightcaret">
          <!-- Right caret icon made with a polyline -->
          <polyline points="
            3 3
            30 28
            3 53
          "></polyline>
        </g>

        <g id="browser">
          <!-- Browser icon made with rectangle and lines -->
          <rect x="3" y="3" width="80" height="60"></rect>
          <line x1="3" y1="19" x2="83" y2="19"></line>
          <line x1="20" y1="3" x2="20" y2="17"></line>
        </g>

        <symbol id="alert" viewBox="0 0 86 86">
          <!-- Alert icon made with ellipses and a line -->
          <ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
          <ellipse style="fill:black;" cx="43" cy="65" rx="5" ry="5"></ellipse>
          <line style="stroke-width: 8;" x1="43" y1="19" x2="43" y2="48"></line>
        </symbol>

        <symbol id="play" viewBox="0 0 86 86">
          <!-- Play icon made with ellipse and polygon -->
          <ellipse cx="43" cy="43" rx="40" ry="40"></ellipse>
          <polygon points="35 23, 60 43, 35 63" />
          </g>

          <symbol id="download" viewBox="0 0 64 71">
            <!-- Download icon made with path -->
            <path d="
                M 18 3
                L 46 3
                L 46 40
                L 61 40
                L 32 68
                L 3 40
                L 18 40
                Z
            "></path>
          </symbol>
      </defs>
      <use href="#leftalign" x="100" y="100"></use>
      <use href="#rightcaret" x="300" y="100"></use>
      <use href="#browser" x="500" y="100"></use>
      <use href="#alert" x="100" y="200" width="100" height="100"></use>
      <use href="#play" x="300" y="200" width="100" height="100"></use>
      <use href="#download" x="500" y="200" width="100" height="100"></use>
    </svg>
  </div>
</body>

</html>
複製程式碼

這就涵蓋了手寫 SVG 的要點了!讓我們總結一下我們所學到的:

  • 設定你的 <svg> 元素來包裹你的整個圖形。
  • 使用 <line><polyline> 來創造線。
  • 使用 <rect>, <ellipse><polygon> 來創造閉合的圖形。
  • 使用 <path> 來創造你想要的任何形狀。
  • 使用 <g> 來組合形狀。
  • 對於需要有額外特性的組合使用 <symbol>
  • 使用 <defs> 元素定義組合和模板。
  • 使用 <use> 元素來放置你定義的組合和模板。

通過本教程我們打下了堅實的基礎,但是你還可以使用 SVG 做更多的事情,所以不要止步於此,繼續挖掘並發現更多可以實現的令人讚歎的東西!

與此同時,希望你不再完全依賴於向量設計應用程式來建立 SVG,並且你有信心可以手寫一些自己的圖形。對於更復雜的圖形來說,設計類應用仍然是一種可行的方法,但是你可以利用你所掌握的構建模組做很多事,獲得手寫程式碼帶來的速度和控制方面的優勢。

相關連結


原文:How to Hand Code SVG

作者:Kezz Bracey

譯者:WillWang