SVG Scalable Vector Graphics

SVG 以 XML 格式定義圖形。

將 SVG 直接嵌入 HTML 頁面:

<svg width="100" height="100">
  <circle cx="50" cy="50" r="40"
  	stroke="green" stroke-width="4" fill="yellow" />
</svg>

SVG 形狀

SVG 有一些預定義的形狀元件可供使用:

SVG Rectangle - <rect>

元件用於創建矩形和矩形的變體:
<svg width="400" height="110">
  <rect width="200" height="100" style="fill:rgb(0,0,255);
          stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
圓角矩形就是在矩形的 rect 屬性內額外增加rx、ry的圓角半徑屬性
<svg width="400" height="110">
  <rect x="60" y="10" rx="10" ry="10" width="75" height="75"
          stroke="#FF5500" stroke-width="5" fill="#FFB255"/>
</svg>
fill-opacity 屬性定義了填充顏色的不透明度(0 到 1)
<svg width="400" height="180">
  <rect x="50" y="20" width="100" height="100"
  style="fill:blue;stroke:pink;stroke-width:5;
          fill-opacity:0.1;stroke-opacity:0.9" />
</svg>

SVG - <ellipse>

<svg height="140" width="400">
  <ellipse cx="200" cy="80" rx="100" ry="50"
  style="fill:yellow;stroke:purple;stroke-width:2" />
</svg>

SVG - <line>

<svg height="120" width="500">
  <line x1="0" y1="0" x2="200" y2="100"
          style="stroke:rgb(255,0,0);stroke-width:2" />
</svg>

SVG - <polygon>

多邊形由直線構成,形狀是“封閉的”(所有的線都連接起來)。
<svg height="250" width="500">
  <polygon points="220,10 300,210 170,250 123,234"
          style="fill:lime;stroke:purple;stroke-width:1" />
</svg>
使用 <polygon> 元件創建一個星形:
<svg height="210" width="500">
  <polygon points="100,10 40,198 190,78 10,78 160,198"
          style="fill:lime;stroke:purple;stroke-width:5;
          fill-rule:evenodd;" />
</svg>

SVG - <polyline>

<svg height="200" width="500">
  <polyline points="20,20 40,25 60,40 80,120 120,140 200,180"
  style="fill:none;stroke:black;stroke-width:3" />
</svg>

SVG - <image>

<svg width="100" height="100"
  xmlns="http://www.w3.org/2000/svg">
  <image href="../svg/mdn_logo_only_color.png" height="100" width="100"/>
</svg>

SVG - <pattern>

元件定義了一個圖形物件,該物件可以以重複的 x 和 y 坐標間隔(“平鋪”)重新繪製以覆蓋一個區域。

由其他圖形元件上的 fill 和/或 stroke 屬性引用,以使用引用的模式填充或描邊這些元件。

<svg viewBox="0 0 230 200" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <pattern id="star" viewBox="0,0,10,10" width="10%" height="10%">
      <polygon points="0,0 2,5 0,10 5,8 10,10 8,5 10,0 5,2"/>
    </pattern>
  </defs>
  <circle cx="50"  cy="60" r="50" fill="url(#star)"/>
  <circle cx="120" cy="60" r="40" fill="none"
        stroke-width="20" stroke="url(#star)"/>
</svg>
<pattern>可以製作透明背景的效果:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <pattern id="checkerPattern" patternUnits="userSpaceOnUse"
             x="0" y="0" width="20" height="20" viewBox="0 0 10 10">
            <rect x="0" y="0" width="10" height="10" fill="#fff">
            <rect x="0" y="0" width="5" height="5" fill="#eee">
            <rect x="5" y="5" width="5" height="5" fill="#eee">
        </pattern>
    </defs>
    <rect width="100%" height="100%" x="0" y="0" stroke="#000"
            fill="url(#checkerPattern)" style="pointer-events:none">
</svg>

SVG 拷貝 - <use>

元件從 SVG 文檔中獲取節點,並在其他地方複製它們。
    <svg width="400" height="200"
        xmlns="http://www.w3.org/2000/svg">
        <circle id="gfg" cx="100" cy="100" r="40"/>

        <use href="#gfg" x="110" fill="blue"></use>
    </svg>

SVG - <defs>

defs 元件可以容納許多重複性質高的元件,變成一個可以重複利用的物件。 首先我們來看到最常見的 defs 例子:「重複的圖形」,

下面利用 defs 定義了一個矩形的長寬顏色,再使用 use 元件把矩形表現在畫面上,而 use 元件具有 x 與 y 的座標屬性,就可以輕鬆的做出許多不同位置的矩形。

<defs>
  <rect id="rect1" width="100" height="50" x="10" y="10" fill="#c00"/>
</defs>
<use xlink:href="#rect1"/>
<use xlink:href="#rect1" x="110"/>
也可以將 g 元件 ( 群組 ) 放在 defs 元件�媕Y:
<defs>
    <g id="g1">
       <rect id="rect1" width="100" height="50" x="10" y="10" fill="#c00"/>
       <circle id="circle1" cx="30" cy="30" r="10" fill="#00c"/>
    </g>
</defs>
<use xlink:href="#g1"/>
<use xlink:href="#rect1" x="110"/>
<use xlink:href="#circle1" x="210"/>

Clipping ( 剪裁 )

要建立一個 Clipping 的圖形,首先要在定義檔內放入<clipPath></clipPath>的標籤,記得要放入 id,這樣要被剪裁的圖形才能夠對應。 接著在<clipPath></clipPath>�媕Y放入一些圖形,這些圖形以外的都會被剪裁。

下面的範例,圓形被矩形剪裁了,所以變成半圓形了。

<defs>
  <clipPath id="a1">
    <rect x="0" y="0" width="160" height="80" />
  </clipPath>
</defs>
<circle cx="80" cy="80" r="80" clip-path="url(#a1)" fill="lime" />

剪輯路徑與圖像一起縮放

事實上,<clipPath> 元件可以包含任意數量的基本形狀(<rect>、<circle> 等)、<path> 元件,甚至 <text> 元件。

假如 SVG 剪輯路徑與圖像一起縮放, 必須將 clipPathUnits="objectBoundingBox" 添加到 HTML 中的 clipPath,
而且 SVG 路徑值必須介於 0 和 1 之間。

<style>
.clip-svg {
  clip-path: url(#clip-svg);
}

<img src="Harry-Potter.jpg"  width="50%" height="50%" class="clip-svg">
<svg width="0" height="0">
  <defs>
    <clipPath id="myClip" clipPathUnits="objectBoundingBox">>
      <circle cx="0.5" cy="0.4" r="0.35"/>
    </clipPath>
  </defs>
</svg>

Clipping ( 文字剪裁 )

以下是用作剪切路徑的一段文本的示例。
<defs>
    <clipPath id="Txt-clipPath">
        <text x="10" y="100" style="font-size: 40px"
        font-weight="bold">天上明月光</text>
    </clipPath>
</defs>
<g id="g1" style="clip-path: url(#Txt-clipPath);">
    <circle cx="120" cy="120" r="100" fill="#34538b" />
    <rect x="0" y="0" width="120" height="180"
    style="fill:#cd0000;" />
</g>

SVG <text> 很酷的一點是它可以使用自定義字體顯示,就像 HTML 文本一樣。 在這個例子中,使用了來自 Google Web Fonts 的 Vollkorn 字體。 使用 textLength 屬性將文本的寬度設置為與圖像的寬度相同,並使用 x 和 y 坐標定位文本。 注意這裡的 x 和 y 坐標決定了文本左下角的位置(底部代表文本的基線)。

參考資料:
css-svg-clipping
css3-svg-clip-path
image-pop-out-effect-with-svg-clip-path
using-clip-path-with-an-svg-defined-clippath
Apply effects to images with CSS's mask-image property

SVG 路徑 - <path>

SVG 是向量圖,所有的物件和元件都是由 Path ( 路徑 ) 所組成。
所以 Path 就具有相當多的指令讓使用者設定:
指令 參數 指令說明
M x y 起始點的 x , y 座標 ( move to )
L x y  從目前點的座標畫直線到指定點的 x , y 座標 ( line to )
H x 從目前點的座標畫水平直線到指定的 x 軸座標 ( horizontal line to )
V y 從目前點的座標畫垂直線到指定的 y 軸座標 ( vertical line to )
C x1 y1 x2 y2 x y 從目前點的座標畫條貝茲曲線到指定點的 x, y 座標:其中 x1, y1 及 x2, y2 為控制點 ( curve )
S x2 y2 x y 從目前點的座標畫條反射的貝茲曲線到指定點的 x, y 座標:其中 x2, y2 為反射的控制點 ( smooth curve )
Q x1 y1 x y 從目前點的座標畫條二次貝茲曲線到指定點的 x, y 座標:其中 x1, y1 為控制點 ( quadratic Bezier curve )
T x y 從目前點的座標畫條反射二次貝茲曲線到指定點的 x, y 座標:以前一個座標為反射控制點( smooth quadratic Bezier curve )
A rx ry x-axis-rotation large-arc-flag sweep-flag x y 從目前點的座標畫個橢圓形到指定點的 x, y 座標:其中 rx, ry 為橢圓形的 x 軸及 y 軸的半徑,x-axis-rotation 是弧線與 x 軸的旋轉角度, large-arc-flag 則設定 1 最大角度的弧線或是 0 最小角度的弧線,sweep-flag 設定方向為 1 順時針方向或 0 逆時針方向 (elliptical Arc )
Z   關閉路徑,將目前點的座標與第一個點的座標連接起來 ( closepath )
注意:以上所有命令也可以用小寫字母表示。 大寫表示絕對定位,小寫表示相對定位。
利用 path 畫三角形
起點移到 150 0,畫線到 75 100,畫線到 225 100,再用 Z 關閉路徑:
<svg height="120" width="300">
  <path d="M150 0 L75 100 L225 100 Z" style="fill:blue;" />
</svg>
利用 path 畫橢圓形
A (Arc 弧線) 指令參數多達 7 個,以下就一一為說明這些參數:
A rx,ry x-axis-rotation large-arc-flag,sweep-flag  x,y
  1. rx : 橢圓的長軸半徑 ( 根據不同的終點換算成比例 )
  2. ry : 橢圓的短軸半徑 ( 根據不同的終點換算成比例 )
  3. x-axis-rotation : 長軸與 x 軸的夾角
  4. large-arc-flag : 1 為大角度弧線,0 為小角度弧線 ( 必須有三個點 )
  5. sweep-flag : 1 為順時針方向,0 為逆時針方向
  6. x : 終點 x 座標
  7. y : 終點 y 座標
關於 A 指令參數的詳細說明,見Path 進階篇

下列的路徑也可用以畫橢圓:

<path
    d="
    M cx cy
    m -rx, 0
    a rx,ry 30 1,0 (rx * 2),0
    a rx,ry 30 1,0 -(rx * 2),0
    "
/>
利用 path 畫圓形
路徑的指令 A (Arc 弧線) 也可用以畫圓:

cx cy 為圓心坐標,r 為半徑,即rx 和 ry 等值為 r。

<path
    d="
    M cx cy
    m -r, 0
    a r,r 0 1,0 (r * 2),0
    a r,r 0 1,0 -(r * 2),0
    "
/>
貝塞爾(Bezier)曲線
貝塞爾(Bezier)曲線用於模擬可以無限縮放的平滑曲線。 通常,選擇兩個端點和一兩個控制點。

二次貝塞爾曲線起點和終點的貝茲曲線共用同一個控制點(50 50),只需要有貝茲控制點的座標和終點座標即可。

<svg>
<path d="M0 0 Q30 120, 100 0" stroke="black" fill="none"/>
</svg>

具有兩個控制點的曲線稱為三次貝塞爾曲線:
當中 (40 40) 表示第一個貝茲曲線的控制點,(60 40) 表示第二個貝茲曲線的控制點,(100,0) 則是線段的結束點。
<svg>
<path d="M0 0 C40 40,90 60,100,0" stroke="black" fill="none"/>
</svg>
鏡射貝塞爾(Bezier)曲線
S 可以在原本的點後方建立一個帶有貝茲曲線控制點的點,然後原本的點會以同樣的斜率鏡射一個貝茲控制點。
<svg>
<path d="M0 0 C40 40,60 40,100,0 S150 -40, 200 0"
           stroke="black" fill="none"/>
</svg>

變形

SVG 的 transform 就是這五個方法:translate、scale、rotate、skew、matrix:

變形 語法 等效矩陣 說明
位移 translate(tx,[ty]) matrix(1 0 0 1 tx ty) 在 x 軸或 y 軸進行位移
縮放 scale(sx,[sy]) matrix(sx 0 0 sy 0 0) scale 的放大縮小除了寬度和高度,連同坐標也會一併放大縮小
旋轉 rotate(angle,[cx,cy]) matrix(cos(a) sin(a) -sin(a) cos(a) 0 0) rotate 可以控制圖形的旋轉角度,順時針為正,逆時針為負。
旋轉圓心的預設值為 SVG 整張畫布的左上角(0,0),當然我們也可以自訂圓心的座標值。
傾斜 skewX(angle)、skewY(angle) skewX:matrix(1 0 tan(a) 1 0 0)
skewY:matrix(1 tan(a) 0 1 0 0)
分別是要設定 X 與 Y 方向的傾斜角度,不過與 scale 有點相同的地方,使用 skew 之後,也必須使用 translate 把位置調整回來才可以
備註:中括號為不是必須的值。

例題: 矩形以逆時針旋轉20度。
<rect fill="none" width="60" height="60" x="50" y="50" stroke="#000" stroke-width="2" />
<rect fill="#c00" width="60" height="60" x="50" y="50" transform="rotate(-20,50,50)" />
  
例題: 矩形以順時針傾斜50度。
<rect fill="none" width="60" height="60" x="50" y="50"
    stroke="#000" stroke-width="2" />
<rect fill="#c00" width="60" height="60" x="50" y="50"
    transform="skewX(50) translate(-60)" />
關於矩陣變形的詳細說,請參考transform-matrix

SVG 描邊(stroke)屬性

stroke 屬性定義元件的線條、文本或輪廓的顏色:
<svg height="80" width="300">
  <g fill="none">
    <path stroke="red" d="M5 20 l215 0" />
    <path stroke="black" d="M5 40 l215 0" />
    <path stroke="blue" d="M5 60 l215 0" />
  </g>
</svg>
stroke 五個設定
  • stroke :邊框的顏色
  • stroke-width:邊框的寬度
  • stroke-linecap:邊框端點的屬性 ( butt ( 預設 )、square、round )
  • stroke-linejoin:邊框接合尖角的屬性 ( miter ( 預設 )、round、bevel )
  • stroke-dasharray:虛線
除了邊框的顏色和寬度,storke 最重要的只有剩下的三個屬性, 首先我們看到stroke-linecap和stroke-linejoin,分別代表了兩個端點的屬性,以及兩條線段尖角接合處的屬性。
<polyline fill="none" stroke="#000000" stroke-width="10" points="83.678,119.133 113.376,89.434 143.075,119.133 "/>
<polyline fill="none" stroke="#000000" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" points="193.546,119.133
    223.245,89.434 252.943,119.133 "/>
<polyline fill="none" stroke="#000000" stroke-width="10" stroke-linecap="square" stroke-linejoin="bevel" points="
    307.677,116.758 337.376,87.059 367.076,116.758 "/>

最後一個屬性是stroke-dasharray,�媕Y的值是一個陣列,代表線段長度與虛線間隔長度的交錯數字,通常是兩個數字一組 ( 長度和間隔 ),如果是奇數,則最後數字接續的間隔,長度會以第一個數字為預設值,下方的圖片可以看出不同設定所造成的差異:

<line fill="none" stroke="#000000" stroke-dasharray="2" x1="0" y1="0" x2="100" y2="0"/>
<line fill="none" stroke="#000000" stroke-dasharray="2,5" x1="0" y1="10" x2="100" y2="10"/>
<line fill="none" stroke="#000000" stroke-dasharray="2,5,3" x1="0" y1="20" x2="100" y2="20"/>
<line fill="none" stroke="#000000" stroke-dasharray="2,5,3,10" x1="0" y1="30" x2="100" y2="30"/>
<line fill="none" stroke="#000000" stroke-dasharray="2,5,3,10,5" x1="0" y1="40" x2="100" y2="40"/>
<line fill="none" stroke="#000000" stroke-dasharray="2,5,3,10,5,1" x1="0" y1="50" x2="100" y2="50"/>

筆觸偏移動畫

使用 path 畫出的 svg 圖,加上動畫的樣式,即可逐點動態畫出。

使用 @keyframes 和 stroke-dashoffset 屬性,創建填充線動畫。

#line {
    stroke-dasharray: 1;  // 虛線間隔: 1px
    animation-name: fill-line;
    animation-duration: 5s;
}

@keyframes fill-line {
    from {stroke-dashoffset: 1;    }    // 虛線偏移: 1px
    to {  stroke-dashoffset: 0;    }
}

將此動畫樣式 line,添加到 SVG 的 中,如下。
<svg id="visual" viewBox="0 0 1280 800" preserveAspectRatio="none" >
  <path id="line"
        d="M150 0 L75 100 L225 100 Z"
        pathLength="1" fill="none" stroke-linecap="round"  stroke="#9370db" stroke-width="3">
   </path>
 </svg>

示例: 畫三角形

將路徑指令換成其他形狀的指令,如:

示例: 畫圓形
示例: 畫橢圓形
示例: 畫心形
示例: 畫豎起大拇指

參考animate-svg

SVG 文本 - <text>

<svg height="60" width="200">
  <text x="0" y="15" fill="red" transform="rotate(30 20,40)">I love SVG</text>
</svg>
I love SVG
<text> 元件可以使用 <tspan> 元件排列在任意數量的子組中。 每個 <tspan> 元件可以包含不同的格式和位置。
<svg height="90" width="200">
  <text x="50" y="20" style="fill:red;">Several lines:
    <tspan x="50" y="45">First line.</tspan>
    <tspan x="50" y="70">Second line.</tspan>
  </text>
</svg>
Several lines: First line. Second line.

路徑文字

將路徑定義在 <defs> 以便重複使用。之後在 <text> 內側創建 <textPath>。
使用 xlink:href="#id" 導入路徑,文字便可順著路徑顯示出來。
<svg width="250" height="250">
  <defs>
    <path id="path" d="M20 30 Q40 5,60 30 T90 60 L200 80" />
  </defs>
  <text>
    <textPath xlink:href="#path" style="font-size:25px; fill:green">
      Hello World!
    </textPath>
  </text>
</svg>
Hello World!

SVG 濾鏡元件

SVG 梯度

梯度是從一種顏色到另一種顏色的平滑過渡。 此外,可以將多個顏色過渡應用於同一元件。

SVG 中有兩種主要的梯度類型:

  • 線性(Linear)
  • 徑向(Radial)
<svg height="150" width="400">
  <defs>
    <linearGradient id="grad3" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
  </defs>
  <ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad3)" />
  <text fill="#ffffff" font-size="45" font-family="Verdana" x="150" y="86">
  SVG</text>
</svg>
SVG

如何使用 SVG 圖像

網頁引用 SVG 有三種做法:
  • Object:
    • <embed src="../svg/happy.svg" …>
    • <object data="../svg/happy.svg">
    • <iframe src="../svg/happy.svg" …>
  • Inline: <svg>…</svg>
  • Image:
    • <img src="../svg/happy.svg" …>
    • background: url('…')
       body {
         background-image: url(happy.svg);
       }
       

這是什麼寶可夢?

--> SVG 濾鏡元件

--> SMIL 動畫

參考資料