SVG 基礎

前言

在整理圖片相關優化的時候發現本身對 SVG 所知甚少,因而學習了一波,大致總結了一下,整理成文。由於前端開發人員由於細分領域不一樣,對待 SVG 的態度差異也很大,對於數據可視化這種對 SVG 有高要求的同窗這裏的介紹估計沒啥乾貨。對於日常較少接觸 SVG 的同窗,能夠對 SVG 有個初步的認識。php

這篇文章主要參考 《SVG 精髓》一書。接下來,開始幹活。css

基礎

SVG,便可縮放矢量圖形(Scalable Vector Graphics),是一種 XML 應用,能夠以一種簡潔、可移植的形式表示圖形信息。html

在矢量圖形系統中,圖像被描述爲一系列的形狀。矢量圖形閱讀器接受在指定的座標集上繪製形狀的指令。而不是接受一系列的已經計算好的像素。前端

因爲 SVG 是 XML 程序,因此圖像的有關信息被存儲爲純文本,並且具備 XML 的開放性、可移植性以及可交互性。瀏覽器

視口

viewport

SVG 的世界就是一張無限大的畫布。文檔打算使用的畫布區域稱做視口(viewport)。bash

概念提及來很玄乎。看個例子,建立一個簡答的 SVG:svg

<svg width="200" height="200" style="border:solid red 2px">
    <rect width="100" height="100" fill="#4c93cf" stroke="none"/>
</svg>
複製代碼

這裏的 width="200" height="200" 即是用來設置視口的大小;style 設置樣式, rect 元素用來畫一個矩形。效果以下:工具

SVG - viewport

viewbox

語法:post

viewBox="x, y, width, height"
複製代碼

接下來咱們改裝一下上面的代碼,讓裏面的正方形鋪滿視口。學習

<svg width="200" height="200" style="border:solid red 2px" viewBox="0 0 100 100">
    <rect width="100" height="100" fill="#4c93cf"/>
</svg>
複製代碼

效果以下:

SVG - viewbox1

相較於上面的代碼,這裏僅僅多了 viewBox 屬性。不過這個 viewBox 屬性解釋起來有點麻煩,可是很容易理解。 看兩個例子,而後,結合下面的一段話,基本就能夠理解了。

SVG 就像是咱們的顯示器屏幕,viewBox 就是截屏工具的那個選擇的框框,最終呈現就是把框框選中的內容再次在顯示器全屏顯示。

簡單的理解就是:

  1. 從 SVG 中截取一塊區域
  2. 顯示時,縮放這塊區域到視口大小

而後,咱們再改一下上面的例子,加深一下理解:

<svg width="200" height="200" style="border:solid red 2px" viewBox="0 0 800 800" >
    <rect width="400" height="400" fill="#4c93cf"/>
</svg>
複製代碼

基本信息:

  • 視口: 200 * 200
  • 矩形: 400 * 400
  • viewBox: 800 * 800

分析:

  1. viewBox 首先截取從(0, 0) 位置截取一個 800 * 800 的區域;
  2. 這個區域縮放到和視口大小相等。

此時,

  • viewBox 長寬縮小爲 200, 是原來的 1/4;
  • viewBox 中的矩形的長寬也縮小爲原來的 1/4, 即長寬都是 100;
  • 矩形的面積(100 * 100)佔視口面積(200 * 200)的 1/4 (以下圖)。

SVG - viewbox2

上面的例子裏,viewport 和 viewBox 的長寬比是相等的,最後的效果很舒服。若是兩者長寬比不相等,viewbox 要在 viewport 中顯示是要瓢的,咱們如何指定 viewbox 「瓢」的規則呢? 答案是 preserveAspectRatio

preserveAspectRatio

在解釋這個概念以前,咱們先看看 CSS 中 background 相關的兩個屬性(暫且不討論其餘相關屬性):

  1. background-size: cover|contain:
  • cover:圖片寬高比不變、鋪滿整個容器的寬高,而圖片多出的部分則會被截掉;
  • contain: 圖片自身的寬高比不變,縮放至圖片自身能徹底顯示出來,因此容器會有留白區域;
  1. background-position: xpos ypos CSS 的取值更靈活,如今只需回憶 xpos 和 ypos 的這幾個有效值, top, centerbottom 以及 left, centerright

這兩個屬性分別指定了背景如何伸縮和如何對齊。在 SVG 中,使用 preserveAspectRatio 屬性來指定上這兩種的行爲,語法以下:

preserveAspectRatio="<align> [<meetOrSlice>]"
複製代碼

其中,align 相似 background-position 用來指定對齊方式。有效值相似,xMidYMid,即指定關於 x 軸和 y 軸的三種對齊方式:min, mid 和 max。這裏須要注意的是,兩個值是連在一塊兒,且要採用駝峯命名法,好比: xMidYMin, 表示:viewBox 的最小 x 值對齊 viewport 的左邊部, viewBox 的最小 y 值對齊 viewport 的頂邊。

meetOrSlice:

  • meet, 保持 viewbox 寬高比,儘量放大 viewbox,使其 viewport 內是可見的。這時,viewport 可能會出現留白
  • slice,保持寬高比,viewbox 儘量小,但要使 viewbox 所有覆蓋 viewport。這個時候,可能會使部分 viewbox 超出 viewport,超出部分會被裁掉

由於能夠類比 CSS 屬性,這裏就不提供例子了(主要是我懶。。)

viewbox 帶來的變化,其實源自其對座標系的改變。接下來咱們看看 SVG 的座標系。

座標系

先介紹兩個概念: 初始視口座標系,是一個創建在視口上的座標系。原點(0,0)在視口的左上角,x 軸正向指向右,y 軸正向指向下,初始座標系中的一個單位等於視口中的一個"像素"。

用戶座標系,是創建在 SVG 畫布上的座標系。這個座標系一開始和視口座標系徹底同樣。使用 viewBox 屬性,初始用戶座標系統能夠變成與視窗座標系不同的座標系,如上面關於 viewBox 屬性的第一個例子中,用戶座標系的一個單位等於視口座標系的兩個單位。

經過 viewBox 建立了一個用戶座標系以後,後代元素的定位再也不以初始座標系定位,而是以新建的用戶座標系定位。

座標系統變換

開始具體看這節內容以前先記住一句話: SVG 是座標系統變換而不是元素變換

SVG 變換包括縮放,移動,傾斜和旋轉等,相似 CSS 的 transform,SVG 中使用 transform 屬性。不一樣的是

  • CSS 中的變換是相對於元素自身的中心點,而 SVG 中是相對於座標系原點的;
  • CSS 對元素的變換; SVG 是對座標系的變換:根據變換元素,先複製當前用戶座標系,而後對用戶座標系副本進行變換
  • SVG 變換中不指定單位,默認的單位等於當前用戶座標系單位;
  • CSS 變換還包含 3D 效果,SVG1.1 不支持 3D 效果。

注:貌似 SVG2 版本中可經過相似 transform-origin 屬性的形式設置變換的原點;以及支持 CSS3 規範的 CSS 2D 和 CSS 3D 變換。

translate 位移

語法:

transform="translate(<x> [<y>])"
複製代碼

其中 y 方向偏移爲非必選,默認爲 0。

HTML 元素的偏移是相對本身的中心點,SVG 元素 的偏移是相對 SVG 的左上角。 雖然在最後的表現上是同樣的。但在渲染機制上有着很大的不一樣:

  • CSS 中,會先畫好元素,而後再發生偏移。
  • SVG 中,先偏移座標系,而後再渲染元素。

scale 縮放

語法:

transform="scale(<x> [<y>])"
複製代碼

其中: x,表示沿 x 軸的縮放值,全部 x 座標乘以給定的 x; y,表示沿 y 軸的縮放值,全部 y 座標乘以給定的 y; y 是可選的,若是沒有默認與 x 值相同。

HTML 元素的縮放與 SVG 元素的縮放比較。 HTML 中的縮放:

  • 相對元素中心點;
  • 縮放元素自己;
  • 元素定位不發生變化。

SVG 中的縮放:

  • 相對 SVG 左上角;
  • 縮放座標系;
  • 元素被從新定位。

skew 斜切

語法:

transform="skewX(<a>)"

transform="skewY(<a>)"
複製代碼

其中,

  • skewX 聲明一個沿 x 軸的傾斜;
  • skewY 聲明一個沿 y 軸的傾斜。

同其餘的 transform 變換,skew 的操做對象也是座標軸,操做完成後會被從新定位。

rotate 旋轉

語法:

transform="rotate(<a> [<x> <y>])"
複製代碼

其中,

  • a 表示旋轉角度,默認是單位是度(deg);
  • x 和 y 可選,表明旋轉中心點;
  • 若是沒有設置 x,y 的值,默認爲當前用戶座標系的原點。

rotate 與上面介紹的另外幾個操做不一樣的是,能夠指定旋轉中心點,看似和 CSS 中的旋轉規則相同,其實:

transform="rotate(a x y)"
複製代碼

等同於:

transform="translate(x y) rotate(a) translate(-x -y)"
複製代碼

變換序列

一個圖形對象上能夠作多個變換。咱們只需將多個變換經過空格或逗號分隔,依次放入 transform 屬性便可。

<rect height="15" width="20" transform="translate(30, 20) scale(2)" fill=" gray" />
複製代碼

形狀

在 SVG 創建座標系統以後就能夠畫圖了, 下面介紹 SVG 中的形狀。

矩形

語法:

<rect x="x" y="y" rx="rx" ry="ry" width="width" height="height" />
複製代碼

其中:

  • x,y 指定矩形左上角的位置
  • width 和 height 爲矩形的寬高
  • rx 和 ry,表示圓角半徑。默認爲 0

栗子:

<svg width="200" height="200">
    <rect width="150" height="80" fill="red" rx="15" ry="15"/>
</svg>
複製代碼

圓角矩形

圓形

語法:

<circle cx="cx" cy="cy" r="r" />
複製代碼

其中:

  • cx,cy 指定圓心的位置
  • r 指定半徑

橢圓

語法:

<ellipse cx="cx" cy="cy" rx="rx" ry="ry" />
複製代碼

其中:

  • rx, ry 分別指定橢圓的 x 半徑和 y 半徑
  • cx,cy 指定橢圓中心的位置

語法:

<line x1="x1" y1="y1" x2="x2" y2="y2" />
複製代碼

其中:

  • x1,y1,指定一個點
  • x2,y2, 指定另外一個點
  • 兩點肯定一條線

折線

語法:

<polyline points="x1 y1, x2 y2, x3 y3, x4 y4, … , xn yn" />
複製代碼

其中:

  • points:點集合
  • 點集中的每一個數字均可以經過空格,逗號或換行隔開,可是更推薦上面的寫法,這樣能比較清晰的看出來每一個點的座標

多邊形

語法:

<polygon points="x1 y1, x2 y2, x3 y3, x4 y4, … , xn yn" />
複製代碼

語法與 polyline 相同,不一樣的是繪製最後回到第一個點,造成一個閉合圖形。

路徑

上面介紹的全部基本形狀都是 <path> 元素的簡寫形式。 <path> 元素經過指定一系列相互鏈接的線、圓弧和曲線繪製任意形狀的輪廓。 全部描述的輪廓的數據都放在 <path> 元素的 d(data 的縮寫)屬性中,d 的數據包括命令以及命令對應的座標信息。

上面關於 <path> 的介紹, 讓人感受很玄幻,簡單理解d 屬性的值是「命令+參數」的序列

  • 命令,一個單個字符,用來描述行爲
  • 參數,通常是指定命令對應的座標信息

先看一個簡單的例子來瞅瞅,好對 d 屬性有個最初的印象:

<svg width="200" height="1200">
    <path d="M20 20 L180 20 L180 80 l-160 0 Z" stroke-width="8" fill="transparent" stroke="red"/>
</svg>
複製代碼

效果以下:

path 畫一個矩形

d="M20 20 L180 20 L180 80 l-160 0 l0 -60" 中,M,L 和 l 即爲命令,命令後面即是這個命令做用的座標。 每一個路徑都必須以 M 命令(move to)開始。和 Canvas 同樣,moveto 命令用來把「筆」移動到一個位置,而後開始「畫畫」。

在 moveto 命令後面是一個 L(lineto)命令,用來繪製一條線。經過前三條命令畫出來了兩條線。接下來的 l 命令,仍是 lineto 命令,與 L 命令不一樣的是,l 命令的座標是相對座標(相對當前畫筆位置)。 其實,每種命令都有兩種表示方式:

  • 大寫字母,表示絕對定位;
  • 小寫字母,表示相對定位。

最後一個 Z(closepath)命令,用來閉合路徑,與第一個點連成線。

畫完第一個框框,而且瞭解路徑的基本的套路後,開始瞭解更多的命令:

直線命令

除了上面介紹的 lineto 命令,還有兩個簡寫形式的命令,用來畫水平方向和豎直方向的直線。

簡寫形式 等價的冗長形式 效 果
H 20 L 20 current_y 繪製一條到絕對位置 (20, current_y) 的線
h 20 l 20 0 繪製一條到 (current_x + 20,current_y) 的線
V 20 L current_x 20 繪製一條到絕對位置 (current_x,20) 的線
v 20 l 0 20 繪製一條到 (current_x, current_y + 20) 的線

還有更簡潔的形式: L H 和 V(及其小寫)後面均可以跟多個座標值。跟 <polyline> 元素同樣,會依次鏈接起來這些座標點。

曲線命令

繪製平滑曲線的命令分爲貝塞爾曲線和弧形(橢圓弧)兩種。

橢圓弧

繪製直線段相對簡單,由於路徑上的兩個點就就惟一肯定一條直線段。但若是是橢圓弧的話,因爲在兩個點之間能夠繪製無限條弧線,所以咱們必須給出額外信息,以在它們之間繪製一條曲線路徑。

  1. 給出圓弧上的兩個點,而且給出橢圓的 x 半徑和 y 半徑,能夠肯定出兩個橢圓。以下圖 a;
  2. 此時,兩點之間存在 4 個圓弧,兩個大弧(角度大於或等於 180 度)兩個小弧(角度小於 180 度),經過指定大小弧能夠肯定出兩條圓弧。
  3. 由兩個大弧和兩個小弧的繪製方向不一樣,能夠肯定出一條圓弧。

橢圓弧命令

不過,上面的描述中默認橢圓的 x 軸 和 y 軸都是座標軸平行的,若是有旋轉角,咱們還須要知道這個旋轉角度才能惟一肯定出一條圓弧。

圓弧命令以字母 A (絕對座標的縮寫)或者 a (相對座標的縮寫)開始,後面緊跟如下 7 個參數。

  • 點所在橢圓的 x 半徑和 y 半徑。
  • 橢圓的 x 軸旋轉角度 x-axis-rotation 。
  • large-arc-flag ,若是須要圓弧的角度小於 180 度,其爲 0;若是須要圓弧的角度大於或等於 180 度,則爲 1。
  • sweep-flag ,若是須要弧以逆時針繪製則爲 0,以順時針繪製則爲 1。
  • 終點的 x 座標和 y 座標(起點由最後一個繪製的點或者最後一個 moveto 命令肯定)。

命令形式:

A rx ry x-axis-rotation large-arc-flag sweep-flag x y
a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy
複製代碼

試着畫一下這四個圓弧:

<svg width="400" height="300">
    <path d="M 125,75 A100,50 0 1,0 225,125" fill="none" stroke="red" stroke-width="3"/>
    <path d="M 125,75 A100,50 0 0,1 225,125" fill="none" stroke="blue" stroke-width="3"/>
<path d="M 125,75 A100,50 0 1,1 225,125" fill="none" stroke="black" stroke-width="3"/>
    <path d="M 125,75 A100,50 0 0,0 225,125" fill="none" stroke="green" stroke-width="3"/>
</svg>
複製代碼

畫四個圓弧

貝塞爾曲線

二次貝塞爾曲線

最簡單的貝塞爾曲線是二次曲線。不看數學原理的話,簡單理解:咱們能經過三個點(起點、終點和控制點)肯定一條曲線

在 SVG 中,經過在 <path> d 屬性中使用 Q 或者 q 命令指定一個二次曲線。 繪製曲線起點在 (30, 75),終點在 (300, 120),控制點在 (240, 30),代碼以下:

<svg width="400" height="300">
  <path d="M30 75 Q240 30, 300 120" fill="none" stroke="red" stroke-width="3"/>
</svg>
複製代碼

二次貝塞爾

二次曲線命令後面能夠跟多組座標,下一組座標會以上一組座標的終點爲起點繪製曲線。不過這種方法獲得的曲線不是平滑曲線,平常中不少場景是但願獲得一個平滑曲線。對於這種需求,SVG 提供了流暢的二次曲線命令命令(用 T 或 t 表示)。 T 命令會自動計算控制點的位置,方法是「使新的控制點與上一條命令中的控制點相對於 當前點中心對稱」(PS 的鋼筆工具很容易模擬這個過程)。由於控制點是自動計算獲得的,因此 T 命令只要一組座標值。

<svg width="200" height="200">
  <path d="M30 100 Q 80 30, 100 100 T 200 80"  fill="none" stroke="red" stroke-width="3"/>
</svg>
複製代碼

平滑二次曲線

三次貝塞爾曲線

二次曲線和三次曲線之間的區別是三次曲線有兩個控制點。這裏不討論其幾何原理(原理也不太複雜),三次曲線能呈現更復雜的形狀。

三次貝塞爾曲線

三次曲線:

  • 使用命令 C 或 c
  • 同二次曲線同樣,命令後面能夠有多組座標
  • 同二次曲線同樣,也能夠平滑鏈接多個曲線,使用 S(或 s)命令

在 CSS 中的 cubic-bezier 就是用來肯定一個三次貝塞爾曲線(Cubic Bézier curves)的。不過 CSS 中肯定了起始點(0,0)和終點(1,1),因此 cubic-bezier 只需兩個控制點就能夠肯定一條三次曲線。

接下來模擬一條 CSS 中的三次曲線 cubic-bezier(0,1, 1,0)

<svg width="200" height="200" viewbox="0 0 100 100">
  <path d="M0 100 C 0,0 100,100 100,0" fill="none" stroke="red"/>
</svg>
複製代碼

對比

文字

text 元素

在一個 SVG 文檔中,<text> 元素內部能夠聽任何的文字。 如:

<text>balabala</text>
複製代碼

和 CSS 差很少,SVG 中的文本也有不少字體和文本有關的屬性,甚至屬性名都是徹底相同的。如: font-family、font-style、font-weight、font-variant、font-stretch、font-size、font-size-adjust、kerning、letter-spacing、word-spacing 和 text-decoration。

文本位置

語法:

<text x="x" y="y">balabala</text>
複製代碼

其中:

  • x:將文本向右移動 x
  • y:將文本想下移動 y (指定文本基線位置)
  • x 和 y 值是能夠帶單位的
  • 文本移動是相對 SVG 的左上角

另外 x 和 y 還能夠接受一個數列:

<text x="x1 x2 x3 x4 x5 … xn" y="y1 y2 y3 y4 y5 … yn">balabala</text>
複製代碼

分別定義每一個符號的位置:第一個符號(x1,y1),第二個符號(x2,y2)...,沒有指定的繼續使用最後組座標。

文本對齊

<text text-anchor="start|middle|end">balabala</text>
複製代碼

基於文本座標位置的對齊方式。

文本偏移

<text dx="dx" dy="dy">balabala</text>
複製代碼

相對文本位置的偏移量。

dx 和 dy 也能夠接受一個數列,表示對多個符號的偏移量。

文本旋轉

<text rotate="r">balabala</text>
複製代碼

表示對每一個字符進行旋轉 r 度,其中 r,沒有單位,默認單位爲 deg。

固然,也能夠給 rotate 一個數列,給多個符號指定不一樣的旋轉角度。

注意:若是想對整個文本元素進行旋轉,需使用上面提到的轉換座標系的方式transform="rotate(r)"

縱向文本

  • writing-mode:tb (tb:top to bottom),從上到下。實現文本的縱向排列。
  • glyph-orientation-vertical 屬性來設置文本(不是整個文本元素)旋轉角度。

tspan 元素

用來標記大塊文本的子部分,它必須是一個 <text> 元素的或別的 <tspan> 元素的子元素。

使用場景和 HTML 中的 span 標籤很類似,能夠用來在一段文本中單獨處理一小段文本內容,好比加粗,傾斜和上下標等。

textPath 元素

利用 xlint:href 屬性把字符對齊到路徑,讓字體能夠順着路徑排列。 這是個很騷的操做,必須得有例子:

<svg width="800" height="800">
    <path id="path" d="M 50 110 A 40 30 0 1 0 230 110 M 250 110" fill="none" stroke="none" />
    <text>
        <textPath xlink:href="#path" font-size="22">
            風 吹 水 面 層 層 浪 ~
        </textPath>
    </text>
</svg>
複製代碼

textPath的例子

樣式

填充和邊框

上面的例子上已經在屢次使用了,便是 fill 和 stroke:

  • fill,設置內部顏色
  • stroke,設置線條顏色

色值和 CCS 中相同,可使用顏色名,也可使用 rgb,rgba 和 16 進制色值等。

stroke 相關的一些內容須要額外講一下:

  • stroke-width: 描邊的寬度。以路徑爲中心,向兩邊擴散繪製。
  • stroke-linecap: 控制邊框起點和終點的形狀
  • stroke-linejoin:控制兩條描邊線段之間的鏈接方式
  • stroke-dasharray: 將虛線類型應用在描邊上

SVG 提供了四種樣式書寫的方式:

  • 內聯樣式
  • 內部樣式表
  • 外部樣式表
  • 表現屬性

內聯樣式

<circle cx="20" cy="20" r="10" style="stroke: black; stroke-width: 1.5; fill: blue; fill-opacity: 0.6"/>
複製代碼

內部樣式表

內部樣式表能夠寫一些經常使用的樣式,也是使用 <style> 標籤,不過與 HTML 有些不一樣:

  • <style> 須要定義在 <defs> 內;
  • 樣式表要寫在 <!CDATA[ ]]> 中。
<defs>
    <style type="text/css"><![CDATA[ circle { fill: #ffc; stroke: blue; stroke-width: 2; stroke-dasharray: 5 3; } ]]></style>
</defs>
複製代碼

外部樣式表

同 HTML 同樣,SVG 也可使用外部 CSS 樣式表。

<?xml-stylesheet href="ext_style.css" type="text/css"?>
複製代碼

表現屬性

上面的例子中已經屢次使用了表現屬性來指定樣式,相似:

<circle cx="10" cy="10" r="5" fill="red" stroke="black" stroke-width="2"/>
複製代碼

表現屬性位於優先級列表的最底部,任何來自內聯樣式,內部樣式表或者外部樣式表的樣式聲明都會覆蓋表現屬性。

注:指定樣式的首選是 style 屬性或者樣式表。

分組和引用

除了表示圖形的一些元素外,SVG 中還有一波表示文檔結構的元素。

g 元素

<g> 元素會將其全部子元素做爲一個組合,一般組合還會有一個惟一的 id 做爲名稱。每一個組合還能夠擁有本身的 <title><desc> 來供基於文本的 XML 應用程序識別,或者爲視障用戶提供更好的可訪問性。

use 元素

<use> 元素用於重用(再次顯示)分組或獨立圖形

<svg viewBox="0 0 1024 1024" width="400" height="100" preserveAspectRatio="xMinYMin meet">
    <g id="shape">
        <path d="M567.1 512l318.5-319.3c5-5 1.5-13.7-5.6-13.7h-90.5c-2.1 0-4.2 0.8-5.6 2.3l-273.3 274-90.2-90.5c12.5-22.1 19.7-47.6 19.7-74.8 0-83.9-68.1-152-152-152s-152 68.1-152 152 68.1 152 152 152c27.7 0 53.6-7.4 75.9-20.3l90 90.3-90.1 90.3C341.6 589.4 315.7 582 288 582c-83.9 0-152 68.1-152 152s68.1 152 152 152 152-68.1 152-152c0-27.2-7.2-52.7-19.7-74.8l90.2-90.5 273.3 274c1.5 1.5 3.5 2.3 5.6 2.3H880c7.1 0 10.7-8.6 5.6-13.7L567.1 512zM288 370c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z m0 444c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"></path>
    </g>

    <!-- 對上面的分組引用 三 次 -->
    <use xlink:href="#shape" x="1024" fill="#666" y="0" />
    <use xlink:href="#shape" x="2048" fill="#999" y="0" />
    <use xlink:href="#shape" x="3072" fill="#bbb" y="0" />
</svg>
複製代碼

效果以下:

use的例子

<use> 的引用是支持跨 svg 的,甚至是支持跨文件的。

defs 元素

<defs> 主要是用來定義(但不顯示)想要複用的元素的。

<svg viewBox="0 0 1024 1024" width="400" height="100" preserveAspectRatio="xMinYMin meet">
    <defs>
        <g id="shape">
            <path d="M567.1 512l318.5-319.3c5-5 1.5-13.7-5.6-13.7h-90.5c-2.1 0-4.2 0.8-5.6 2.3l-273.3 274-90.2-90.5c12.5-22.1 19.7-47.6 19.7-74.8 0-83.9-68.1-152-152-152s-152 68.1-152 152 68.1 152 152 152c27.7 0 53.6-7.4 75.9-20.3l90 90.3-90.1 90.3C341.6 589.4 315.7 582 288 582c-83.9 0-152 68.1-152 152s68.1 152 152 152 152-68.1 152-152c0-27.2-7.2-52.7-19.7-74.8l90.2-90.5 273.3 274c1.5 1.5 3.5 2.3 5.6 2.3H880c7.1 0 10.7-8.6 5.6-13.7L567.1 512zM288 370c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z m0 444c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"></path>
        </g>
    </defs>

    <!-- 引用 四 次 -->
    <use xlink:href="#shape" x="0" fill="#333" y="0" />
    <use xlink:href="#shape" x="1024" fill="#666" y="0" />
    <use xlink:href="#shape" x="2048" fill="#999" y="0" />
    <use xlink:href="#shape" x="3072" fill="#bbb" y="0" />
</svg>
複製代碼

symbol 元素

<symbol> 元素提供了另外一種組合元素的方式。和 <g> 元素不一樣,<symbol> 元素永遠不會顯示。 <symbol> 能夠建立本身的視窗,因此能夠指定 viewBoxpreserveAspectRatio 屬性,經過給 <use> 元素添加 width 和 height 屬性就可讓 <symbol> 適配視口大小。SVG Sprite 技術就是利用這個特色,將多個單獨的圖標放到一個個的 <symbol> 中。

<!DOCTYPE html>
<html>
    <body>
        <svg>
            <symbol id="shape" viewBox="0 0 1024 1024" preserveAspectRatio="xMinYMin meet" >
                <path d="M567.1 512l318.5-319.3c5-5 1.5-13.7-5.6-13.7h-90.5c-2.1 0-4.2 0.8-5.6 2.3l-273.3 274-90.2-90.5c12.5-22.1 19.7-47.6 19.7-74.8 0-83.9-68.1-152-152-152s-152 68.1-152 152 68.1 152 152 152c27.7 0 53.6-7.4 75.9-20.3l90 90.3-90.1 90.3C341.6 589.4 315.7 582 288 582c-83.9 0-152 68.1-152 152s68.1 152 152 152 152-68.1 152-152c0-27.2-7.2-52.7-19.7-74.8l90.2-90.5 273.3 274c1.5 1.5 3.5 2.3 5.6 2.3H880c7.1 0 10.7-8.6 5.6-13.7L567.1 512zM288 370c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z m0 444c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z" ></path>
            </symbol>
        </svg>

        <div style="font-size:40px;">
            石頭
            <svg width="60" height="60" style="vertical-align:middle;">
                <use xlink:href="#shape" x="5" y="5" width="50" height="50" />
            </svg></div>
    </body>
</html>
複製代碼

療效:

symbol的例子

在瀏覽器使用 SVG

做爲圖像

將圖像包含在 <img> 元素內。

<img src="./scissor.svg" />
複製代碼

或者 CSS 中:

<div style="height:200px; width:200px;background:url(./scissor.svg)"></div>
複製代碼

僅僅做爲圖像引入:

  • svg 不能與主頁面通訊;
  • 主頁面的樣式對 SVG 無效;
  • 主頁面腳本沒法感知和修改 SVG 的結構;
  • 大多數 Web 瀏覽器都不會加載 SVG 本身引用的文件,包括其餘圖像文件、外部腳本,甚至是 Web 字體文件。

<img>元素內包含 SVG 時,注意寬高的計算方式:

HTML <img> 元素定義了一個空間,表示瀏覽器應該將圖像繪製到這個空間中。要使用的圖像文件指定在 src(source)屬性內。

圖像的高度和寬度可使用屬性或者 CSS 屬性(優先考慮)設置。

若是不指定 <img> 元素的尺寸,就會使用圖像文件固有的尺寸。若是隻指定高度(寬度),寬度(高度)就會按比例縮放,以使高寬比(寬高比)與圖像文件固有的尺寸匹配。

複習完了 <img> 元素的知識,接下來討論一下 SVG 的尺寸問題:

對於柵格圖像來講,它固有的尺寸就是它的像素尺寸。對於 SVG 來講,則更爲複雜。若是文件中的根元素 <svg> 帶有明確的 height 和 width 屬性,則它們會被用做文件的固有尺寸。若是隻指定 height 或者 width 而不是兩個都指定,而且 <svg> 帶有 viewBox 屬性,那麼將用 viewBox 計算寬高比,圖像也會被縮放以匹配指定的尺寸。若是 <svg> 帶有 viewBox 屬性而沒有尺寸,則 viewBox 的 height 和 width 將被視爲像素長度。

若是 <img>元素和 <svg> 根元素都沒有任何有關圖像尺寸的信息,瀏覽器應該爲嵌入內容應用默認 HTML 尺寸,一般是 150 像素高、300 像素寬,可是最好不要依賴默認尺寸。

在 CSS 做爲圖像使用 SVG 時,寬高的計算方式與此相同。

將 SVG 做爲應用程序

哇~~ 這個狠了,啥叫將 SVG 做爲應用程序?? 就是懟到 <object><embed> 裏。

<object data="cat.svg" type="image/svg+xml" title="Cat Object" alt="Stick Figure of a Cat">
    <!-- 文本或者柵格圖像用做備用選項 -->
    <p>No SVG support! Here's a substitute:</p>
    <img src="cat.png" title="Cat Fallback" alt="A raster rendering of a Stick Figure of a Cat"/>
</object>
複製代碼

與圖像不一樣的是,嵌入的 SVG 能夠包含外部文件,同時腳本能夠在該對象和父頁面之間進行通訊。

HTML5 中內聯 SVG

在上文的 symbol 元素部分,咱們已經見過這種用法了。

默認狀況下,定位 SVG 時採用內聯顯示模式(這意味着它和先後的文本會被插入到同一行),而且其尺寸會基於 <svg> 元素的 height 和 width 屬性決定。 可以使用 CSS 的 height 和 width CSS 屬性改變尺寸,使用 display、margin、padding 和許多其餘 CSS 定位屬性改變其定位。 主文檔指定的樣式會被 SVG 繼承。

最後

洋洋灑灑寫了一大坨,感受寫的也不咋滴。

相關文章
相關標籤/搜索