一個深入的SVG教程
SVG是一個令人驚嘆且非常強大的圖像格式。本教程將通過簡單易懂的方式提供SVG的概述,以解釋您需要知道的一切。
- 簡介
- SVG的優勢
- 您的第一個SVG圖像
- 使用SVG
- SVG元素
- SVG視口和viewBox
- 將SVG插入Web頁面
- 使用數據URL內聯SVG
- 樣式化元素
- 使用CSS或JavaScript與SVG交互
- SVG vs Canvas API
- SVG符號
- 驗證SVG
- 是否應該包含
xmlns
屬性? - 是否需要擔心瀏覽器支持?
簡介
儘管SVG(可縮放矢量圖形)在2000年代初已經定為標準,但它仍然是如今的熱門話題。
多年來,由於瀏覽器的支持(尤其是IE),SVG一直受到懲罰。
我在一本2011年的書中找到了這樣的語句:“在寫作時,將SVG直接嵌入HTML只適用於最新的瀏覽器。”這句話已經過去7年了,現在我們可以安全地使用SVG圖像。
今天,除非您有很多使用IE8及以下版本或舊版Android設備的用戶,否則我們可以安全地使用SVG圖像,此時可使用回退選項。
SVG之所以取得一部分成功,部分原因是我們必須支持各種屏幕顯示器,具有不同的分辨率和尺寸。這是SVG的理想任務。
此外,近年來Flash的急劇衰落,使SVG重新引起人們的興趣,這對於過去Flash完成的許多工作來說是一個很好的選擇。
SVG是一種矢量圖像文件格式。這使它們與PNG、GIF或JPG等光柵圖像文件格式完全不同。
SVG的優勢
由於是矢量圖像,SVG圖像可以進行無限縮放,並且在圖像質量下降方面沒有任何問題。為什麼這樣呢?因為SVG圖像使用XML標記來構建,瀏覽器通過繪製每個點和線而打印它們,而不是使用預定義的像素填充某些空間。這保證了SVG圖像可以適應不同的屏幕尺寸和分辨率,甚至還有尚未發現的尺寸。
由於在XML中定義,SVG圖像比JPG或PNG圖像更靈活,我們甚至可以使用CSS和JavaScript與之交互。SVG圖像甚至可以包含CSS和JavaScript。
SVG圖像可以以比其他格式更小的方式渲染矢量風格圖像,主要用於商標和插圖。另一個巨大的用例是圖標,曾經是FontAwesome之類的圖標字體的範疇,現在設計師更喜歡使用SVG圖像,因為它們更小,並且可以具有多色圖標。
SVG很容易實現動畫效果,這是一個很酷的主題。
SVG提供了一些圖像編輯效果,例如遮罩和裁剪、應用過濾器等。
SVG只是文本,因此可以使用GZip進行高效壓縮。
您的第一個SVG圖像
SVG圖像使用XML進行定義。這意味著,如果您瞭解HTML,則SVG看起來會非常熟悉,只不過,與用於文檔構建(如p
,article
,footer
,aside
)的標籤不同,在SVG中我們有用於矢量圖像構建的基本元素:path
,rect
,line
等。
這是一個示例SVG圖像:
1 | <svg width="10" height="10"> |
請注意,它非常容易讀取和理解圖像的外觀:這是一個簡單的10x10像素(默認單位)的藍色矩形。
大多數情況下,您不需要編輯SVG代碼,而是使用諸如Sketch、Figma或任何其他矢量圖形工具來創建圖像,然後導出為SVG。
當前版本的SVG是1.1版本,SVG 2.0版本正在開發中。
使用SVG
可以通過將SVG包含在img
標籤中來顯示SVG圖像:
1 | <img src="image.svg" alt="My SVG image" /> |
就像您對其他基於像素的圖像格式所做的那樣:
1 | <img src="image.png" alt="My PNG image" /> |
此外,非常特別的是,SVG可以直接包含在HTML頁面中:
1 |
|
為了使用減少FOUT(無內容過早渲染),應將CSS放在頂部。
請注意,HTML5和XHTML對內聯SVG圖像需要不同的語法。幸運的是,XHTML已經成為過去,因為它比必要的更複雜,但是如果您仍然需要使用XHTML頁面,這也值得一試。
將SVG內聯在HTML中的能力使這種格式在場景中成為一只獨角獸,其他圖像無法實現這一點,它們必須通過打開單獨的請求來獲取。
SVG元素
在上面的示例中,您看到了對rect
元素的使用。SVG具有許多不同的元素。
其中最常用的有:
text
:創建文本元素circle
:創建圓圈rect
:創建矩形line
:創建直線path
:在兩點之間創建路徑textPath
:在兩點之間創建路徑和連接的文本元素polygon
:可創建任何類型的多邊形g
:將多個元素分組
座標從繪圖區域的左上角的0,0開始,x的區域從左到右,y的區域從上到下。
您看到的圖片反映了上面顯示的代碼。使用瀏覽器的DevTools,您可以對其進行檢查和更改。
text
text
元素添加文本。可以使用鼠標選擇文本。x
和y
定義文本的起始點。
1 | <svg> |
circle
定義一個圓。cx
和cy
是圓心坐標,r
是半徑。fill
是常用的屬性,表示圖形的顏色。
1 | <svg> |
rect
定義一個矩形。x
、y
是起始座標,width
和height
是解釋性的。
1 | <svg> |
line
x1
和y1
定義起始座標,x2
和y2
定義結束座標。stroke
是常用的屬性,表示線條的顏色。
1 | <svg> |
path
路徑是一系列線條和曲線。它是使用SVG繪制的最強大的工具,因此也是最複雜的。
d
包含指示命令。這些命令以命令名開始,然後是一組坐標:
M
表示移動,接受一組坐標x,yL
表示線段,接受一組坐標x,y進行線段繪製H
是水平線,僅接受一個x坐標V
是垂直線,僅接受一個y坐標Z
表示關閉路徑,將線返回到起點A
表示弧形,它需要一個完整的自己的教程Q
是一個二次貝塞爾曲線,同樣需要一個完整的自己的教程
1 | <svg height="300" width="300"> |
textPath
在路徑元素的形狀上添加文本。
1 | <svg |
polygon
使用polygon
繪製任意的多邊形。points
表示多邊形應該連接的一組x、y坐標:
1 | <svg> |
g
使用g
元素可以分組多個元素:
1 | <svg width="200" height="200"> |
SVG視口和viewBox
相對於其容器,SVG的大小由svg
元素的width
和height
屬性設置。這些單位默認為像素,但您可以使用任何其他常用單位,例如%
或em
。這就是視口。
一般來說,“容器”表示瀏覽器窗口,但是
svg
元素可以包含其他svg
元素,此時容器是父級svg
。
一個重要的屬性是viewBox
,它允許您在SVG畫布內部定義一個新的座標系統。
假設您有一個簡單的圓,位於200x200像素的SVG中:
1 | <svg width="200" height="200"> |
通過指定viewBox,您可以選擇僅顯示此SVG的一部分。例如,您可以從點0,0開始,僅顯示100x100像素的畫布:
1 | <svg width="200" height="200" viewBox="0 0 100 100"> |
如果從100,100開始,您將看到另一個部分,即圓的右下角:
1 | <svg width="200" height="200" viewBox="100 100 100 100"> |
一個偉大的方式來可視化這一點是想象谷歌地圖是一個巨大的SVG圖像,而您的瀏覽器是一個視口,大小與窗口大小一樣。當您移動時,視口的開始點(x,y)坐標發生變化,當您調整窗口大小時,視口的寬度和高度也會發生變化。
在Web頁面中插入SVG
有多種方法可以將SVG添加到Web頁面中。
最常見的方法包括:
- 使用
img
標籤 - 使用CSS的
background-image
屬性 - 內聯在HTML中
- 使用
object
,iframe
或embed
標籤
可以在Glitch上查看所有這些示例:https://glitch.com/edit/#!/flavio-svg-loading-ways
使用img
標籤
1 | <img src="flag.svg" alt="Flag" /> |
使用CSS的background-image
屬性
1 | <style> |
內聯在HTML中
1 | <svg |
使用object
,iframe
或embed
標籤
1 | <object data="flag.svg" type="image/svg+xml"></object> |
使用embed
,您可以使用以下代碼從父文檔中獲取SVG文檔:
1 | document.getElementById('my-svg-embed').getSVGDocument() |
從SVG內部您可以使用以下代碼引用父文檔:
1 | window.parent.document |
如果SVG使用img
標籤加載,或將其作為背景使用CSS,則無論起源如何:
- CSS和JavaScript無法與之交互
- SVG中的JavaScript被禁用
- 無法加載圖像、樣式表、腳本、字體等外部資源
詳情
功能 | 內聯SVG | object /embed /iframe |
img |
---|---|---|---|
可與用戶交互 | ✅ | ✅ | ✅ |
支持動畫 | ✅ | ✅ | ✅ |
可以運行自己的JavaScript | ✅ | ✅ | ❌ |
可以從外部腳本進行操作 | ✅ | ❌ | ❌ |
在HTML中內嵌的SVG圖像絕對是最強大和靈活的方式,這也是執行某些SVG操作的唯一方式。
如果需要使用img
,object
或embed
載入SVG,則僅當不需要與之交互時,只需在頁面中顯示它,這將非常方便,尤其是如果在不同的頁面中重複使用SVG圖像,或者SVG大小非常大。
SVG內部的CSS
將CSS放在CDATA中:
1 | <svg> |
SVG文件中還可以包含外部樣式表:
1 |
|
SVG內部的JavaScript
您可以首先放置JavaScript,並在load
事件中對其進行封裝,以在頁面完全加載並將SVG插入到DOM時執行它:
1 | <svg> |
或者,如果您將JS放在其他SVG代碼末尾,以確保JavaScript在頁面上出現SVG時運行:
1 | <svg> |
就像html標籤一樣,SVG元素也可以具有id
和class
屬性,因此可以使用選擇器API將它們引用:
1 | <svg> |
在SVG中查看此功能的示例,可以參考這個Glitch項目:https://glitch.com/edit/#!/flaviocopes-svg-script
SVG外部的JavaScript
如果可以與SVG交互(SVG在HTML中內聯),則可以使用JavaScript更改任何SVG屬性,例如:
1 | document.getElementById("my-svg-rect").setAttribute("fill", "black"); |
或者任何其他DOM操作。
SVG外部的CSS
您可以使用CSS更改SVG圖像的任何樣式。
SVG屬性可以在CSS中輕松覆蓋,它們對CSS具有較低的優先級。它們的行為不像內聯CSS,後者的優先級更高。
1 | <style> |
SVG vs Canvas API
Canvas API是Web平臺的一個重要功能,它與SVG具有類似的瀏覽器支持。它與SVG的主要(且差距很大)區別在於Canvas不是基於矢量的,而是基於像素的,因此:
- 它具有與像素為基礎的PNG、JPG和GIF圖片格式相同的縮放問題
- 它使得不可能像SVG那樣使用CSS或JavaScript編輯Canvas圖像
SVG符號
符號允許您定義一次SVG圖像,並在多個位置重用它。如果需要重複使用圖像,甚至只需稍微更改一下某些屬性,這將非常有幫助。
要這樣做,請添加一個symbol
元素並分配一個id
屬性:
1 | <svg class="hidden"> |
1 | <svg> |
(xlink:href
是為了支持Safari,即使它是一個已棄用的屬性)
這開始展示了SVG的功能。
如果要將這兩個矩形以不同的樣式樣式化,例如使用不同的顏色?您可以使用CSS變量。
1 | <svg class="hidden"> |
1 | <svg class="blue"> |
參考這個Glitch Playground上的相關示例:https://glitch.com/edit/#!/flavio-svg-symbols
驗證SVG
由於SVG是XML,因此可以以無效的格式來編寫它,某些服務或應用程序可能無法接受無效的SVG文件。
可以使用W3C驗證器來驗證SVG文件。
是否應該包含xmlns
屬性?
有時SVG被定義為
1 | <svg> |
有時候是
1 | <svg version="1.1" xmlns="http://www.w3.org/2000/svg"> |
第二種形式是XHTML。它也可以與HTML5(具有<!DOCTYPE html>
的文檔)一起使用,但在這種情況下,第一種形式更簡單。
是否需要擔心瀏覽器支持?
如今,絕大多數用戶的瀏覽器都支持SVG。
您可以使用像Modernizr這樣的庫來檢查缺少的支持並提供回退選項。
if (!Modernizr.svg) {
document.querySelector(".my-svg").setAttribute("src", "images/logo.png");
}