深刻淺出 SVG

前言javascript

據悉,8月18號將在廣州舉辦中國第一屆React開發者大會。今日早讀文章由@Starrier翻譯分享。css

正文從這開始~html

SVG 是優秀且使人難以置信的強大圖像格式。本教程經過簡單地解釋全部須要瞭解的知識,爲您提供 SVG 的概述。java

介紹

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

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

我發現這話源自一本 2011 的書:在撰寫本文時,只有在最新的瀏覽器中才能將 SVG 直接嵌入到 HTML 中工做。7 年過去了,這句話如今已是過去式了,咱們能夠很安全地使用 SVG 圖像。api

如今咱們能夠安全地使用 SVG 圖像,除非您有不少用戶使用 IE8 以及更低版本,或者使用較舊的 Android 設備。這種狀況下,依然存在着備選方案。瀏覽器

SVG 支持的瀏覽器安全

SVG 成功的一部分是因爲咱們必須支持各類不一樣分辨率和尺寸的屏幕顯示。SVG 能完美解決這個問題。ide

同時,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標籤

  • 帶有 CSSbackground-image屬性

  • 在 HTML 中內聯

  • 帶有objectiframeembed標籤

在 Glitch 上能夠查看這些示例flavio-svg-loading-ways.glitch.me/

帶有img標籤
<img src="flag.svg" alt="Flag" />
帶有 cssbackground-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");}

關於本文

譯者:@Starrier
譯文:http://www.javashuo.com/article/p-dvangpin-be.html
做者:@flaviocopes
原文:https://flaviocopes.com/svg/
校對者:@dandyxu、@allenlongbaobao

最後,爲你推薦

@大漠等幾位翻譯的一本關於SVG的圖書《SVG動畫-用複雜交互動畫改善用戶體驗》,有興趣的童鞋能夠了解下。

【第1194期】手把手教你用 SVG 符號和 CSS 變量作出彩色圖標

【第1110期】SVG 路徑動畫簡易指南

相關文章
相關標籤/搜索