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

2017-10-15 09:49| 作者: admin| 查看: 18381| 评论: 0|来自: 蚂蚁部落

实际应用中,可能需要多次重复出现一个相同的图形。

最不明智的解决方案是每次都绘制一个全新的图形,较好的解决方案是重复使用一个图形。

下面通过代码实例分步介绍一下图形重复使用的相关内容。

一.<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详解一章节。


鲜花

握手

雷人

路过

鸡蛋
返回顶部