SVG <g>、<defs>、<symbol>和<use>元素詳解

admin發表於2017-10-15
實際應用中,可能需要多次重複出現一個相同的圖形。

最不明智的解決方案是每次都繪製一個全新的圖形,較好的解決方案是重複使用一個圖形。

下面通過程式碼例項分步介紹一下圖形重複使用的相關內容。

一.<g>元素:

g是group(分組)的縮寫。

<g>元素通常用來對相關圖形元素進行分組,以便統一操作,比如旋轉,縮放或者新增相關樣式等。

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
svg {
  border:1px solid red;
  margin:100px;
}
</style>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1"
        width="300" height="200">
    <g id="group" fill="red">
      <rect x="10" y="10" width="100" height="100" />
      <rect x="120" y="10" width="100" height="100" />
    </g>
  </svg>
</body>
</html>

上面程式碼將兩個矩形元素用<g>元素分組,就可以對它們統一操作,比如旋轉或者縮放等。

程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
svg {
  border:1px solid red;
  margin:100px;
}
</style>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1"
        width="300" height="200">
    <g id="group"
       transform="rotate(20)"
       fill="red">
      <rect x="10" y="10" width="100" height="100" />
      <rect x="120" y="10" width="100" height="100" />
    </g>
  </svg>
</body>
</html>

上面程式碼對<g>進行旋轉操作,也就是對此分組的進行整體旋轉,分組內圖形元素的相互關係會保持。

二.使用<use>元素進行重用:

<use>實現SVG現有圖形的重用,可以重用單個SVG圖形元素,也可以重用<g>定義的組元素。

程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
svg {
  border:1px solid red;
  margin:100px;
  width:500px;
  height:500px;
}
</style>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg"  version="1.1">
    <g id="group" fill="red" >
      <rect x="10" y="10" width="100" height="100"/>
    </g>
    <use id="one" x="0" y="110" xlink:href="#group"/>
    <use id="two" x="0" y="220" xlink:href="#group" stroke="black" stroke-width="2"/>
  </svg>
</body>
</html>

特別說明:為了便於演示,<g>分組中只保留了一個矩形元素。

下面對程式碼做一下分析:

(1).<g>元素可以直接顯示。

(2).<use>元素可以使用xlink:href屬性(屬性值是#+g元素id)多次引用<g>元素。

(3).被引用後建立的新元素是最初元素的一個副本;新元素會繼承最初元素的樣式、旋轉、縮放等特性。

(4).不能在新元素中覆蓋初始元素的樣式(例如描邊和填充)。

(5).x和y屬性規定新元素的座標原點。

最後一條需要著重說明一下,以上面程式碼的第一個<use>為例:

[XML] 純文字檢視 複製程式碼
<use id="one" x="0" y="110" xlink:href="#group" />

等同於如下程式碼:

[XML] 純文字檢視 複製程式碼
<use id="one" transform="translate(0, 110)" xlink:href="#group" />

位移是以初始元素的座標為參考,所以新元素的左上角位置是:初始x+新x和初始y+新y。

當然建立新的元素也會形成一個新的當前使用者座標系,這個新座標系的原點位置是在之前原點位置基礎上累加x和y值,上面的程式碼中,初始元素的座標系原點是(0,0),那麼新元素所在的使用者座標系原點(0,0)在初始元素使用者座標系的(0,110)處。

程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
svg {
  border:1px solid red;
  margin:100px;
  width:500px;
  height:500px;
}
</style>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <g id="group" fill="red">
      <rect
            x="90" y="110"
            width="100" height="100" />
    </g>
 
    <use id="one"
         transform="translate(0 110) rotate(10 0 0)"
         xlink:href="#group" />
 
    <rect id="rect"
          fill="blue"
          x="90" y="220"
          width="110" height="110"
          transform="rotate(10 0 110)"
          fill-opacity="0.5"
          />
  </svg>
</body>
</html>

上面程式碼的表現可以說明一切,下面簡單做一下介紹:

[XML] 純文字檢視 複製程式碼
<use id="one"
     transform="translate(0 110) rotate(10 0 0)"
     xlink:href="#group" />

translate(0 110)可以將座標原點從初始元素座標系的(0,0)移動到初始元素座標系的(0,110),在當前座標系當然是(0,0)。

rotate(10 0 0)設定元素旋轉角度10,圍繞當前使用者座標系的原點(位於初始元素座標系的(0,110)處)旋轉。

[XML] 純文字檢視 複製程式碼
<rect id="rect"
      fill="blue"
      x="90" y="220"
      width="110" height="110"
      transform="rotate(10 0 110)"
      fill-opacity="0.5"
      />

上面程式碼規定矩形的座標是(90,220),也就是在都不旋轉的情況下會和<use>的左上角重合。

transform="rotate(10 0 110)" 旋轉10度,旋轉的中心點是在初始元素座標系的(0,110)位置。

更多內容可以參閱以下三篇文章:

(1).SVG 座標系統詳解一章節。

(2).SVG transform用法詳解一章節。

(3).SVG transform座標變化深入理解一章節。

三.<defs>重用已儲存元素:

<defs>可以定義我們不想直接顯示的內容。

<g>分組定義的內容直接會顯示,所以<defs>在使用的時候會有更大的靈活性。

<g>和<defs>定義的圖形元素的樣式在被重用的新元素中都是無法被改變的;由於<g>中的內容會直接顯示,通常需要給元素一些樣式,所以會對應用帶來一些障礙;<defs>內部定義的元素不會直接顯示,可以不用事先定義樣式,而是在使用<use>例項化的時候再定義。程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
svg {
  border:1px solid red;
  margin:100px;
  width:500px;
  height:500px;
}
</style>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <defs>
      <rect
            id="defs"
            x="90" y="110"
            width="100" height="100" />
    </defs>
 
    <use id="ant"
         transform="translate(0 110) rotate(10 0 0)"
         fill="red"
         xlink:href="#defs" />
    <rect id="rect"
          fill="blue"
          x="90" y="220"
          width="110" height="110"
          transform="rotate(10 0 110)"
          fill-opacity="0.5" />
  </svg>
</body>
</html>

與<g>一個明顯的區別是,<use>引用的是內部元素的id。

可以認為<defs>是為了定義初始不可見且可重用的元件,而<g>是一個初始可見且本身就是一個元件(當然具有分組功能)。

三.<symbol>元素的使用:

<symbol>兼具<g>的分組功能和<defs>初始不可見的特性。

<symbol>能夠建立自己的視窗,所以能夠應用viewBox和preserveAspectRatio屬性。

程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
svg {
  border:1px solid red;
  margin:100px;
  width:500px;
  height:500px;
}
</style>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <symbol id="symbol" viewBox="0 0 250 250">
      <rect
            x="90" y="110"
            width="100" height="100" />
    </symbol>
 
    <use id="ant"
         transform="translate(0 110) rotate(10 0 0)"
         fill="red"
         xlink:href="#symbol" />
    <rect id="rect"
          fill="blue"
          x="90" y="220"
          width="110" height="110"
          transform="rotate(10 0 110)"
          fill-opacity="0.5" />
 
  </svg>
</body>
</html>

更多內容可以參閱下面幾篇文章:

(1).SVG transform座標變化深入理解一章節。

(2).SVG viewbox和preserveAspectRatio詳解一章節。

相關文章