ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SVG文档结构

2021-10-11 12:57:58  阅读:168  来源: 互联网

标签:样式 SVG 元素 文档 样式表 结构 属性


Chapter 5. Document Structure

我们偶然提到过,SVG 允许您将文档的结构与其表示分离。在这一章中,我们将比较和对比这两者,更详细第讨论文档外观方面,然后展示一些 SVG 元素,这些元素您能够使文档结构更加清晰,更容易阅读,更容易维护。

Structure and Presentation

就像章节 1 提到的那样,在 Basic Shapes 中,XML的目的使提供一种方法来组织数据,并将这个结构从它的视觉呈现中分离出来。想一想那一章中画的猫。你识别出它是一只猫,是因为它的结构,几何形状的位置和大小构成了绘图。如果我们要进行结构性改变,例如缩短它的胡须,把鼻子变得更圆,让耳朵变得更长,耳朵的结尾处边等更圆滑。这个结构,因此,告诉你什么是图形(graphic).

这并不是说可视化样式的信息不重要;如果我们用紫色的粗线和灰色的内部来画这只猫,他就会被认出来是一只猫,但它的外观就不那么赏心悦目了。差异如图5-1所示。XML鼓励您分离结构(structure)和外观(presentation);不幸的是,许多关于XML的讨论都强调构(structure)而忽略了外观(presentation)。我们会纠正这个错误,通过详细介绍如何在 SVG 中指定外观(presentation)。

在这里插入图片描述

Using Styles with SVG

SVG 为了提供了四种方式指定一个图形各个方面的外观: 通过内联的样式(inline styles), 内部的样式表(internal stylesheets), 外部的样式表(external stylesheets), 和外观属性(presentation attributes)。让我们依次检查每一个。

Inline Styles

样例5-1 使用了内联样式(inline styles)。这正是我们目前使用外观信息的方式。我们设置 style 属性的值为一系列视觉属性,这些属性在附录B中的 Anatomy of a Style 中有详细描述。

Example5-1:Use of inline styles

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

Internal Stylesheets

你不需要把您的 styles 放置到每个 SVG 元素当中;你可以创建一个内部的样式表(internal stylesheets)来收集公共使用的样式,可以应用一个特定元素出现的所有地方,
或者使用 named classes,将样式应用于特定的元素。样例5-2设置了一个内部样式表(internal stylesheets),该样式表将用淡蓝色的双虚线绘制圆,圆得内部使用淡黄色填充。
这个样式表写在 <defs> 元素中,我梦将在下一个章节中讨论。

这个例子接着绘制了一些圆。这些圆在图5-2的第二行,在内部样式表中具有覆盖规范的内联样式。

Example5-2. Use of internal stylesheet

<svg width="200px" height="200px" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css"><![CDATA[
  circle {
    fill: #ffc;
    stroke: blue;
    stroke-width: 2;
    stroke-dasharray: 5 3
  }
]]></style>
</defs>
<circle cx="20" cy="20" r="10"/>
<circle cx="60" cy="20" r="15"/>
<circle cx="20" cy="60" r="10" style="fill: #cfc"/>
<circle cx="60" cy="60" r="15"
style="stroke-width: 1; stroke-dasharray: none;"/>
</svg>

在这里插入图片描述

External Stylesheets

如果您想将一组样式应用到多个 SVG 文档中,你可以拷贝这组内部样式(internal stylesheet),然后粘贴到每个要应用的文档中。这种方法,当然,如果您需要
对所有文档进行全局更改,那么对于大量文档来说,合适不切实际的。取而代之的,你应当取出 <style> 开始和结束标签之家的所有信息(不包括 <![CDTA[]]>)。
然后保存到外部文件中,这个文件变成一个外部样式表(external stylesheet)。 样例5-3 显示了一个外部样式(external stylesheet), 保存在一个名为
ext_style.css 的文件中。这个样式使用了一系列的选中器(selectors), 包括 * ,它为所有没有其他样式的元素设置一个默认值,它与SVG一起,生成图5-3.

Example 5-3.External stylesheet

* { fill:none; stroke: black; } /* default for all elements */

rect { stroke-dasharray: 7 3; }

circle.yellow { fill: yellow; }

.thick { stroke-width: 5; }

.semiblue { fill:blue; fill-opacity: 0.5; }

在这里插入图片描述

样例5-4显示了一个完整的SVG文档(包括<?xml ...?><?xml-stylesheet ...?><!DOCTYPE>)和引用外部样式表的引用。

Example 5-4. SVG file that references an external stylesheet

<?xml version="1.0"?>
<?xml-stylesheet href="ext_style.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
width="200px" height="200px" viewBox="0 0 200 200">
<line x1="10" y1="10" x2="40" y2="10"/>
<rect x="10" y="20" width="40" height="30"/>
<circle class="yellow" cx="70" cy="20" r="10"/>
<polygon class="thick" points="60 50, 60 80, 90 80"/>
<polygon class="thick semiblue"
points="100 30, 150 30, 150 50, 130 50"/>
</svg>

注意:内联样式(Inline styles) 的渲染几乎总比内部样式表(internal stylesheet)或外部样式(external stylesheet)快;样式表(stylesheets)
和 classes 增加了渲染的时间,时间的长短取决于查询和解析的快慢。然而,样式表(stylesheets)更容易维护,更小的文件大小和缓存,使得文件加载速度更快。

Presentation Attributes

尽管绝大多数SVG文档将使用样式来表示信息,SVG 允许您已外观属性的形式指定这些信息。如果不用下面的表示方法:

<circle cx="10" cy="10" r="5" style="fill: red; stroke:black; stroke-width: 2;"/>

您可以将每个属性写成一个属性:

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

如果你认为这是结构(structure)和外观(presentation)的混合,你是对的。外观属性确实会派上用场,但是,当您通过将XML数据源转换为SVG来创建SVG文档时。
你将会在 15 章中看到。在这些情况下,为每个外观属性创建一个独立的属性,会比创建一个独立的 style 属性内容更加容易。如果你展示的环境不支持样式表,
你可能也需要使用外观属性。

外观属性位于优先级列表的最底部。任何通过 内联样式(inline style),内部样式表(internal stylesheet),或外部样式表(external stylesheet)指定的样式都将覆盖
通过外观属性(presentation attribute)指定的样式,尽管外观属性(presentation attribute)覆盖继承的样式。在下面的SVG文档中,这个圆将会以红色填充,而不是绿色:

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <defs>
      <style type="text/css"><![CDATA[ circle { fill: red; } ]]></style>
  </defs>
<circle cx="20" cy="20" r="15" fill="green"/>
</svg>

我们再一次强调,使用样式属性(style attributes) 或者 样式表(stylesheets) 应当一直是你的第一选择。样式表允许您将一系列复杂的填充和画笔特征,
应用到文档中所有拥有该效果的某些元素中,而不需要每个元素都有一份重复的信息。样式表的这种能力和灵活性,允许您已最少的工作量对多个文档的外观和感觉进行
重大调整。

Grouping and Referencing Objects

虽然我们可以将任何一幅画定义为一组无区别的形状(shapes)和线条(lines),但大多数非抽象艺术都是由一组形状(shapes)和线条(lines)组成的,
这些线条构成了可识别的命名对象。

The <g> element

<g> 元素将它的所有子元素,集合为一个组,并且通常具有ID属性,来为这个组指定唯一的名称。每个组可能也由它自己的 <title><desc> ,
以便为基于文本的 XML应用程序提供表示,或者在不能展示的时候,提供展示。许多 SVG 渲染客户端,当你将鼠标悬停在该组内的任何图形上是,
将显示一个提示消息,内容为 <title> 元素的文本。屏幕前的读者将会看到 <title> 元素 和 <desc> 元素的内容。

除了概念上的清晰之外,这还来自于分组和记录对象的能力,<g> 元素还提供了符号上的便利。在开始的 <g> 标签中指定的任何样式都将应用于组中的
所有子元素。在样例5-5中,这样我们就不必在图5-4中所示的每个元素上复制 style="fill:none; stroke:black;"。也可以将一个组嵌套在另一个组中,
尽管您在第6章之前不会看到任何示例。

元素类似于 Adobe Illustrator 等程序中的 Group Object 函数。它还提供了类似于此类程序中的层概念的功能;层也是关联对象的分组。

Example 5-5.Simple use of the g element

<svg width="240px" height="240px" viewBox="0 0 240 240" xmlns="http://www.w3.org/2000/svg">
<title>Grouped Drawing</title>
<desc>Stick-figure drawings of a house and people</desc>
<g id="house" style="fill: none; stroke: black;">
    <desc>House with door</desc>
    <rect x="6" y="50" width="60" height="60"/>
    <polyline points="6 50, 36 9, 66 50"/>
    <polyline points="36 110, 36 80, 50 80, 50 110"/>
</g>
<g id="man" style="fill: none; stroke: black;">
    <desc>Male human</desc>
    <circle cx="85" cy="56" r="10"/>
    <line x1="85" y1="66" x2="85" y2="80"/>
    <polyline points="76 104, 85 80, 94 104" />
    <polyline points="76 70, 85 76, 94 70" />
</g>
<g id="woman" style="fill: none; stroke: black;">
    <desc>Female human</desc>
    <circle cx="110" cy="56" r="10"/>
    <polyline points="110 66, 110 80, 100 90, 120 90, 110 80"/>
    <line x1="104" y1="104" x2="108" y2="90"/>
    <line x1="112" y1="90" x2="116" y2="104"/>
    <polyline points="101 70, 110 76, 119 70" />
</g>
</svg>

在这里插入图片描述

The <use> Element

复杂的图形通常包含重复的元素。例如,产品宣传册的每一页的左上角和右下角都可能有公司的 logo。如果你在一个图形设计程序中绘制这个宣传册,你只需要
绘制这个 logo 一次,将它的元素打包在一起,然后将它拷贝粘贴到其他要使用位置。 SVG 中的 <use> 元素为您提供了类似复制和粘贴功能的组(group),
您已经通过 <g> 元素或者任何单独的图形元素(例如你想要一个复杂的多边形形状,您只需要定义一次)。

一旦你定义了一组图形对象,你可以再一次展示它们,只需要通过 <use> 标签指定您想要重复利用的组,把它的 URI 设置到 xlink:href 属性中,
并指定 group 的(0,0)点应该移动到的位置的x坐标和y坐标。(我们将在第6章看到另一种实现这种效果的方法,在 The translate Transformation 章节。)
所以,为了创建另一个房子,并设置这些人物,如图5-5所示,你只需要把这些行放置在结束标签 </svg> 的前面:

<use xlink:href="#house" x="70" y="100"/>
<use xlink:href="#woman" x="-80" y="100"/>
<use xlink:href="#man" x="-30" y="100"/>

在这里插入图片描述

The <defs> Element

你可能已经注意掉前面例子的一些缺陷:

  • 决定将重用的男人和女生放置在哪里,数学上要求您知道原始的位置,并将其作为基础。而不是用一个简单的数字,比如零。
  • 房子填充和画笔的颜色将会和原始图像建立联系,并不能被 <use> 所覆盖。这意味着你不能作一排五颜六色的房子。
  • 这个文档绘制了三个组:女人,男人和房子。你不能“把它们存起来”,只画一组房子或一组人。

<defs> 元素(定义元素 definitions)解决了这些问题。通过将分组对象放在开始和结束的<defs>标签之间。您指示 SVG 定义它们而不显示它们。
SVG 规范中,实际上,建议您将所有希望重用的对象放在 <defs> 元素之中,以便在流环境(streaming environment)中工作的 SVG 查看器可以更
有效地处理数据。在样例5-6 当中,房子,男人和女人都定义在左上角的原始坐标(0,0)处,并且房子没有设置任何颜色。因为这些组将放到<defs>元素当中,
它们不会立马绘制到屏幕之上。而是作为一个模板(template)供将来使用。我们也创建了另外一个称为 couple 的房子,犯规来,使用了 man 和 woman 组。
(注意图5-6的底部的前半边不能使用 couple, 因为它用了不同的排列方式。)

Example 5-6. The defs element

<svg width="240px" height="240px" viewBox="0 0 240 240"
  xmlns="http://www.w3.org/2000/svg">
  <title>Grouped Drawing</title>
  <desc>Stick-figure drawings of a house and people</desc>
  <defs>
    <g id="house" style="stroke: black;">
      <desc>House with door</desc>
      <rect x="0" y="41" width="60" height="60"/>
      <polyline points="0 41, 30 0, 60 41"/>
      <polyline points="30 101, 30 71, 44 71, 44 101"/>
    </g>
    <g id="man" style="fill: none; stroke: black;">
      <desc>Male stick figure</desc>
      <circle cx="10" cy="10" r="10"/>
      <line x1="10" y1="20" x2="10" y2="44"/>
      <polyline points="1 58, 10 44, 19 58"/>
      <polyline points="1 24, 10 30, 19 24"/>
    </g>
    <g id="woman" style="fill: none; stroke: black;">
      <desc>Female stick figure</desc>
      <circle cx="10" cy="10" r="10"/>
      <polyline points="10 20, 10 34, 0 44, 20 44, 10 34"/>
      <line x1="4" y1="58" x2="8" y2="44"/>
      <line x1="12" y1="44" x2="16" y2="58"/>
      <polyline points="1 24, 10 30, 19 24" />
    </g>
    <g id="couple">
      <desc>Male and female stick figures</desc>
      <use xlink:href="#man" x="0" y="0"/>
      <use xlink:href="#woman" x="25" y="0"/>
    </g>
  </defs>
  <!-- make use of the defined groups -->
  <use xlink:href="#house" x="0" y="0" style="fill: #cfc;"/>
  <use xlink:href="#couple" x="70" y="40"/>
  <use xlink:href="#house" x="120" y="0" style="fill: #99f;"/>
  <use xlink:href="#couple" x="190" y="40"/>
  <use xlink:href="#woman" x="0" y="145"/>
  <use xlink:href="#man" x="25" y="145"/>
  <use xlink:href="#house" x="65" y="105" style="fill: #c00;"/>
</svg>

在这里插入图片描述

<use> 元素不限于使用来自它所在文件的对象;xlink:href 属性可以指定任何有效的文件或URI。这使得在一个 SVG 文件中收集一组公共元素,并从其他文件中选择性地使用它们称为可能。例如,你可以创建一个名叫 identity.svg 的文件,它包了你结构中要使用的所有标识图形:

<g id="company_mascot">
    <!-- drawing of company mascot -->
</g>
<g id="company_logo" style="stroke: none;">
   <polygon points="0 20, 20 0, 40 20, 20 40" style="fill: #696;"/>
   <rect x="7" y="7" width="26" height="26" style="fill: #c9c;"/>
</g>
<g id="partner_logo">
   <!-- drawing of company partner's logo -->
</g>

然后通过下面的方式来引用它们:

<use xlink:href="identity.svg#company_logo" x="200" y="200"/>

警告:并不是所有的 SVG 查看器都支持外部引用,特别是网页浏览器,出于安全原因。一些浏览器(特别是 Internet Explorer)目前根本不支持外部文件引用。
其他的只允许 <use>元素来引用来自同一个域名或者同一台网络服务的文件,它被专门配置为允许跨源(cross-origin)使用。

The <symbol> Element

<symbol> 元素提供了另外一种方法来分组元素。不像 <g> 元素, <symbol> 元素永远不会被显示,因此,您不必将它包含在 <defs> 规范中。
然而,这样做是习惯,因为 symbol 实际上是你为以后使用而定义的东西。symbol 还可以指定 viewBox 和 preserveAspectRatio 属性,通过向<use>
元素添加 width 和 height 属性,允许一个 symbol 是适应 viewport 的大小。样例5-7 显示对于一个简单 group(顶部的两个八边形)来说,忽略了
width 和 height 属性,但是在显示 symbol 时使用了 width 和 height。图5-7中右下边的八边形被切断了, 因为 preserveAspectRatio 被设置
成了 slice。 <rect> 元素用于显示每次使用的坐标。

Example 5-7. Symbols versus groups

<svg width="200px" height="200px" viewBox="0 0 200 200"
  xmlns="http://www.w3.org/2000/svg">
  <title>Symbols vs. groups</title>
  <desc>Use</desc>
  <defs>
    <g id="octagon" style="stroke: black;">
      <desc>Octagon as group</desc>
      <polygon points="
36 25, 25 36, 11 36, 0 25,
0 11, 11 0, 25 0, 36 11"/>
    </g>
    <symbol id="sym-octagon" style="stroke: black;"
      preserveAspectRatio="xMidYMid slice" viewBox="0 0 40 40">
      <desc>Octagon as symbol</desc>
      <polygon points="
36 25, 25 36, 11 36, 0 25,
0 11, 11 0, 25 0, 36 11"/>
    </symbol>
  </defs>
  <g style="fill:none; stroke:gray">
    <rect x="40" y="40" width="30" height="30"/>
    <rect x="80" y="40" width="40" height="60"/>
    <rect x="40" y="110" width="30" height="30"/>
    <rect x="80" y="110" width="40" height="60"/>
  </g>
  <use xlink:href="#octagon" x="40" y="40" width="30" height="30"
    style="fill: #c00;"/>
  <use xlink:href="#octagon" x="80" y="40" width="40" height="60"
    style="fill: #cc0;"/>
  <use xlink:href="#sym-octagon" x="40" y="110" width="30" height="30"
    style="fill: #cfc;"/>
  <use xlink:href="#sym-octagon" x="80" y="110" width="40" height="60"
    style="fill: #699;"/>
</svg>

在这里插入图片描述

The <image> Element

<use> 让你唔够复用一个 SVG 文件中的一部分,<image> 元素包含了一个完整的 SVG 文件或者网格文件。如果你引入的是一个 SVG 文件,x, y, width 和 height 属性建立了引用文件绘制的视图窗口(viewport)。如果你包含的是一个网格文件,它将被缩放以使用属性值指定的矩形区域。 SVG 规范要求查看器同时支持JPEG和PNG两种网格类型的文件;查看器可能支持其他文件。例如,大部分浏览器将迟迟GIF。样例5-8展示了如何使用SVG包含JPEG图像。结果如图5-8所示。

Example 5-8. Use of the image element

<svg width="310px" height="310px" viewBox="0 0 310 310"
  xmlns="http://www.w3.org/2000/svg">
  <ellipse cx="154" cy="154" rx="150" ry="120" style="fill: #999999;"/>  <!-- 1 -->
  <ellipse cx="152" cy="152" rx="150" ry="120" style="fill: #cceeff;"/> <!-- 2 -->
  <image xlink:href="kwanghwamun.jpg"
    x="72" y="92"
    width="160" height="120"/>  <!-- 3,4,5 -->
</svg>

在这里插入图片描述

  • 注释1: 创建一个灰色的椭圆以模拟一个阴影。
  • 注释2: 创建主蓝色椭圆,因为它出现在灰色椭圆之后,所以它显示在灰色椭圆上面。
  • 注释3: 通过xlink:href指定要引入文件的URI。
  • 注释4: 通过 x 和 y 指定图像的左上角。
  • 注释5: 通过 width 和 height 指定图片需要进行缩放的比例。

在这里插入图片描述

<image> 元素可以有一个 preserveAspectRatio 属性,来指示当图像文件的尺寸与元素的 width 和 height 不匹配时应做什么。默认的值是:xMidYMid meet,将缩放图像,以适应并居中于你指定的矩形区域(参考 Preserving Aspect Ratio 章节)。如果你包含的是一个 SVG 文件,您可以在 preserveAspectRatio 值的开头添加关键字 defer(比如 defer xMidYMin meet);如果被包含的图像有 preserveAspectRatio 属性,就使用这个属性。

  • [7] In Chapter 11, we’ll see another way to create a drop shadow in Creating a Drop Shadow.

标签:样式,SVG,元素,文档,样式表,结构,属性
来源: https://blog.csdn.net/fudaxing/article/details/120700727

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有