SVG 基础入门篇
可缩放矢量图形(Scalable Vector Graphics,SVG),是一种用于描述二维矢量图形、基于 XML 的标记语言。作为一个基于文本的开放网络标准,SVG 能够优雅而简洁地渲染不同大小的图形,并和 CSS、DOM、JavaScript 和 SMIL 等其他网络标准衔接。本质上,SVG 相对于图像,就好比 HTML 相对于文本。
和传统的点阵图像(如 JPEG、PNG)不同,SVG 提供的是矢量图:可以放大而不失真,也便于改内容。
SVG 是由万维网联盟(W3C)自 1999 年开始开发的开放标准。
- SVG 是指可伸缩矢量图形
- SVG 用来定义用于网络的基于矢量的图形
- SVG 使用 XML 格式定义图形
- SVG 图像在放大或缩小(改变尺寸)时,图形质量不会受损失
- SVG 是 W3C 的一个标准
SVG 有哪些优缺点
与其他图像格式相比,使用 SVG 的优势在于:
- SVG 是矢量格式,可呈现任何大小而不降低其质量
- SVG 支持静止或动态图像
- SVG 支持透明度
- SVG 可被非常多的工具读取和修改(比如:代码或文本编辑器)
- SVG 可以从 Adobe Illustrator 或 Sketch 等设计软件中导出
- SVG 因为基于文本,是可搜索的(很适合制作地图)
- SVG 是开放的标准。现代浏览器支持 SVG 格式,并且面向未来
- SVG 文件是纯粹的 XML
- SVG 格式具有高度可压缩性和轻量级
SVG 也有一些缺点:
- 复杂图形会让 SVG 源码变得很长、难维护
- 在过低版本的浏览器上无法呈现
- 电子邮件客户端支持有限
- 复杂路径、节点很多时,运行时计算和栅格化会比同等观感的 PNG 更耗。
- 渲染效果不一致。不同浏览器乃至不同平台的抗锯齿处理差别很大,尤其是关掉抗锯齿时,边数较多的多边形图标会很难看。
浏览器中如何使用 SVG 元素
注意: 若要用脚本访问外部 SVG 的内部 DOM(iframe、object、内联),须同源。img 和 CSS 背景把 SVG 当图片加载,内部脚本不会执行。
要在浏览器中显示,可以通过几种方法来实现:
HTML 元素引入 SVG 文件
使用
iframe元素来嵌入 SVG 图像使用
img元素来嵌入 SVG 图像

<iframe src="snowman.svg" width="200" height="200"></iframe>
<img src="snowman.svg" width="300" />
在 CSS 样式中使用 SVG 来对 HTML 内容应用图像效果
- 将 SVG 图像作为背景图像嵌入
div { background: url(snowman.svg) no-repeat center; background-size: 300px 200px; }现代浏览器支持在 CSS 样式中使用 SVG 来对 HTML 内容应用图像效果。
你可以在同一文件中使用 SVG 样式,也可以通过外部样式表引入。有三个属性可以使用:
mask、clip-path、filter。<svg> <mask id="mask-1"> ... </mask> <clipPath id="clipping-path-1"> ... </clipPath> <filter id="f1"> ... </filter> </svg>.target { mask: url(#mask-1); clip-path: url(#clipping-path-1); filter: url(#f1); } .target2 { /* 使用外部引用 */ clip-path: url(resources.svg#c1); }
将 SVG 直接嵌套在 HTML 中
- 直接使用
svg元素,通过代码将 SVG 图像嵌入到 HTML 代码中。
<section class="box_02"> <svg width="447.64197" height="631.57538"> ... </svg> </section>- 使用
embed、object元素来嵌入 SVG 图像(不推荐)。
<embed src="snowman.svg" width="300" height="220" type="image/svg+xml" /> <object data="snowman.svg" width="300" height="200" type="image/svg+xml"></object>- 直接使用
SVG 文档基本结构
一个独立的 SVG 文件,也就是平时看到的以扩展名 .svg 结尾的文件。一个简单的 SVG 图形例子:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
XML 声明:和 HTML 文档的 DTD 声明是类似的。
<!-- 类似于 HTML 文档的 DTD 声明 <!DOCTYPE html> --> <?xml version="1.0" encoding="UTF-8" standalone="no"?>version="1.0"和encoding="utf-8"是 XML 声明里常见的默认写法。standalone规定此文件在 XML 意义上是否「独立」。standalone="no"表示文档可以引用外部标记声明(如 DTD),并不等于「一定引用了另一张图」。svg根元素包括用来描述 SVG 的 XML 命名空间。<!-- 类似于 HTML 中的命名空间声明 <html xmlns="http://www.w3.org/1999/xhtml"> --> <svg xmlns="http://www.w3.org/2000/svg">
嵌入 HTML5 文档中的 SVG 不应再写一份 XML 声明(格式良好的 XML 只允许文档最顶部有一个 XML 声明)。独立 .svg 文件可以写 XML 声明,但不是必须;通过 img 或 CSS background-image 引用的 SVG 按图片解析,有无 XML 声明都能显示。HTML5 里内联的 <svg> 也可省略 xmlns,独立文件仍应写上。
几个重要的 SVG 概念
1. viewport
视口,表示 SVG 可见区域的大小,或者可以想象成画布大小(与 canvas 的画布概念相似)。SVG 中超出视窗边界的区域会被裁切并且隐藏。
<svg width="500" height="300"></svg>
2. viewBox 属性
viewBox 是「视区盒子」的意思,即创建一个可伸展的盒子,用以承载一组图形。当 viewBox 的大小与 viewport 不一致时,盒子会自动伸缩(与 preserveAspectRatio 属性有关)。
viewBox="min-x min-y width height"
viewBox 大小默认与 viewport 相同。不允许宽度和高度为负值;为 0 则禁用该元素的呈现。

<section class="box_16">
<svg width="400" height="300" viewBox="0,0,40,30" style="border: 1px solid #eee;">
<rect x="10" y="5" width="20" height="15" fill="#0aa" />
<line x1="20" y1="15" x2="20" y2="30" stroke="orange" stroke-width="2" />
</svg>
</section>
如上所示,viewBox 的大小是 40 * 30,viewport 的大小是 400 * 300。实现渲染时,会将 viewBox 放大 10 倍。
有 marker、pattern、svg、symbol、view 等五个 SVG 元素可以有这个属性。
3. preserveAspectRatio 属性
有时候使用 viewBox 时希望图形拉伸占据整个视口;其他情况下为了保持长宽比,必须使用统一的缩放比例。preserveAspectRatio 表示是否强制进行统一缩放。
对于支持该属性的元素,除了 image 之外,preserveAspectRatio 只在提供了 viewBox 时生效;没有 viewBox 则忽略该属性。
preserveAspectRatio="<align> <meetOrSlice>"
align: 表示对齐方式和是否强制统一缩放。当 SVG 的
viewBox与视口宽高比不一致时使用。默认值 xMidYMid,即居中。align的值一定是下列之一:- none:不强制统一缩放,可以拉伸变形。此时
meetOrSlice会被忽略。 - xMinYMin:强制统一缩放。viewBox 与 viewport 在 X 方向左对齐、Y 方向上对齐。
- xMidYMin:强制统一缩放。viewBox 与 viewport 在 X 方向居中、Y 方向上对齐。
- xMaxYMin:强制统一缩放。viewBox 与 viewport 在 X 方向居右、Y 方向上对齐。
- xMinYMid:强制统一缩放。viewBox 与 viewport 在 X 方向左对齐、Y 方向居中。
- xMidYMid(默认值):强制统一缩放。viewBox 与 viewport 在 X 方向、Y 方向都居中。
- xMaxYMid:强制统一缩放。viewBox 与 viewport 在 X 方向右对齐、Y 方向居中。
- xMinYMax:强制统一缩放。viewBox 与 viewport 在 X 方向左对齐、Y 方向下对齐。
- xMidYMax:强制统一缩放。viewBox 与 viewport 在 X 方向居中、Y 方向下对齐。
- xMaxYMax:强制统一缩放。viewBox 与 viewport 在 X 方向右对齐、Y 方向下对齐。
- none:不强制统一缩放,可以拉伸变形。此时
meetOrSlice: 可选。只有
meet和slice两个值,默认 meet。none属于上面的align,不是meetOrSlice。- meet: 默认值。保留宽高比,尽可能放大 viewBox,同时保证整个 viewBox 都在视口内可见(类似 CSS
contain)。 - slice: 保留宽高比,尽可能放大 viewBox,并保证宽、高都覆盖整个视口(类似 CSS
cover),多出的部分被裁掉。
- meet: 默认值。保留宽高比,尽可能放大 viewBox,同时保证整个 viewBox 都在视口内可见(类似 CSS
SVG 中的坐标系统
SVG 的坐标系统分为三种类型:
- 初始坐标系统
- 转换坐标系统
- 嵌套坐标系统
初始坐标系统
初始视窗坐标系是建立在视窗(viewport)上的坐标系。原点 (0, 0) 在视窗的左上角,X 轴正向指向右,Y 轴正向指向下,初始坐标系中的一个单位等于视窗中的一个「像素」(更确切地说是一个用户单位)。
初始用户坐标系是通过 viewBox 建立在 SVG 画布上的坐标系。一开始它和初始视窗坐标系完全一样:原点位于视窗左上角,x 轴正向指向右,y 轴正向指向下。
<svg width="300" height="300"></svg>
转换坐标系统
可以使用 transform 属性来对元素的坐标系统进行变换。transform 属性的作用对象是元素所在的坐标系统,而不是元素本身。
在 SVG 规范中,transform 属性的作用是 在被添加的元素上建立新用户空间坐标系(当前坐标系)(效果与 viewBox 类似)。
它和 CSS 中 transform 的变换函数,都是基于坐标系变换的。区别在于:HTML 元素的坐标系建立在元素自身上;SVG 属性 transform 基于初始坐标系或当前用户空间坐标系。现行浏览器里,给 SVG 元素写 CSS transform 时,行为更接近 CSS 盒子模型,和 SVG 属性 transform 仍有差别。

svg 元素有多个变换时,下一个变换的坐标系是基于上一个变换完成后的坐标系创建的,并且其子元素变换的坐标系,也是基于父元素变换后的坐标系创建的。
嵌套坐标系统
在 svg 元素中可以嵌套 svg 元素。外面的 svg 创建一个 Viewport 和坐标系统,嵌套在里面的 svg 也可以创建一个 Viewport 和坐标系统。
如果不声明子 SVG 的 x 和 y 属性,它们默认是 0。如果不声明 height 和 width 属性,子 svg 会是父 SVG 宽度和高度的 100%。
除了嵌套 svg,也可以使用 use、symbol 等元素来建立新的 viewport 和用户坐标系。
SVG 的基本组成元素
一个简单的 SVG 文档由 svg 根元素和基本的形状元素构成。另外还有一个 g 元素,它用来把若干个基本形状编成一个组。
从这些开始,SVG 可以变得更加复杂。SVG 支持渐变、旋转、动画、滤镜效果、与 JavaScript 交互等等功能,但是所有这些额外的语言特性,都需要在一个定义好的图形区域内实现。
1. line 元素(直线)
line 元素是一个 SVG 基本形状,用来创建一条连接两个点的线。
x1:起点 x 坐标y1:起点 y 坐标x2:终点 x 坐标y2:终点 y 坐标

<section class="box_03">
<svg width="300px" height="300px" style="border: 1px solid #ccc;">
<line x1="0" y1="200" x2="250" y2="0" stroke="#0aa" stroke-width="5" />
</svg>
</section>
2. rect 元素(矩形)
rect 元素是 SVG 的一个基本形状,用来创建矩形,基于一个角位置以及它的宽和高。它还可以用来创建圆角矩形。
x:左上角 x 坐标y:左上角 y 坐标width:宽度height:高度rx:x 方向的圆角半径ry:y 方向的圆角半径

<section class="box_04">
<svg width="300px" height="150px" style="border: 1px solid #ccc;">
<rect x="20" y="20" width="250px" height="125px" rx="5" ry="5" fill="teal" />
</svg>
</section>
3. circle 元素(圆)
circle 元素是一个 SVG 的基本形状,用来创建圆,基于一个圆心和一个半径。
cx:圆心 x 坐标cy:圆心 y 坐标r:半径

<section class="box_05">
<svg width="300px" height="300px" style="border: 1px solid #ccc;">
<circle cx="100" cy="100" r="50" fill="#0aa"></circle>
</svg>
</section>
4. ellipse 元素(椭圆)
ellipse 元素是一个 SVG 基本形状,用来创建一个椭圆,基于一个中心坐标以及它们的 x 半径和 y 半径。
cx:圆心 x 坐标cy:圆心 y 坐标rx:x 方向半径ry:y 方向半径

<section class="box_06">
<svg width="300px" height="300px" style="border: 1px solid #ccc;">
<ellipse cx="150" cy="150" rx="100" ry="75" fill="#0aa" />
</svg>
</section>
5. polygon 元素(闭合多边形)
polygon 元素是由连接一组点集的直线构成。polygon 的路径在最后一个点处自动回到第一个点。需要注意的是,矩形也是一种多边形。
points:定义用来画polygon或polyline的点列。每个点用用户坐标系统中的一个 X 坐标和 Y 坐标定义,点与点之间用空格或逗号分开。

<section class="box_07">
<svg width="300px" height="300px" style="border: 1px solid #ccc;">
<polygon points="0,50 50,0 150,0 200,50 150,100 50,100" fill="#0aa"></polygon>
</svg>
</section>
6. polyline 元素(折线)
polyline 元素是 SVG 的一个基本形状,用来创建一系列直线连接多个点。典型的一个 polyline 是用来创建一个开放的形状,最后一点不与第一点相连。

<section class="box_08">
<svg width="300px" height="180px" style="border: 1px solid #ccc;">
<polyline points="10 10,50 50,75 175,175 150,175 50,225 75,225 150,300 150" fill="none" stroke="#0aa" />
</svg>
<svg width="300px" height="180px" style="border: 1px solid #ccc;">
<polyline points="10 10,50 50,75 175,175 150,175 50,225 75,225 150,300 150" fill="#0aa" stroke="none" />
</svg>
</section>
7. image 元素(图片)
允许在一个 SVG 对象内部呈现光栅图像,也可以引用其他 SVG 文件。规范要求至少支持 JPEG、PNG;GIF 不是必须格式,浏览器支持不一致。
x:图像水平方向上到原点的距离y:图像竖直方向上到原点的距离width:图像宽度。SVG 1.1 中是必须的,缺省为 0 则不绘制;SVG 2 可用图像固有尺寸。height:图像高度。同上。href、xlink:href:图像的 URL。现行用href,xlink:href仍可用于兼容。preserveAspectRatio:控制图像比例
<section class="box_26">
<svg width="500" height="300">
<image xlink:href="https://my-files-1259410276.cos.ap-chengdu.myqcloud.com/md_images/飞舞.png" x="0" y="0" height="300" width="300" />
</svg>
</section>
- 如果没有设置
x或y,它们自动被设置为 0 - SVG 1.1 下如果没有设置
height或width,它们自动被设置为 0;为 0 则不呈现该图像
8. text 元素(文本)
text 元素定义了一个由文字组成的图形。
注意:我们可以将渐变、图案、剪切路径、遮罩或者滤镜应用到 text 上。
x、y:在用户坐标系统中标识了一个 x 轴、y 轴坐标。dx、dy:一个元素或其内容在 x 轴、y 轴方向上的偏移,偏移量取决于设置该属性的元素。text-anchor:用来描述该文本与所给点的对齐方式(开头、中间、末尾对齐)。取值:start、middle、end。rotate:旋转各个字形的角度(可以是一个数,也可以是与字形对应的一组数)。textLength:指定文本将绘制到的空间的宽度。lengthAdjust:控制文本如何拉伸到textLength定义的长度。取值:spacing、spacingAndGlyphs。
9. textPath 元素(文本路径)
除了笔直地绘制一行文字以外,SVG 也可以根据 path 元素的形状来放置文字。只要在 textPath 元素内部放置文本,并通过其 href(或兼容用的 xlink:href)引用 path 元素,就可以让文字块呈现在路径上。
startOffset:将路径转换到 textPath 的坐标系后,沿路径的初始文本位置相对于路径起点的偏移量。method:沿路径呈现文本的方法。取值:align、stretch。spacing:如何确定沿路径呈现的字符之间的间距。href、xlink:href:引用的路径。现行用href。

<section class="box_27">
<svg width="500" height="300" style="border: 1px solid #eee;">
<defs>
<path id="MyPath" d="M 50 200 C 200 400 900 -200 900 100" />
</defs>
<use xlink:href="#MyPath" fill="none" stroke="orange" stroke-width="3" />
<text font-family="Verdana" font-size="30" fill="#0aa">
<textPath startOffset="-50" xlink:href="#MyPath" spacing="exact"> 君子之交淡如水,茶人之交醇如茶。 </textPath>
</text>
<text x="120" y="30" dx="0" dy="30" font-weight="bold" font-size="30" fill="#0aa" text-anchor="middle">
君子之交淡如水,茶人之交醇如茶。 </text>
<text x="20" y="100" font-weight="bold" font-size="30" fill="#0aa" textLength="300"> 君子之交淡如水,茶人之交醇如茶。 </text>
<text x="20" y="140" font-weight="bold" font-size="30" fill="#0aa" textLength="300"
lengthAdjust="spacingAndGlyphs" rotate="30"> 君子之交淡如水,茶人之交醇如茶。 </text>
</svg>
</section>
10. pattern 元素(图案)
使用预定义的图形对一个对象进行填充或描边,就要用到 pattern 元素。pattern 元素让预定义图形能够以固定间隔在 x 轴和 y 轴上重复(或平铺)从而覆盖要涂色的区域。先使用 pattern 元素定义图案,然后在给定的图形元素上用属性 fill 或属性 stroke 引用用来填充或描边的图案。
patternUnits:指示将哪个坐标系用于pattern元素的几何属性。patternContentUnits:指示要用于pattern元素内容的坐标系。patternTransform:定义应用于图案的变换列表。x、y:在用户坐标系统中标识了一个 x 轴、y 轴坐标。width、height:在用户坐标系统中标识了一个水平长度、垂直长度。href、xlink:href:引用另一个图案。preserveAspectRatio:表示是否强制进行统一缩放。

<section class="box_28">
<svg width="400" height="400">
<defs>
<linearGradient id="Gradient7">
<stop offset="5%" stop-color="white" />
<stop offset="95%" stop-color="#0aa" />
</linearGradient>
<linearGradient id="Gradient8" x1="0" x2="0" y1="0" y2="1">
<stop offset="5%" stop-color="white" />
<stop offset="95%" stop-color="orange" />
</linearGradient>
<pattern id="Pattern" x="0" y="0" width=".25" height=".25">
<rect x="0" y="0" width="50" height="50" fill="#0aa" />
<line x1="25" y1="25" x2="50" y2="50" stroke-width="5" stroke="url(#Gradient8)" />
<circle cx="25" cy="25" r="20" fill="url(#Gradient7)" fill-opacity="0.8" />
</pattern>
</defs>
<rect fill="url(#Pattern)" x="0" y="0" width="200" height="200" />
</svg>
</section>
SVG 中的路径
path 是 SVG 中最常见的形状。你可以用 path 元素绘制矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形,以及贝塞尔曲线、二次曲线等。
路径可以被填充、描边或者用于剪裁其他元素。
d:一个字符串,包含了一系列路径描述。可以使用不同的指令,移动到一个新的点,然后绘制不同的直线和曲线。
注意:指令字母大写表示坐标位置是绝对坐标,指令字母小写表示坐标位置是相对坐标。x、y 坐标之间可以用空格或逗号隔开。
以下用 path 元素,绘制上个 polyline 示例:
<section class="box_09">
<svg width="300px" height="180px" style="border: 1px solid #ccc;">
<path d="
M10 10
L50 50
L75 175
L175 150
L175 50
L225 75
L225 150
L300 150
"
fill="none"
stroke="#0aa"
stroke-width="2px"
/>
</svg>
</section>
1. 直线指令
这里有五种不同的直线指令,你可以使用它们来创建路径。
moveto(M或m):移动到新的位置lineto(L或l):从当前坐标画一条直线到一个新坐标horizontal lineto(H或h):画一条水平线到新坐标。只带一个参数,标明在 x 轴移动到的位置vertical lineto(V或v):画一条垂直线到新坐标。只带一个参数,标明在 y 轴移动到的位置closepath(Z或z):关闭当前路径。它是最简单的命令,而且不带有任何参数。Z或z,两种写法作用都一样
注意: 指令的参数用空格或逗号隔开,多个指令之间不需要隔开。
d="M10 10L50 50L75 175L175 150L175 50L225 75L225 150L300 150"
d="M10,10 L50,50 L75,175 L175,150 L175,50 L225,75 L225,150 L300,150"
注意: 实际应用中使用指令字母即可。指令字母大写表示绝对位置,指令字母小写表示相对位置。

<section class="box_10">
<svg width="300px" height="300px" style="border: 1px solid #ccc;">
<g fill="none">
<path d="M 0 300 l 150 -300" stroke="red" />
<path d="M 150 0 l 150 300" stroke="red" />
<path d="M 50 200 h 200" stroke="#0aa" />
<path d="M 0 300 q 150 -300 300 0 z" stroke="orange" stroke-width="3px" />
</g>
</svg>
</section>
2. 曲线指令
绘制平滑曲线的命令有三个,其中两个用来绘制贝塞尔曲线,另外一个用来绘制弧形或者说是圆的一部分:
Curveto:三次贝塞尔曲线指令(
C、c、S、s),需要一个初始点的控制点和一个结束点的控制点,还有一个结束点。C (or c) x1,y1 x2,y2 x,y S (or s) x2,y2 x,yx1、y1是曲线起点的控制点坐标x2、y2是曲线终点的控制点坐标x、y是曲线的终点坐标(曲线的起点是上一条指令的终点)
Curveto:二次贝塞尔曲线指令(
Q、q、T、t),只需要一个控制点,同时作为起点控制点和终点控制点。Q (or q) x1,y1 x,y T (or t) x,yx1、y1是曲线起点和终点共用的控制点坐标(仅Q、q)x、y是曲线的终点坐标T、t只写终点,控制点由前一段的控制点关于前终点反射得到
<section class="box_11"> <svg width="300px" height="150px" style="border: 1px solid #ccc;"> <path d="M0 30 C 100 30 150 150 300 30" fill="none" stroke="#0aa" stroke-width="3px" /> <path d="M0 100 Q 150 180 300 100" fill="none" stroke="orange" /> </svg> </section>
为了连缀平滑的贝塞尔曲线,还可以使用 T 和 S 命令。它们的语法比别的 Curveto 命令简单。因为它假定第一个控制点是前一个控制点关于前一个点的反射(即,关于前一个点对称),或者说如果没有前一个控制点的话它实际上就是前一个点。
Arcto:椭圆弧线(
A、a),用于绘制一段椭圆片段。若rx和ry的值相同,则绘制出圆。A (or a) rx ry xAxisRotate large-arc-flag sweep-flag x yrx、ry:弧线在 x 轴、y 轴方向的半径xAxisRotate:与 x 轴夹角的度数large-arc-flag:0 或 1,用来确定是要画小弧(0)还是画大弧(1)sweep-flag:0 或 1,用来确定弧是顺时针方向(1)还是逆时针方向(0)x、y:弧线的终点

<section class="box_12"> <svg width="600" height="300" style="border: 1px solid #eee;"> <path d="M250,100 A120,80 0 0 0 250,200" fill="none" stroke="red" stroke-width="5" /> <path d="M250,100 A120,80 0 1 1 250,200" fill="none" stroke="#0aa" stroke-width="3" /> <path d="M250,100 A120,80 0 1 0 250,200" fill="none" stroke="orange" stroke-width="1" /> <path d="M250,100 A120,80 0 0 1 250,200" fill="none" stroke="#a0a" stroke-width="3" /> </svg> </section>
SVG 中的其他元素
SVG 中的标记(Marker)
marker 元素定义了在特定的 path、line、polyline、polygon 元素上绘制的箭头或者多边标记图形。
markerUnits:标记的坐标系。取值userSpaceOnUse(用户坐标)或strokeWidth(相对描边宽度,默认)。refX、refY:定义元素参考点的 x、y 坐标markerWidth、markerHeight:定义 marker 元素的宽度、高度。orient:指示将标记放置在形状上时如何旋转。
marker-start、marker-mid、marker-end这三个 CSS 属性会将标记分别放置在路径的开始、中间和结束位置。可以设置
markerUnits="strokeWidth"使得标记进行缩放来适应路径描边的大小

<section class="box_13">
<svg width="300" height="150" style="border: 1px solid #eee;">
<defs>
<marker id="markerCircle" markerWidth="20" markerHeight="20" refX="5" refY="5">
<circle cx="5" cy="5" r="3" style="stroke: none; fill: orange;" />
</marker>
<marker id="markerCircle2" markerWidth="8" markerHeight="8" refX="5" refY="5">
<circle cx="5" cy="5" r="5" style="stroke: none; fill: red;" />
</marker>
<marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto"
markerUnits="strokeWidth">
<path d="M2,2 L2,11 L10,6 L2,2" style="fill: orange;" />
</marker>
</defs>
<path d="M75 25 h150 v100 l -100 -50"
style="stroke: #0aa; fill: none; marker-start: url(#markerCircle); marker-mid: url(#markerCircle2); marker-end: url(#markerArrow); " />
</svg>
</section>
SVG 中的 clipPath
SVG 剪裁路径是指根据指定的路径或形状来剪裁 SVG 图形。应用了剪裁路径的图形,在剪裁路径内部的图形可以被显示出来,在剪裁路径之外的图形会被隐藏。
你可以使用任何图形来作为剪裁路径或者被剪裁的对象。可以是文字、圆形、椭圆、多边形或自定义路径。

<section class="box_14">
<svg viewBox="0 0 100 100" style="width: 300px; border: 1px solid #eee;">
<clipPath id="myClip">
<circle cx="40" cy="35" r="35" />
</clipPath>
<path id="heart" d="M10 30 A20 20 0 0 1 50 30 A20 20 0 0 1 90 30 Q90 60 50 90 Q10 60 10 30 Z"
style="clip-path: url(#myClip);" fill="#0aa" />
</svg>
</section>
SVG defs 元素、symbol 元素和 use 元素
defs元素:用于预定义一个元素使其能够在 SVG 图像中重复使用。在defs元素中定义的图形元素不会直接呈现。symbol元素:用于定义可重复使用的符号。symbol能够创建自己的视窗,所以能够应用viewBox和preserveAspectRatio属性。use元素:可以在 SVG 图像中多次重用一个预定义的 SVG 图形,包括<g>元素和<symbol>元素。use元素可以引入在defs元素中定义的图形。出于安全原因,浏览器会对
use的跨源引用应用同源策略,跨源 URI 会被拒绝。

<section class="box_15">
<svg viewBox="0 0 300 300" style="width: 300px; border: 1px solid #eee;">
<defs>
<g id="shape" stroke-width="1">
<line x1="150" y1="150" x2="150" y2="300" />
<circle cx="150" cy="150" r="120" />
</g>
</defs>
<symbol id="shape2">
<circle cx="75" cy="75" r="75" style="fill: orange;" />
</symbol>
<use xlink:href="#shape" style="stroke: #0aa; fill: none;" />
<use xlink:href="#shape2" x="150" y="75" />
</svg>
</section>
SVG 元素的样式属性
SVG 元素不同于普通的 HTML 元素,具有特殊的一些样式属性。这些属性的声明可以通过 SVG 元素属性直接声明,也可以通过 CSS 样式表声明。
语法和在 HTML 里使用 CSS 一样,只不过你要把 background-color、border 改成 fill 和 stroke。
注意:不是所有属性都能用 CSS 设置。上色和描边一般可以,比如 fill、stroke、stroke-dasharray 等,渐变和图案本身仍要写在 SVG 里再以 url() 引用。SVG 1.1 里 width、height 以及路径的 d 等几何属性不能用 CSS;SVG 2 起其中不少已成为演示属性,现行浏览器可以用 CSS 改 width、height,部分引擎也支持 CSS 的 d。
SVG 规范将属性区分成 properties 和其他 attributes,前者是可以用 CSS 设置的,后者不能。
以下是一些 CSS 2 里没有、SVG 里常用的样式属性:
- fill:元素的填充颜色
- fill-opacity:元素的填充颜色透明度
- stroke:元素的笔画颜色
- stroke-width:元素的笔画宽度
- stroke-linecap:定义元素顶点样式
- stroke-dasharray:虚线样式虚线长度
- stroke-dashoffset:虚线样式的偏移长度
- stroke-linejoin:定义元素之间的连接点的形状
- stroke-opacity:元素的笔画颜色透明度
我们可以通过以下方法引用样式属性:
使用属性来添加 CSS 样式。
<circle stroke="none" fill="#0aa" />使用 STYLE 属性。
<circle style="stroke: none; fill: #0aa;" />使用内联样式表。
这种使用内联样式表的工作方式和在 HTML 元素上使用内联样式表是完全相同的。样式可以定义在 svg 元素外,也可以定义在 svg 元素内。
<style> .class_name2 { stroke: #0aa; fill: #a0a; } </style> <svg> <style type="text/css" > <![CDATA[ circle { stroke: #0aa; fill: orange; } .class_name1 { stroke: #0aa; fill: red; } ]]> </style> <circle cx="40" cy="40" r="25"/> <circle class="class_name1" cx="120" cy="40" r="25"/> <circle class="class_name2" cx="200" cy="40" r="25"/> </svg>使用外部样式表来添加 CSS 样式。
<?xml-stylesheet type="text/css" href="svg-stylesheet.css" ?>
SVG 中的渐变效果
SVG 可以创建并在填充和描边上应用渐变色。
有两种类型的渐变:线性渐变和径向渐变。你必须给渐变内容指定一个 id 属性,否则文档内的其他元素就不能引用它。为了让渐变能被重复使用,渐变内容需要定义在 defs 标签内部,而不是定义在形状上面。
线性渐变
线性渐变沿着直线改变颜色,要插入一个线性渐变,你需要在 SVG 文件的 defs 元素内部,创建一个 linearGradient 元素。
gradientUnits:定义用于渐变几何属性的坐标系。取值:userSpaceOnUse、objectBoundingBox,默认值为objectBoundingBox。objectBoundingBox相对被填充图形的包围盒(0~1 或百分比),不是相对整个 SVG 视口。userSpaceOnUse使用当前用户坐标系的绝对单位。gradientTransform:定义从渐变坐标系到目标坐标系的转换。x1、y1、x2、y2:起点和结束点的坐标。用于定义渐变的方向和范围。spreadMethod:确定如何填充超出定义的渐变边的形状。pad(默认值):该值表示渐变的最终颜色填充了超出渐变边缘的形状。reflect:此值表示渐变超过其边缘反向重复。repeat:此值指定渐变以原始顺序重复其边缘。
xlink:href:引入其他linearGradient元素

<section class="box_24">
<svg width="500" height="300">
<defs>
<linearGradient id="Gradient1">
<stop stop-color="orange" offset="0%" />
<stop stop-color="white" stop-opacity="0.5" offset="50%" />
<stop stop-color="#0aa" offset="100%" />
</linearGradient>
<linearGradient id="Gradient2" x1="0" y1="0" x2="1" y2="1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Gradient1" />
<linearGradient id="Gradient3" x1="33%" x2="67%" y1="33%" y2="67%" spreadMethod="reflect" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Gradient1" />
</defs>
<rect x="0" y="50" rx="30" ry="30" width="150" height="150" fill="url(#Gradient1)" />
<rect x="175" y="50" rx="30" ry="30" width="150" height="150" fill="url(#Gradient2)" />
<rect x="350" y="50" rx="30" ry="30" width="150" height="150" fill="url(#Gradient3)" />
</svg>
</section>
可以在 stop 元素中定义 stop-color、stop-opacity、fill 属性,也可以定义在 CSS 中:
<style type="text/css"><![CDATA[
#rect { fill: url(#Gradient1); }
.stop { stop-color: black; stop-opacity: 0; }
]]></style>
linearGradient 元素还需要一些其他的属性值,它们指定了渐变的大小和出现范围。渐变的方向可以通过两个点来控制,它们分别是属性 x1、x2、y1 和 y2,这些属性定义了渐变路线走向。
可以在渐变上使用
href(或兼容的xlink:href),使一个渐变的属性和颜色中值(stop)可以被另一个渐变引用。
<linearGradient id="Gradient2" x1="0" y1="0" x2="1" y2="1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Gradient1"/>
径向渐变
径向渐变与线性渐变相似,只是它是从一个点开始发散绘制渐变。创建径向渐变需要在文档的 defs 中添加一个 radialGradient 元素。
cx、cy:中心点的 x、y 轴坐标。r:定义圆的半径fx、fy:定义径向渐变的焦点的 x、y 轴坐标。如果该属性没有被定义,就假定它与中心点是同一位置。fr:定义径向渐变的焦点的半径。若该属性没有被定义,默认值为 0%。

<section class="box_25">
<svg width="500" height="300">
<defs>
<radialGradient id="Gradient4">
<stop stop-color="orange" offset="0%" />
<stop stop-color="white" stop-opacity="0.5" offset="50%" />
<stop stop-color="#0aa" offset="100%" />
</radialGradient>
<radialGradient id="Gradient5" cx="0.5" cy="0" r="1" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Gradient4" />
<radialGradient id="Gradient6" fx="0.5" fy="0.35" fr="0.25" spreadMethod="reflect" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#Gradient4" />
</defs>
<rect x="0" y="50" rx="30" ry="30" width="150" height="150" fill="url(#Gradient4)" />
<rect x="175" y="50" rx="30" ry="30" width="150" height="150" fill="url(#Gradient5)" />
<rect x="350" y="50" rx="30" ry="30" width="150" height="150" fill="url(#Gradient6)" />
</svg>
</section>
SVG 中的 SMIL 动画
SMIL 是 Synchronized Multimedia Integration Language(同步多媒体集成语言)的首字母缩写。SMIL 开发组和 SVG 开发组合作开发了 SMIL 动画规范,在规范中制定了一个基本的 XML 动画特征集合。SVG 吸收了其中的动画能力,并提供了 SVG 自己的实现。现行主流浏览器仍支持这些动画元素;也可用 CSS 或 Web Animations API 做同类效果。
SMIL 允许你做下面这些事情:
- 动画元素的数值属性(X、Y、…)
- 动画属性变换(平移或旋转)
- 动画颜色属性
- 沿着运动路径运动
不论使用下面 4 个动画元素中的哪一个,你都需要为它指定一个动画目标。可以使用 href(或兼容的 xlink:href)指向将要执行动画的元素,该元素必须在当前 SVG 文档中。动画元素也可以嵌套在目标 SVG 元素里。如果没有指定引用,那么动画的目标就是当前动画元素的直接父元素。
<rect id="cool_shape" ... />
<animate xlink:href="#cool_shape" ... />
SVG 四个动画元素
set 元素
此元素没有动画效果。可以实现基本的延迟功能。即,可以在特定时间之后修改某个属性值(也可以是 CSS 属性值)
<section class="box_18">
<svg width="320" height="320">
<g>
<text font-family="microsoft yahei" font-size="80" y="160" x="160" fill="#0aa">
SVG
<set attributeName="x" attributeType="XML" to="60" begin="2s" />
</text>
</g>
</svg>
</section>
animate 元素
基础动画元素。实现单属性的动画过渡效果。类似于 CSS 中的 transition 属性。
<section class="box_19">
<svg width="320" height="320">
<g>
<text font-family="microsoft yahei" font-size="80" y="160" x="160" fill="#0aa">
SVG
<animate attributeName="x" from="160" to="60" begin="0s" dur="3s" repeatCount="indefinite" />
</text>
</g>
</svg>
</section>
animateTransform 元素
实现 transform 变换动画效果的。
<section class="box_20">
<svg width="640" height="640">
<g>
<text font-family="microsoft yahei" font-size="80" y="160" x="160" fill="#0aa">
SVG
<animateTransform attributeName="transform" begin="0s" dur="3s" type="scale" from="1" to="1.5" repeatCount="indefinite" />
</text>
</g>
</svg>
</section>
animateMotion 元素
可以让 SVG 图形沿着特定的 path 路径运动。
<section class="box_21">
<svg width="360" height="200">
<text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#0aa">SVG
<animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" rotate="auto"
repeatCount="indefinite" />
</text>
<path d="M10,80 q100,120 120,20 q80,-80 160,0" stroke="#0aa" stroke-width="2" fill="none" />
</svg>
</section>
与使用 CSS 动画的区别
SVG 元素可以像 HTML 元素一样,使用 CSS keyframes 和 animation 属性或者 CSS transitions 来制作各种动画效果。大多数情况下,一个复杂的动画效果需要组合多种变换效果:旋转、倾斜、缩放以及它们的转换和过渡效果。
多数情况下,SVG 元素和 HTML 元素在使用 transform 和 transform-origin 上是相同的。但它们之间也有不同之处:
- SVG 元素不能使用 box model 来管理,因此,它没有
margin、padding、border或 content boxes。 - 默认情况下,一个 HTML 元素的 transform 原点位于该元素的 (50%, 50%) 的地方,这里是元素的中心点。与之不同,SVG 属性
transform的原点位于当前用户坐标系统的原点上,这个点是画布的左上角位置。CSStransform作用在 SVG 元素上时,现行浏览器更接近 CSS 盒子。
SVG 动画的参数详解
attributeName 属性
动画属性的名称
- 可以是元素直接暴露的属性,例如
text元素上的x、y或者font-size; - 可以是 CSS 属性。例如,透明度
opacity。
attributeType 属性
动画属性所属的命名空间。取值:CSS、XML、auto。
x、y 以及 transform 属于 XML,opacity 属于 CSS。auto 为默认值,表示自动判别。SVG 2 已不再强调此属性,现行可省略。
from、to、by、values
类似于 CSS 中的关键帧定义。
from:动画的起始值,缺省为默认值to:指定动画的结束值by:动画的相对变化值values:用分号分隔的一个或多个值,可以看成是动画的多个关键值点
<svg width="320" height="320">
<g>
<text font-family="microsoft yahei" font-size="80" y="160" x="160" fill="#0aa">
SVG
<animate attributeName="x" from="160" to="60" begin="0s" dur="3s" repeatCount="indefinite" />
</text>
</g>
</svg>
begin、end
可选值包括:
time-value:表示具体的时间值。常见单位有h、min、s、ms,默认单位为s。时间值还支持hh:mm:ss这种写法,因此90s也可以写成01:30。offset-value:表示偏移值,数值前面有+或-。相对于文档的begin而言。syncbase-value:基于同步确定的值。语法为:[元素的 id].begin或.end,再加减时间值。可以用来把两个独立元素的动画级联起来。event-value:与事件相关联的值。语法是:[元素的 id].[事件类型] +/- 时间值。repeat-value:指某动画重复多少次结束之后开始执行动画。语法为:[元素的 id].repeat(整数) +/- 时间值。accessKey-value:定义快捷键。即按下某个按键动画开始。语法为:accessKey(character)。character表示快捷键所在的字符。wallclock-sync-value:指真实世界的时钟时间。时间语法基于 ISO 8601。indefinite:表示无限等待。需要beginElement()方法触发,或者指向该动画元素的超链接(SVG 中的a元素)。
dur 属性
该属性标识了动画的简单持续时间。常规时间值:clock-value | indefinite。
指定简单持续时间的时长。值必须大于0。可以用小时(h)、分钟(m)、秒(s)、毫秒(ms)表达这个值。可以组合这些时间表达式以提供一个复合的持续时间,比如这样:hh:mm:ss.iii 或者这样:mm:ss.iii。
如果一个动画元素不带有 dur 属性,简单持续时间就是无限期的。
calcMode、keyTimes、keySplines
calcMode 属性支持 4 个值:discrete、linear、paced、spline。
discrete:from 值直接跳到 to 值。类似于step(1, end)。linear:animateMotion以外元素的calcMode默认值。动画从头到尾的速率都是一致的。paced:通过插值让动画的变化步调平稳均匀。仅支持线性数值区域内的属性,这样点之间「距离」的概念才能被计算(如 position、width、height 等)。如果指定了paced,任何keyTimes或keySplines值将会失效。spline:插值定义贝塞尔曲线。spline 点的定义在keyTimes属性中,每个时间间隔控制点由keySplines定义。
keyTimes: 是关键时间点的意思。一个以分号分隔的时间值列表,用于控制动画的执行步骤。列表中的每个值与 values 中的值一一对应,定义了 values 中的值在动画中何时执行。keyTimes 列表中的每一个值都是指定在 [0, 1] 之间的浮点数,表示动画的完成时间。
前面提到过 values 也是多值,这里有一些约定的规则:首先,keyTimes 值的数目要和 values 一致,如果是 from、to、by 动画,keyTimes 就必须有两个值。然后对于 linear 和 spline 动画,第一个数字要是 0,最后一个是 1。
最后,每个连续的时间值必须比它前面的值大或者相等。
repeatCount、repeatDur
repeatCount 表示动画执行次数,可以是合法数值或者 indefinite(无限循环)。
repeatDur 定义重复动画的总时间。可以是普通时间值或者 indefinite(无限循环)。
fill
这里的 fill 是 SMIL 属性,不是上色的 fill。表示动画结束后如何处理。支持参数:freeze、remove。其中 remove 是默认值,表示动画结束直接回到开始的地方。freeze 表示动画结束后保持结束时的状态。
accumulate、additive
accumulate 是累积的意思。支持参数:none、sum。默认值是 none。如果值是 sum 表示动画结束时候的位置作为下次动画的起始位置。
additive 控制动画是否附加。支持参数:replace、sum。默认值是 replace。如果值是 sum 表示动画的基值会附加到其他低优先级的动画上。
restart
restart 控制重新开启动画的规则。支持的参数有:always、whenNotActive、never。
always是默认值,表示随时可以重新开始。whenNotActive表示动画正在进行的时候,不能重启动画。never表示动画开始后不能再由外部条件重启。
SVG 与 JavaScript
当 SVG 嵌入到 HTML 页面的时候,你可以使用 JavaScript 来操作 SVG 元素,就像操作其他 HTML 元素一样。
- 通过 ID 或 class 获取 SVG 元素
- 可以读取/修改 SVG 元素的属性值
- 可以读取/修改 SVG 元素的 CSS 属性值
可以给 SVG 元素及其子元素添加事件监听
动画的暂停与播放
// svg 指当前 svg DOM 元素(SVGSVGElement) svg.pauseAnimations(); // 暂停 svg.unpauseAnimations(); // 继续