网页中使用SVG"/>
2.网页中使用SVG
Chapter2. Using SVG in Web Pages
约翰多恩说过,没有人是一座孤岛。同样,SVG 也不是孤立存在的。您可以查看 SVG 图像本身,作为一个独立的文件在您的 web 浏览器或 SVG 查看器中查看。本书中的许多例子都是以这种方式进行的。但是在其他例子中,你将想让你的图像集成到一个大的文档中,而这个文档包含了文本段落,表格,或者其他不能够单独通过使用 SVG 展示的内容。这章``描述了各种方法,用于将 SVG 集成到 HTML 或者其他类型的文档中。
图2-1 显示了上一章节绘制出来的猫咪,以四种不同方式插入到 HTML 页面中。结果看上去都几乎一模一样,但是每种方法都有自己的优点和局限性。
SVG as an Image
SVG 是一种图像格式,因此它可以像其他图像类型一样,使用同样的方式包含进 HTML 页面中。实际存在两种方法:你可以使用一个 HTML 标记语言中的 <img>
元素标签引入这张图像(在这张图像时页面内容的基本组成部分时推荐使用这种方法);或者你可以将图片作为一个 另外一个元素的 CSS 样式属性插入(当图像作为装饰图像时推荐使用这种方法)。
无论您使用哪种方法,将 SVG 作为一张 image 都会导致某些限制。图像将会被渲染("绘制"的意义是 SVG 代码被转换为网格图像显示),渲染和主要网页分开进行, 并且没有方法在两者之间进行通信。在主页面定义的样式将不会影响到 SVG。如果你的 SVG 图像包含文本,你可能需要在你的 SVG 代码中定义一个默认的字体大小,也可能需要定义一个长度来表示相关的字体大小。此外,在主网页上允许的脚本将无法发现或修改任何 SVG 的文档结构。
大多数 web 浏览器不会加载作为图像使用的, 引用 SVG 的文件。这包括其他图像文件,外部脚本,甚至是 webfont 文件。根据浏览器和用户的安全设置,SVG 文件中定义的脚本可能不会运行,URL片段(URL中字符 # 后面的部分,它表示您感兴趣的文件的哪一部分)可能会被忽略。动画,就像第 12 章节定义的,在图像中被支持(通常浏览器支持 SVG 中的动画)。
Including SVG in an <img>
Element
HTML 的 <img>
元素定义了一个区域,浏览器应当在该区域绘制一个外部的图像文件。图像文件使用 src(source) 属性指定。 在 <img>
元素中包含一张 SVG 图像,只需要将 source 指定到 SVG 文件在你服务器上保存的位置。当然,你也需要通过 alt 属性或者 title 属性指定描述信息。这样的话,用户在无法看到图片的情况下,还能够明白它代表的是什么。例如:
<img src="cat.svg" title="Cat Image"
alt="Stick Figure of a Cat" />
注意:即使绝大多数浏览器现在已经支持把 SVG 当做图像处理,一些老的浏览器在不知道如何渲染这个文件的适合,将会显示一个损坏的文件图标(或者什么都不显示)。对于其他浏览器,你需要确定你的 Web 服务器已配置为以 .svg 结尾的文件声明正确的媒体类型标题(image/svg+xml)。
图像的高度和宽度能够通过使用属性(attributes)或者 CSS properties(优先) 设置。其他 CSS 属性控制图像在网页中的位置。如果你不指定 <img>
元素的尺寸,将会使用图像本身的尺寸。如果你只指定了宽度和高度中的一个,另一个维度按比例缩放,使纵横比(宽度与高度之比)与图像内在的尺寸相匹配。
对于网格图像,图像内在的尺寸是以像素为单位的。而 SVG 图像,它更复杂。如果文件中的根元数 <svg>
明确指定了高度和宽度属性。 那么指定的宽度和高度将用于文件的内在尺寸。如果只指定了高度或者宽度中的一个,而没有都指定,同时 <svg>
元素由一个 viewBox 属性,然后, viewBox 将用于计算纵横比,图像将进行缩放以匹配指定的尺寸。
否则,如果 <svg>
有 viewBox 属性 但是没有尺寸,那么 viewBox 的高度和宽度部分将被当作以像素为单位的尺寸。 如果这一切听起来不可理解。请放心,我们将在第 3 章 Specifying User Coordinates for a Viewport 介绍 viewBox 的属性。
如果 <img>
元素和 <svg>
元素都没有关于图像大小的任何信息,浏览器应将默认的 HTML 大小应用于嵌入式内容,高 150 像素,宽 300 像素,但最好不要依赖它。
Including SVG in CSS
各种各样的 CSS 样式属性接收一个指向图像文件的 URL 作为值。最常使用的是 background-image 属性, 将图像(或多个分层图像)绘制在使用了该 styleId 元素的文本内容下面。
默认情况下,一个背景图以它固有的尺寸绘制,然后在被指定的元素尺寸范围内的水平方向和垂直方向重复绘制。而 SVG 文件的固有尺寸的决定方式,和用 <img>
元素包含 SVG 的方式一样。如果没有固有尺寸, SVG 图像将放大到被指定元素相同的高度和宽度。尺寸大小可以使用 background-size 属性显式设置,重复方式可以通过 background-repeat 属性设置,图像的位置可以通过 background-position 属性设置:
div.background-cat {
background-image: url("cat.svg");
background-size: 100% 100%;
}
备注: 当使用多个网格类型的小型图标和徽标时,在单个图像文件中将所有图像排列在网格中是很常见的,然后使用 background-size 和 background-position 来正确显示每个元素的图像。通过这种方法,网页浏览器只需要下载一个图像文件,从而更快地显示网页。复合图像文件称为 CSS sprite, 以一个神话般的乐于助人的精灵命名,神奇地使事情变得更容易。SVG 文件能够被设置成 sprites, 浏览器能够更快地渲染它们,但您可能应该避免使 sprite 文件过大。
SVG 定义了在一个图像文件中创建多个图标的其他方式;然后你使用 URL fragments 指定显示哪一个图标。理想情况下,这些将基于 sprites 的 background-position 属性。然而,就像先前提到的,一些浏览器在将 SVG 作为 image 渲染的时候会忽略掉 URL fragments, 因此,这些功能目前在 CSS 中没有多大的实际用途。
除了作为背景图之外, SVG 文件可在 CSS 中用作 list-image(用于创建装饰性编号列表)或者 border-image(用于创建天马行空的边界)。
SVG as an Application
要将外部 SVG 文件集成到 HTML 页面中, 而不受把 SVG 作为 image 的限制,您可以使用 embedded object。
在 HTML(version 4 以上的版本) 和 XHTML 文档中嵌入外部文件通用的方法是使用 <object>
元素。和 <img>
类似,<object>
能够用来嵌入图像,或者类似于 <iframe>
元素, 嵌入单独的 HTML/XML 文档。更重要的是,它也可以用来嵌入任意类型的文件,因为浏览器有一个应用程序(浏览器插件或扩展)来解释该文件类型。一些老的浏览器无法直接显示 SVG 图像,而使用 object 嵌入您的 SVG 能够让用户可以看到您的图像。前提是它们有一个 SVG 插件。
<object>
元素的 type 属性指明了你嵌入文件的类型。 type 属性的值只能是有效的互联网媒体类型(通常称为 MIME 类型)。对于 SVG 图像来说,使用 type = “image/svg+xml”。
浏览器使用这个文件类型来判断如何(能不能)显示这个文件,而且不需要下载这个文件就可以先进行判断。文件的位置是通过 data 属性指定的。而 alt 和 title 属性的工作方式和 在 <image>
元素中一样。
object 元素必须有一个开始和结束标签。如果 object 的数据无法显示,那么将显示开始和结束标签之间包含的任何文本。以下代码在不支持 SVG 的浏览器中显示了文本解释和一个网格图像。
<object data="cat.svg" type="image/svg+xml"
title="Cat Object" alt="Stick Figure of a Cat" >
<!-- As a fallback, include text or a raster image file -->
<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>
<OBJECT>
VERSUS<EMBED>
在引入<object>
元素之前,有些浏览器使用非标准的<embed>
元素来达到同样的目的。它现在已经被采纳为标准,如果你担心老版本的浏览器的支持问题,可以使用<EMBED>
替代<object>
元素。 为了获得更广泛的支持。可以在<object>
标签的里面使用<embed>
,以达到向后兼容的目的。
当你将一个 SVG 文件作为一个嵌入的对象时(无论使用 <object>
还是 <embed>
),外部文件的渲染方式与用 <img>
元素包含的渲染方式一样:图像被缩放以适应嵌入元素的宽度和高度,并且图像不会继承任何在父类文档中声名的任何样式。
但是,与图像不同的是,嵌入的 SVG 可以包含外部文件,脚本可以在对象和父页面之间通信,如 Interacting with an HTML Page 中所描述的那样。
SVG Markup in a Mixed Document
将 SVG 作为图像集成到网页中和应用程序中的方法都是显示完整,独立的 SVG 文件的方法。然而,也可以在单个文件中将 SVG 代码和 HTML 或者 XML 标签混合。
将您的标记合并到文件中可以加快您的网页加载时间,因为浏览器并不需要为图像下载单独的文件。然而,如果你网站中的许多网页使用了同样的图像,而你重复的把 SVG 标记混合到每个网页中,这样会增大下载文件的大小,同时消耗更多的时间下载该文件。
更重要的是,在应用 CSS 样式和使用脚本时,混合文档中的所有元素将被视为单个文档对象。
SVG中的外部对象 Foreign Objects in SVG
混合内容的一种方法是在 SVG 中插入 HTML(或其他)内容。 SVG 规范定义了在图形的指定区域内嵌入此类 “foreign” 内容的方法。
<foreignObject>
元素在 web 浏览器(或者其他 SVG 查看器)中定义了一个矩形区域,这个区域应该绘制 <foreignObject>
元素所包含的子节点 XML 内容。浏览器负责决定如何绘制这些内容。子节点内容通常是 XHTML(符合 XML 的 HTML)代码,但它可以是 SVG 查看请能够显示的任何形式的 XML。内容类型是通过使用 XMLNS 属性在子内容上声名 XML namespace 来定义的。
矩形绘制区域是通过 <foreignObject>
元素的 x,y,width,height 属性定义的。和使用 <use>
和 <image>
元素的方式类似, 我们将在第5章中讲解。
矩形在本地 SVG 坐标系中求值。这也将受制于坐标系转换(transformation)(我们将在第 6 章中讨论)或其他 SVG 效果。子 XML 文档通常呈现为一个矩形框架。然后像处理其他 SVG 图像一样处理结果。 一个包含 XHTML 段落的 SVG 外部对象如图 2-2 所示。
<foreignObject>
元素具有创建混合 SVG/XHTML 文档的巨大潜力,但目前还没有得到很好的支持。Internet Explorer(至少到版本11)根本不支持它,并且在其他浏览器的实现中存在显示不一致的bug。
如果你像定义向后兼容的文本,以防止 SVG 查看器无法显示外部内容, 你可以使用 <switch>
元素的 requiredFeatures 属性,如图2-1所示。 在支持 XHTML 和 foreign objects 的浏览器中,代码创建图2-2;在其他浏览器中,它显示 SVG 文本。
<switch>
元素指示 SVG 查看器只绘制 requiredFeatures, requiredExtensions 和 systemLanguage 测试属性为 true 或者缺少的第一个直接子元素(以及所有子元素)。 我们将讨论在 第 9 章 The <switch>
Element 中如何使用 systemLanguage 属性切换不同的文本。当测试所需要的功能时,使用规范中给出的 URL 字符串之一。支持时扩展特性的一部分。
注意:不幸的是,这里没有一致性,跨浏览器方式指定需要哪种类型的外部对象。也许您想使用 MathML 与语言来显示图表的公式。同时提供一个普通文本版本的内容,在浏览器无法解析 MathML 的时候显示,以兼容老版本浏览器。requiredExtensions 属性应该指示需要添加什么类型的功能,但是 SVG1.1 规范没有清楚地描述应该如何标识扩展,除了说它应该是一个 URL, firefox 使用 XML namespace URL, 但其他浏览器不使用。
Example 2-1. The element, with a
<g transform="skewX(20)">
<switch>
<!-- select one child element -->
<foreignObject x="1em" y="25%" width="10em" height="50%"
requiredFeatures=
"">
<body xmlns="">
<p>This is an XHTML paragraph embedded within an SVG!
So this text will wrap nicely around multiple lines,
but it will still be skewed from the SVG transform.
</p>
</body>
</foreignObject>
<text x="1em" y="25%" dy="1em">
This SVG text won't wrap, so it will get cut off…
</text>
</switch>
</g>
Inline SVG in XHTML or HTML5
将 SVG 与 XHTML 混合的另一种方法是在 XHTML 文档中包含 SVG 标签;它还可以使用HTML5 语法处理非 XML 兼容的 HTML 文档。这种在 web 网页中包含 SVG 的方法称之为 内联SVG(InLine SVG)。将其与作为图像或对象嵌入的 SVG 区分开来。尽管它实际上应该称为 InFile SVG,因为没有要求 SVG 代码必须全部出现在一行上!
在 2012 年之后发布的绝大多数桌面版 web 浏览器,都支持 Inline SVG, 包括最新的手机端浏览器。对于 XHTML, 你只需要注意,通过在 SVG namespace 中定义所有的 SVG 元素,你就可以切换成 SVG。最方便的方法是在最顶层的 <svg>
元素上设置 xlmns=“”, 它将更改该元素及其所有子元素的默认 namespace。 对于 HTML5 文档(一个以 <!DOCTYPE html>
开头的文件),您可以跳过标记中的 namespace 声明。 HTML 解析器会自动识别 <svg>
元素和它们的子元素,<foreignObject>
元素的子元素除外,都在 SVG namespace 中。
在 (X)HTML 文档中插入 SVG 标记语言比在 SVG 文档中插入 (X)HTML 语言要简单很多:你不需要一个单独的 像 <foreignObject>
之类的元素,用于渲染SVG, 相反的,你可以将定位样式应用到 <svg>
元素,让它称为你的图形框架。
默认情况下, SVG 将在 inline 显示模式下定位(这意味着它将插入在所插入位置之前的文本和之后的文本所在的同一行),然后根据 <svg>
元素的 height 和 width 属性调整大小, 你可以通过设置 CSS 属性的 height 和 width 来改变大小, 如果想改变位置,可以使用 CSS positioning 属性中的 display, margin, padding 和 其他位置属性。
图2-2 给出了在一个非常简单的 HTML5 文档中绘制一个非常简单的 SVG 的代码。结果如图2-3 所示。 <svg>
元素中的 xmlns 属性对于 HTML5 标签来说是可选的。 对于一个 XHTML 文档,你需要修改文件顶部的 DOCTYPE 声明,同时需要使用 <![CDATA[....]]>
块包住 <style>
元素中的 CSS 代码。
如果没有用 CSS 或者属性设置 SVG 的高度和宽度, web 浏览器就要使用默认的 150像素X300像素大小,但是需要注意!许多浏览器使用了不同的默认大小。不幸的是,不像在 <img>
元素中使用 SVG 文件,你不能只设置宽度和高度中的一个,然后基于 viewBox 属性定义的宽高比缩放这张 SVG 图像。
Example 2-2. Inline SVG within an HTML file
- 第一个样式规则定义了 SVG 在 HTML 文档中的位置和大小。
- 你也可以使用 CSS 属性定义 SVG 将要绘制的区域的样式。
- 为主文档定义的样式将被 SVG 继承。
- 还可以在主样式表中为 SVG 元素定义样式。
SVG in Other XML Applications
XML namespace 能够用于在其他 XML 文档中识别 SVG 标签,其他 XML 标记不仅仅是 XHTML。 具体细节依赖于主 XML 文档的语法, 但是有两个明显的要求: XML 文档必须清晰地为一个 SVG 元素定义一个 layout box, 并且显示这个文档的程序必须知道如何绘制 SVG。
通常使用内联 SVG 的一种 XML 文档是可扩展样式表语言格式化对象(XSL-FO:Extensible Stylesheet Language Formatting Object)文件。一个 XSL-FO 文件定义了多页文档的内容和布局,可以用于发布或创建 PDF 文件, XSL-FO 数据类型包含一个 <instream-foreign-object>
元素,就像 SVG 中的 <foreignObject>
元素,定义一个矩形区域来保存来自不同 namespace 的内容。在里面,你可以添加你自己的 SVG 标签,只需要确保 <svg>
标签和它的所有子节点都定义在 SVG 的 namespace 下面, 要么为所有 SVG 元素使用 namespace 前缀,要么使用 xmlns 属性更改默认 namespace。
图2-3 给出了 XSL-FO 文件的一小段使用了自定义 namespace 前缀来格式化对象元素的代码。<svg>
和它的子节点默认设置为使用了 SVG namespace, 所以在图形标签上不再需要前缀。
Example 2-3. SVG inside an XSL-FO document
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="">
<!-- other formatting object content -->
<fo:instream-foreign-object width="140px" height="140px">
<svg xmlns=""
width="140px" height="140px">
<!-- SVG code goes here -->
</svg>
</fo:instream-foreign-object>
<!-- rest of document -->
</fo:root>
更多推荐
2.网页中使用SVG
发布评论