SVG
简介
TIP
SVG 是 Scalable Vector Graphics 的缩写,意为可缩放矢量图形。于 2003 年 1 月 14 日 SVG 1.1 被 Sun 公司(已被 Oracle 公司收购)、Adobe、苹果公司、IBM 以及柯达共同确立成为 W3C 推荐标准。
基本概念
SVG 是一种 XML 语言,类似 XHTML,可以用来绘制矢量图形。
SVG 是什么
- SVG 是 Scalable Vector Graphics 的缩写 意为可缩放矢量图形
- SVG 是一个基于文本的开放网络标准,用来定义用于网络的矢量图形
- SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失,因此能够优雅而简洁地渲染不同大小的图形,并和 CSS,DOM,JavaScript 和 SMIL 等其他网络标准无缝衔接
- SVG 使用 XML 格式定义图形
- SVG 是万维网联盟的标准与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体
优点
SVG 的优点
- SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
- SVG 图像中的文本是可选的,同时也是可搜索的,且可以与 JavaScript 技术一起运行
- SVG 可在图像质量不下降的情况下被放大和缩小
- SVG 可被非常多的工具读取和修改(比如文本编辑器)
- SVG 图像不依赖分辨率,可在任何的分辨率下被高质量地打印
- SVG 文件是纯粹的 XML
- SVG 是开放的标准
缺点
SVG 的缺点
- SVG 复杂度越高渲染速度就会越慢(任何过度使用 DOM 的应用都不快)
- SVG 不适合游戏应用,只能结合 Canvas 来实现
- SVG 不能动态的修改动画内容
浏览器兼容性
基本语法
简单示例
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="50" />
</svg>
如上面的语法所示,SVG 的绘制其实就是一个 SVG 标签,然后在标签内绘制要绘制的内容,比如上面的语法是在 SVG 标签内绘制了一个圆形(cx、cy 为圆的坐标,r 为圆的半径)
SVG 的属性
width height
width、height 用来设置 SVG 的宽高。
viewBox
viewBox 属性定义了 SVG 中可以显示的区域。
语法:viewBox="x y w h" , x、y 为起始点,w、h 为显示区域的宽高。
示例:
<svg
version="1.1"
baseProfile="full"
width="300"
height="300"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="100" cy="100" r="100" />
</svg>
上例中在一个尺寸为 300 * 300 的 SVG 中绘制一个坐标为(100, 100)半径为 100 的圆,同时加上 viewBox 属性为"0 0 100 100",其结果如下: 如图 SVG 里面的圆只显示了一部份,原因是 viewBox 定义了一个:从(0, 0)点开始,宽高为 100 100 的显示区域。而这个 100 100 的显示区域会放到 300 * 300(svg 宽高)的 SVG 中去显示,整体就放大了 3 倍。
version
version 属性用于指明 SVG 的版本,也就是指明 SVG 文档应该遵循的规范。version 属性纯粹就是一个说明,对渲染或处理没有任何影响。且目前只有 1.0 和 1.1 这两个版本。
xmlns 和 xmlns:xlink
SVG 使用 XML 格式定义图形,SVG 文件是纯粹的 XML 文件。
在 XML 中,标签和属性属于命名空间,这是为了防止来自不同技术的标签和属性发生冲突。例如在 SVG 中存在 a 标签,在 HTML 中也存在 a 标签,那么怎么区分这个 a 标签属于哪一种技术,这就需要使用命名空间了。加入命名空间以后就能知道哪一个是 svg:a,哪一个又是 html:a,这样就可以区分出不同的标签和属性。
xmlns 用于声明命名空间(namespace),在此声明之下的所有子标签都属于这个空间内。这里看起来是一个 url,但实际上仅仅是一个字符串,这样使用只是惯例。因此很多时候都会被称为”namespace url” 而不是”namespace name”。
当在 SVG 中加入 xmlns 时,因为它定义了默认命名空间,因此不需要前缀,直接在 SVG 标签中写一个 a 标签,a 标签和 UA 就知道它是 SVG 的 a 标签而不是 HTML 的 a 标签.
xmlns:xlink 表示前缀为 xlink 的标签和属性,应该由理解该规范的 UA 使用 xlink 规范 来解释。
TIP
UA 是 User Agent 的简称。User Agent 是 Http 协议中的一部分,属于头域的组成部分。通俗地讲 UA 是一种向访问网站提供所使用的浏览器类型、操作系统、浏览器内核等信息的标识。通过这个标识,用户所访问的网站可以显示不同的排版,从而为用户提供更好的体验或者进行信息统计。
示例:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
// ......
</svg>
基本图形
基本图形其实就是插入到 SVG 标签中的元素,如上面示例中的圆形(circle)。
圆形(circle)
circle是一个 SVG 的基本形状,用来创建圆,基于一个圆心和一个半径。
语法:<circle cx="100" cy="100" r="100"/>
属性:cx、cy 为圆的坐标,r 为圆的半径
示例:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="100" />
</svg>
矩形(rect)
rect元素是 SVG 的一个基本形状,用来创建矩形,基于一个角位置以及它的宽和高。它还可以用来创建圆角矩形。
语法:<rect x="0" y="0" rx="5" ry="5" width="300" height="200"/>
属性:x、y 为矩形的起始点坐标,rx、ry 为圆角 x、y 轴方向的半径, width、height 为矩形的宽高
示例:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" rx="5" ry="5" width="300" height="200" />
</svg>
椭圆(ellipse)
ellipse元素是一个 SVG 基本形状,用来创建一个椭圆,基于一个中心坐标以及它们的 x 半径和 y 半径。
语法:<ellipse cx="100" cy="100" rx="100" ry="50"/>
属性:cx、cy 为椭圆的坐标,rx 为椭圆的 x 轴半径、ry 为椭圆的 y 轴半径
示例:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="100" cy="100" rx="100" ry="50" />
</svg>
线条(line)
line元素是一个 SVG 基本形状,用来创建一条连接两个点的线。
语法:<line x1="10" x2="50" y1="110" y2="150" />
属性:x1、y1 为起点的坐标,x2、y2 为终点的坐标
示例:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<!-- 不设置样式属性 style 是看不出效果的 -->
<line x1="50" x2="50" y1="200" y2="50" style="stroke: #000000;"/>
</svg>
折线(polyline)
polyline元素是 SVG 的一个基本形状,用来创建一系列直线连接多个点。
语法:<polyline points="0 0, 20 40, 70 80, 100 90, 200 30, 250 50" />
属性:points 为点集数列,其中每个点都必须包含 2 个数字,一个是 x 坐标,一个是 y 坐标。
示例:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<!-- 不设置样式属性style是看不出效果的 并且polyline默认为填充需要把fill属性设置为none -->
<polyline points="0 0, 20 40, 70 80, 100 90, 200 30, 250 50" fill="none" style="stroke: #000000;" />
</svg>
多边形(polygon)
polygon 元素定义了一个由一组首尾相连的直线线段构成的闭合多边形形状。
语法:<polygon points="0 0, 20 40, 70 80, 100 90, 200 30, 250 50" />
属性:points 为点集数列,其中每个点都必须包含 2 个数字,一个是 x 坐标,一个是 y 坐标。
示例:和折线(polyline)同样的数据
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<!-- 不设置样式属性style是看不出效果的 并且polyline默认为填充需要把fill属性设置为none -->
<polygon points="0 0, 20 40, 70 80, 100 90, 200 30, 250 50" fill="none" style="stroke: #000000;" />
</svg>
path
path 元素是用来定义形状的通用元素。所有的基本形状都可以用 path 元素来创建。
语法:
属性:d 为一个点集数列以及其它绘制路径的信息。
示例:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<path d="M50 50 H 200 V 200 H 50 L 50 50" fill="none" style="stroke: #000000;" />
</svg>
path 里的 d 属性是什么?
path 标签的图形形状是通过属性 d 来定义的,属性 d 的值是以:命令 + 参数 的形式进行组合的,命令又是通过关键字来表示的。 既然 d 属性是以命令+参数形式组合的,那到底有哪些命令呢?以下总结了 10 个命令,分别是:
- M = Move to
- L = Line to
- H = Horizontal Line to
- V = Vertical Line to
- Q = Quadratic Bezier Curve to
- T = Smooth Quadratic Bezier Curve to
- C = Curve to
- S = Smooth Curve to
- A = Elliptical Arc
- Z = close path
直线命令
WARNING
以下所有命令中 大写为绝对定位 小写为相对定位,后续的命令亦如此以下所有命令中 大写为绝对定位 小写为相对定位,后续的命令亦如此.
M(Move to)
M 命令其实就是把画笔移动到某个点,就好像画笔提起来以后移动到一个新的位置准备开始绘制。但因为仅仅是移动画笔而没有绘制,所以 M 命令经常出现在路径的起始点,用来指明画笔应该从何处开始绘制。 每一段路径都必须以 M 命令开头,如果有多个 M 命令则表示新路径的开始。
语法:M x y 或者 m x y
参数:x、y 为坐标
L (Line to)
L 命令会绘制一点并且和之前的点(也就是 L 命令前面的点)连成一条直线。
语法:L x y 或者 l x y
参数:x、y 为坐标
示例:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<!-- 从起始点(50, 20)画一条到(250, 20)的直线 -->
<path d="M50 20 L250 20" style="stroke: #000000;"/>
<!-- 从起始点(50, 50)画一条到(250, 50)的直线 和 从起始点(50, 100)画一条到(250, 100)的直线 -->
<!-- M命令为多个时,后面的M命令为先线段的起始点 -->
<path d="M50 50 L250 50 M50 100 L250 100" style="stroke: #ff0000;"/>
<!-- 从起始点(50, 150)画一条到(250, 150)的直线 -->
<!-- M命令后面连续跟着多个坐标点,除了第一个坐标点,后面的全部默认为隐式的L命令 -->
<path d="M50 150 250 150" style="stroke: #00ff00;"/>
<!-- 从起始点(50, 200)画一条到(250, 200)又到(250,250)的折线 -->
<!-- 多个L命令连续可以省略后面的L命令 -->
<path d="M50 200 L250 200 250 250 " fill="none" style="stroke: #0000ff;"/>
</svg>
H(Horizontal Line to)
H 命令可以从之前的点绘制一条水平的直线,H 命令可以等价于 y 值和之前点相同的 L 命令
语法:H x 或者 h x
参数:x 为 X 轴坐标
示例:
<svg width="300" height="300">
<!-- 从起始点(50, 20)画一条X轴为250的水平直线 -->
<path d="M50 20 H250" style="stroke: #000000;"/>
</svg>
V(Vertical Line to)
V 命令可以从之前的点绘制一条垂直的直线,V 命令可以等价于 x 值和之前点相同的 L 命令
语法:V y 或者 v y
参数:y 为 Y 轴坐标
示例:
<svg width="300" height="300">
<!-- 从起始点(50, 20)画一条Y轴为250的垂直直线 -->
<path d="M50 20 V250" style="stroke: #000000;"/>
</svg>
注意点
连续的 H 命令和 V 命令取大值
Z(Close path)
Z 命令是一个闭合命令,他会从当前点画一条直线到路径的起始点。 Z 命令因为没有参数所以 Z 和 z 效果一样,所以不区分大小写.
语法:Z 或者 z
参数:无
示例:
<svg width="300" height="300">
<path d="M50 100 Q 175 200 300 100" fill="none" style="stroke: #ff0000;" />
</svg>
曲线命令
Q(Quadratic Bezier Curve to)
Q 命令可以用来绘制一条二次贝塞尔曲线,二次贝塞尔曲线需要一个控制点,用来确定起点和终点的曲线斜率。
语法:Q x1 y1, x y 或者 q x1 y1, x y
参数:x、y 为终点位置,x1、y1 为控制点。
示例:
<svg width="300" height="300">
<path d="M50 100 Q 175 200 300 100" fill="none" style="stroke: #ff0000;" />
</svg>
T(Smooth Quadratic Bezier Curve to)
T 命令是一个延长二次贝塞尔曲线的简化命令,T 命令可以通过前一个控制点推断出后一个控制点,这也就是为什么 T 命令只需要一个坐标的原因。 需要注意的是 T 命令的的前面必须有一个 Q 命令或者其他的 T 命令。如果 T 命令单独使用,那么控制点就会被认为和终点是同一个点,所以画出来的将是一条直线
语法:T x y 或者 t x y
参数:x、y 为终点位置
示例:
<svg width="300" height="300">
<path d="M50 100 Q 175 200 300 100 T 600 100 " fill="none" style="stroke: #ff0000;" />
</svg>
C(Curve to)
C 命令可用来绘制一条三次贝塞尔曲线,相对于二次贝塞尔曲线多了一个控制点。
语法:C x1 y1, x2 y2, x y 或者 c x1 y1, x2 y2, x y
参数:x、y 为终点位置,x1、y1 为曲线起始点的控制点,x2、y2 为曲线终止的控制点。
示例:
<svg width="300" height="300">
<path d="M50 50 C 100 100, 200 100, 250 50" fill="none" style="stroke: #000000;" />
<path d="M50 200 C 100 250, 200 150, 250 200" fill="none" style="stroke: #ff0000;" />
</svg>
S(Smooth Curve to)
三次贝塞尔曲线的 S 命令和二次贝塞尔曲线的 T 命令比较相似。S 命令也可以用来创建与前面一样的贝塞尔曲线,但如果 S 命令跟在一个 C 命令或者另一个 S 命令的后面,那么它的第一个控制点,就会被假设成前一个控制点的对称点。 如果 S 命令单独使用,前面没有 C 命令或者另一个 S 命令,那么它的两个控制点就会被假设为同一个点。
语法:S x2 y2, x y 或者 s x2 y2, x y
参数:x、y 为终点位置,x2、y2 为曲线终止的控制点。
示例:
<svg width="300" height="300">
<path d="M10 100 C 40 10, 65 10, 95 100" fill="none" style="stroke: #ff0000;" />
</svg>
三次贝塞尔曲线相对于二次贝塞尔曲线拥有更大的自由度,但两种曲线能达到的效果是差不多的。最终选择使用哪种贝塞尔曲线,通常取决于需求,以及对曲线对称性的依赖程度。
A(Elliptical Arc)
A 命令用于画弧形,它可以截取圆或椭圆的弧形成的曲线
语法: A rx ry x-axis-rotation large-arc-flag sweep-flag x y 或者 a rx ry x-axis-rotation large-arc-flag sweep-flag x y
参数:
- rx、ry 分别为 X 轴的半径和 Y 轴的半径
- x-axis-rotation 为弧度在 X 轴的旋转角度
- large-arc-flag 决定弧线是大于还是小于 180 度,0 表示小角度弧,1 表示大角度弧
- sweep-flag 为弧的方向,0 表示从起点到终点沿逆时针画弧,1 表示从起点到终点沿顺时针画弧
- x、y 为弧形的终点
示例:
<svg width="300px" height="1000px">
<path d="M10 100 50 100 A 30 50 0 0 1 150 100 L 200 100" fill="none" style="stroke: #ff0000"/>
<!-- 旋转45度的弧(第三个参数) -->
<path d="M10 200 50 200 A 30 50 45 0 1 150 200 L 200 200" fill="none" style="stroke: #ff0000"/>
<!-- 1表示大角度弧(第四个参数) -->
<path d="M10 300 50 300 A 30 50 -45 1 1 150 300 L 200 300" fill="none" style="stroke: #ff0000"/>
<!-- 0逆时针(第五个参数) -->
<path d="M10 400 50 400 A 30 50 0 1 0 150 400 L 200 400" fill="none" style="stroke: #ff0000"/>
</svg>
填充和轮廓
fill
fill 属性用于填充图形的颜色.
语法:fill= "color" 或者 style="fill: color"
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SVG - fill</title>
</head>
<body>
<svg>
<circle cx="80" cy="50" r="50" />
<circle cx="200" cy="50" r="50" fill="#ff0000" />
</svg>
</body>
</html>
从上面的示例中可以看出,在不设置 fill 属性的时候,其实默认是黑色的填充,这也就是为什么上面的很多例子设置了 fill='none' 其实就是去掉默认填充。
fill 的延伸属性:
fill-opacity
fill-opacity 属性用于设置填充颜色的透明度
<svg>
<circle cx="200" cy="50" r="50" fill="#ff0000" fill-opacity="0.5" />
</svg>
fill-rule
fill-rule
属性用来设置复杂形状的填充规则。它有两种填充方式:nonzero 和 evenodd。该属性简单说就是判断某点属于该形状的“内部”还是“外部”。那么判断的规则是什么呢?
nonzero
nonzero 为默认值,规则为:要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点情况。从 0 开始计数,路径从左向右(顺时针)穿过射线则计数加 1,从右向左(逆时针)穿过射线则计数减 1。得出计数结果后,如果结果是 0,则认为点在图形外部,否则认为在内部。
evenodd
规则为:要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部。
stroke
stroke 属性用来定义线条、文本或元素轮廓的颜色。
语法:stroke="color" 或者 style="stroke: color"
示例:
<svg>
<circle cx="200" cy="50" r="50" stroke="#ff6666" />
</svg>
文字
SVG 中不仅可以绘制各种图形,还可也以绘制文字。
text
通过 text 标签可以在 SVG 中添加文字,
示例:
<svg width="300" height="300">
<text x="50" y="50">
Hello Svg !
</text>
</svg>
渐变
了解渐变的小伙伴都知道,渐变就是从一个颜色过渡到另一个颜色,且渐变都分为两种渐变:线性渐变和径向渐变 在 SVG 中渐变依旧如此。
注意点
- defs 标签用来定义渐变
- stop 标签用来定义渐变的颜色坡度,具有三个属性:offset 定义渐变开始和结束的位置、stop-color(定义颜色)和 stop-opacity(定义透明度)
线性渐变
语法:
<linearGradient x1="" y1="" x2="" y2="">
<stop offset="0%" />
...
<stop offset="20%" />
...
<stop offset="100%" />
</linearGradient>
参数:x1、y1 定义线性渐变的起点, x2、y2 定义渐变的终点。
径向渐变
语法:
<radialGradient cx="" cy="" r="" fx="" fy="">
<stop offset="0%" />
...
<stop offset="20%" />
...
<stop offset="100%" />
</radialGradient>
参数:cx、cy、r 分别为圆的坐标和半径,也就是渐变的范围,fx、fy 定义渐变的中心点,也叫渐变的焦点。