[譯] 深入淺出 SVG

Starrier發表於2018-04-19

深入淺出 SVG

SVG 是優秀且令人難以置信的強大影象格式。本教程通過簡單地解釋所有需要了解的知識,為您提供 SVG 的概述。

[譯] 深入淺出 SVG

介紹

儘管在 21 世紀初被標準化了,SVG(Scalable Vector Graphics 的縮寫)是近年來的一個熱門話題。

SVG 已經被糟糕的瀏覽器支援(尤其是 IE)懲罰了好多年。

我發現這話源自一本 2011 的書:在撰寫本文時,只有在最新的瀏覽器中才能將 SVG 直接嵌入到 HTML 中工作。7 年過去了,這句話現在已經是過去式了,我們可以很安全地使用 SVG 影象。

現在我們可以安全地使用 SVG 影象,除非您有很多使用者使用 IE8 以及更低版本,或者使用較舊的 Android 裝置。這種情況下,依然存在著備選方案。

SVG 支援的瀏覽器

SVG 成功的一部分是由於我們必須支援各種不同解析度和尺寸的螢幕顯示。SVG 能完美解決這個問題。

同時,Flash 在過去幾年的迅速衰退導致大家對 SVG 產生了興趣。這對於 Flash 過去所做的許多事情都是非常重要的。

SVG 是一種 vector 影象檔案格式。這使得它們與其他影象格式(如 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 看起來會非常熟悉,除了在 SVG 中有標籤適合文件構建(如 particlefooteraside)我們還有向量圖的構建塊: pathrectline 等等。

這是一個 SVG 影象示例:

<svg width="10" height="10">
  <rect x="0" y="0" width="10" height="10" fill="blue" />
</svg>
複製程式碼

注意它非常容易閱讀和理解影象的樣子:它是一個 10 x 10 畫素的簡單藍色矩形(預設單元)。

大多情況下,您不必編寫 SVG 程式碼,因為您可以使用 Sketch 或 Figma 等工具或任何其他向量圖形工具來建立影象,並將其匯出為 SVG。

SVG 的當前版本是 1.1, SVG 2.0 正在研發。

使用 SVG

瀏覽器可以通過將它們包含在一個 img 標籤中來顯示 SVG 影象:

<img src="image.svg" alt="My SVG image" />
複製程式碼

就像其他基於畫素的影象格式一樣:

<img src="image.png" alt="My PNG image" />
<img src="image.jpg" alt="My JPG image" />
<img src="image.gif" alt="My GIF image" />
<img src="image.webp" alt="My WebP image" />
複製程式碼

此外,SVG 非常獨特,它們可以直接包含在 HTML 頁面中:

<!DOCTYPE html>
<html>
  <head>
    <title>A page</title>
  </head>
  <body>
    <svg width="10" height="10">
      <rect x="0" y="0" width="10" height="10" fill="blue" />
    </svg>
  </body>
</html>
複製程式碼

請注意 HTML5 和 XHTML 對於內聯 SVG 影象需要不同的語法。幸運的是,XHTML已經是過去的事情了,因為它過於繁雜,但是如果您仍然需要處理 XHTML 頁面,就值得去了解它。

在 HTLM 中內聯 SVG 的功能使該格式成為場景中的 unicorn,因為其他影象不能這樣做,必須為每個影象開啟一個單獨的請求來獲取該格式。

SVG 元素

在上面的示例中,您看到了 rect 元素的用法。SVG 有許多不同的元素。

最常用的是

  • text: 建立一個 text 元素
  • circle: 建立一個圓
  • rect: 建立一個矩形
  • line: 建立一條線
  • path: 在兩點之間建立一條路徑
  • textPath: 在兩點之間建立一條路徑,並建立一個連結文字元素
  • polygon: 允許建立任意型別的多邊形
  • g: 單獨的元素

座標從繪圖區域左上角的 0,0 開始,並 從左到右表示 x, 從上到下表示 y

您看到的影象反映了上面所示的程式碼。使用瀏覽器 DevTools,您可以檢查和更改它們。

text

text 元素新增文字。可以使用滑鼠選擇文字。xy 定義文字的起始點。

<svg>
  <text x="5" y="30">A nice rectangle</text>
</svg>
複製程式碼
漂亮的長方形

circle

定義圓。 cxcy 是中心座標,r 是半徑。 fill 是一個常用屬性,表示圖形顏色。

<svg>
  <circle cx="50" cy="50" r="50" fill="#529fca" />
</svg>
複製程式碼

rect

定義矩形。 xy 是起始座標,widthheight 是自解釋的。

<svg>
  <rect x="0" y="0" width="100" height="100" fill="#529fca" />
</svg>
複製程式碼

line

x1y1 定義起始座標。x2y2 定義結束座標。stroke 是一個常用屬性,表示線條顏色。

<svg>
  <line x1="0" y1="0" x2="100" y2="100" stroke="#529fca" />
</svg>
複製程式碼

path

路徑是一系列的直線和曲線。它是所有 SVG 繪製工具中最強大的,因此也是最複雜的。

d 包含方向命令。這些命令以命令名和一組座標開始:

  • M 表示移動,它接受一組 x,y 座標
  • L 表示直線將繪製到它接受一組 x,y
  • H 是一條水平線,它只接受 x 座標
  • V 是一條垂直線,它只接受 y 座標
  • Z 表示關閉路徑,並將其放回起始位置
  • A 表示 Arch,它自己需要一個完整的教程
  • Q 是一條二次 Bezier 曲線,同樣,它自己也需要一個完整的教程
<svg height="300" width="300">
  <path d="M 100 100 L 200 200 H 10 V 40 H 70"
        fill="#59fa81" stroke="#d85b49" stroke-width="3" />
</svg>
複製程式碼

textPath

沿路徑元素的形狀新增文字。

Wow such a nice SVG tut

polygon

使用 polygon 繪製任意多邊形。 points 代表一組 x,y 座標多邊形應該連結:

<svg>
  <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" />
</svg>
複製程式碼

g

使用 g 元素,您可以對多個元素進行分組:

<svg width="200" height="200">
  <rect x="0" y="0" width="100" height="100" fill="#529fca" />
  <g id="my-group">
    <rect x="0" y="100" width="100" height="100" fill="#59fa81" />
    <rect x="100" y="0" width="100" height="100" fill="#59fa81" />
  </g>
</svg>
複製程式碼

SVG viewport 和 viewBox

SVG 相對於其容器的大小由 svg 元素的 widthheight 屬性設定。這些單位預設為畫素,但您可以使用任何其他常用單位,如 %em。這是 viewport

通常 “container” 指的是瀏覽器視窗,但 svg 元素可以包含其他 svg 元素,在這種情況下,容器是父元素 svg

一個重要的屬性是 viewBox。它允許您在 SVG 畫布中定義一個新的座標系統。

假設在 200x200px SVG 中有一個簡單的圓:

<svg width="200" height="200">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>
複製程式碼

通過指定 viewBox ,您可以選擇 只顯示此 SVG 的一部分。例如,您可以從 0,0 點開始,只顯示一個 100 x 100 px 畫布:

<svg width="200" height="200" viewBox="0 0 100 100">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>
複製程式碼

從 100,100 開始,您會看到另一部分,圓圈的右下角:

<svg width="200" height="200" viewBox="100 100 100 100">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>
複製程式碼

一個很好的視覺化方法是想象 Google Maps 是一個巨大的 SVG 影象,而您的瀏覽器是一個和視窗大小一樣大的檢視框。當您移動時,Viewbox 會更改它的起始點(x,y)座標,並且當您調整視窗的大小時,會更改 Viewbox 的寬度和高度。

在 Web 網頁中插入 SVG

將 SVG 新增到網頁中有多種方法。

最常見的是:

  • 帶有 img 標籤
  • 帶有 CSS background-image 屬性
  • 在 HTML 中內聯
  • 帶有 objectiframeembed 標籤

在 Glitch 上可以檢視這些示例 flavio-svg-loading-ways.glitch.me/

帶有 img 標籤

<img src="flag.svg" alt="Flag" />
複製程式碼

帶有 css background-image 屬性

<style>
.svg-background {
  background-image: url(flag.svg);
  height: 200px;
  width: 300px;
}
</style>
<div class="svg-background"></div>
複製程式碼

在 HTML 中內聯

<svg width="300" height="200" viewBox="0 0 300 200"
    version="1.1" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Italian Flag</title>
  <desc>By Flavio Copes https://flaviocopes.com</desc>
  <g id="flag">
      <rect fill="green" x="0" y="0" width="100" height="200"></rect>
      <rect fill="white" x="100" y="0" width="100" height="200"></rect>
      <rect fill="red" x="200" y="0" width="100" height="200"></rect>
  </g>
</svg>
複製程式碼

帶有 objectiframeembed 標籤

<object data="flag.svg" type="image/svg+xml"></object>

<iframe src="flag.svg" frameborder="0"></iframe>

<embed src="flag.svg" type="" />
複製程式碼

使用 embed,您可以使用以下命令從父文件獲取 SVG 文件

document.getElementById('my-svg-embed').getSVGDocument()
複製程式碼

在 SVG 內部,您可以通過以下方式引用父文件:

window.parent.document
複製程式碼

使用資料 URL 內聯 SVG

您可以使用以上任何示例結合 Data URLs 將 SVG 內聯到 HTML 中:

<img src="data:image/svg+xml;<DATA>" alt="Flag" />

<object data="data:image/svg+xml;<DATA>" type="image/svg+xml"></object>

<iframe data="data:image/svg+xml;<DATA>" frameborder="0"></iframe>
複製程式碼

在 CSS 中也是:

.svg-background {
  background-image: url("data:image/svg+xml;<DATA>");
}
複製程式碼

只需使用適當的Data URL 更改<DATA>

樣式元素

任何 SVG 元素都可以接受 style 屬性,就像 HTML標籤一樣。並非所有的 CSS 屬性都能像您預期的那樣工作。例如,要更改文字元素的顏色,請使用 fill 而不是 color

<svg>
  <text x="5" y="30" style="fill: green">A nice text</text>
</svg>

<svg>
  <text x="5" y="70" style="fill: green; font-family: Courier New">
    A nice text
  </text>
</svg>
複製程式碼

您也可以使用 fill 作為元素屬性,正如您在前面看到的那樣:

<svg>
  <text x="5" y="70" fill="green">A nice text</text>
</svg>
複製程式碼

其他公共屬性包括

  • fill-opacity,背景顏色不透明度
  • stroke,定義邊框顏色
  • stroke-width,設定邊框寬度

CSS 可以針對 SVG 元素,就像您以 HTML 標籤為目標一樣:

rect {
  fill: red;
}
circle {
  fill: blue;
}
複製程式碼

使用 CSS 或 JavaSCript 與 SVG 互動

SVG 影象可以使用 CSS 進行樣式化,或者使用 JavaScript 編寫指令碼,這種情況下:

  • 當 SVG 在 HTML 中內聯
  • 通過 objectembediframe 標籤載入影象時

但是 (⚠️ 取決於瀏覽器實現) 它們必須從相同的域(和協議)載入,這是同源策略所導致的。 iframe 需要顯式定義的尺寸,否則內容將被裁剪,同時調整 objectembed 尺寸以適應其內容。.

如果 SVG 是使用 img 標籤載入的,或者使用 CSS 作為背景,則與源無關:

  • CSS 和 JavaScript 不能與之進行互動
  • SVG 中包含的 JavaScript 被禁用
  • 無法從外部載入資源(如影象、樣式表、指令碼、字型)

細節


特性 SVG 內聯 object/embed/iframe img
可以與使用者互動
支援動畫
可以執行 JavaScript 指令碼 ??
可以從外部編寫指令碼 ?? ??

內聯 SVG 影象無疑是最強大和最靈活的,它是使用 SVG 執行某些操作的唯一方法。

如果您想要 SVG 與您的指令碼進行任何互動,它必須以內聯的方式載入到 HTML中

如果您不需要與 SVG 互動,只需在頁面中顯示它,將 SVG 載入至 imgobject 或者 embed 中即可,如果您在不同的頁面中重用 SVG 影象,或者 SVG 影象的大小相當大,那麼載入 SVG 就特別方便。

CSS 嵌入 SVG

將 CSS 加至 CDATA:

<svg>
  <style>
    <![CDATA[
      #my-rect { fill: blue; }
    ]]>
  </style>
  <rect id="my-rect" x="0" y="0" width="10" height="10" />
</svg>
複製程式碼

SVG 檔案還可以包括外部樣式表

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/css" href="style.css"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width=".." height=".." viewBox="..">
  <rect id="my-rect" x="0" y="0" width="10" height="10" />
</svg>
複製程式碼

JavaScript 嵌入 SVG

你可以將 JavaScript 放在第一個位置上,幷包裝在一個 load 事件中,以便在頁面完全載入並在 DOM 中插入 SVG 時執行它:

<svg>
  <script>
    <![CDATA[
      window.addEventListener("load", () => {
        //...
      }, false)
    ]]>
  </script>
  <rect x="0" y="0" width="10" height="10" fill="blue" />
</svg>
複製程式碼

或者如果您將 JS 放在其他 SVG 程式碼的末尾,可以避免新增事件監聽,確保當 SVG 出現在頁面時 JavaSCript 會執行。

<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue" />
  <script>
    <![CDATA[
      //...
    ]]>
  </script>
</svg>
複製程式碼

與 HTML 元素一樣,SVG 元素也可以有 idclass 屬性,因此我們可以使用 Selectors API 來引用它們:

<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue"
        id="my-rect" class="a-rect" />
  <script>
    <![CDATA[
      console.log(document.getElementsByTagName('rect'))
      console.log(document.getElementById('my-rect'))
      console.log(document.querySelector('.a-rect'))
      console.log(document.querySelectorAll('.a-rect'))
    ]]>
  </script>
</svg>
複製程式碼

請檢視此故障 flaviocopes-svg-script.glitch.me/ 以獲得功能性提示。

SVG 外部的 JavaScript

如果可以與 SVG 互動(SVG 在 HTML 中是內聯的),則可以使用 JavaScript 更改任何 SVG 屬性,例如:

document.getElementById("my-svg-rect").setAttribute("fill", "black")
複製程式碼

或者真正地做任何您想要的 DOM 操作。

SVG 外部的 CSS

您可以使用 CSS 更改 SVG 影象的任何樣式。

SVG 屬性可以很容易地在 CSS中 被覆蓋,並且它們比 CSS 具有更低的優先順序。它們的行為不像具有更高優先順序的內聯 CSS。

<style>
  #my-rect {
    fill: red
  }
</style>
<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue"
        id="my-rect" />
</svg>
複製程式碼

SVG vs Canvas API

Canvas API 是 Web 平臺一個很好的補充,它有類似於 SVG 的瀏覽器支援。與 SVG 主要的(也是最大的)不同之處是:畫布不是基於向量的,而是基於畫素的,所以

  • 它具有與基於畫素的 png、jpg 和 gif 影象格式相同的縮放問題。
  • 這使得不可能像使用 SVG 那樣使用 CSS 或 JavaScropt 編輯畫布影象。

SVG 符號

符號使您可以定義一次SVG影象,並在多個地方重用它。如果您需要重用一個影象,這是一個很大的幫助,可能只是改變一點它的一些屬性。

您可以通過新增一個 symbol 元素並分配一個 id 屬性來完成此操作:

<svg class="hidden">
  <symbol id="rectangle" viewBox="0 0 20 20">
    <rect x="0" y="0" width="300" height="300" fill="rgb(255,159,0)" />
  </symbol>
</svg>
複製程式碼
<svg>
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<svg>
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>
複製程式碼

(xlink:href 用於 Safari 支援,即使它是一個已廢棄的屬性)

這讓我們能開始瞭解 SVG 的強大功能。

如果您希望對這兩個矩形使用不同的樣式,例如,對每個矩形使用不同的顏色?您可以使用CSS 變數.

<svg class="hidden">
  <symbol id="rectangle" viewBox="0 0 20 20">
    <rect x="0" y="0" width="300" height="300" fill="var(--color)" />
  </symbol>
</svg>
複製程式碼
<svg class="blue">
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<svg class="red">
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<style>
svg.red {
  --color: red;
}
svg.blue {
  --color: blue;
}
</style>
複製程式碼

檢視 SVG 符號--我的 Glitch playground

驗證 SVG

SVG 檔案是 XML,可以用無效的格式編寫,有些服務或應用程式可能不接受無效的 SVG 檔案。

SVG 可以使用 W3C Validator驗證。

我應該包含 xmlns 屬性麼?

有時 SVG 別定義為

<svg>
  ...
</svg>
複製程式碼

有時定義為

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  ...
</svg>
複製程式碼

第二個表單是 XHTML。它可以與 HTML5 一起使用(文件具有 <!DOCTYPE html>),但在本例中,第一種形式更簡單。

我應該擔心瀏覽器支援問題麼?

在 2018 版本中,絕大多數使用者的瀏覽器都支援 SVG。.

您仍然可以使用諸如 Modernizr 這樣的庫來檢查缺少的支援,並提供一個後備:

if (!Modernizr.svg) {
  $(".my-svg").attr("src", "images/logo.png");
}
複製程式碼

掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章