文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!
原文链接:SVG-基础部分 · 语雀
1. 什么是SVG?
- SVG 是万维网联盟的标准。
- 它使用 XML 格式定义图像。
- SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体。
- SVG全称是 Scalable Vector Graphics,意为可缩放矢量图形。
- SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失。
2003年1月14日 SVG 1.1 被Sun公司、Adobe、苹果公司、IBM 以及柯达等共同确立成为W3C推荐标准。
2. SVG的优势
- SVG 是可伸缩的。
- SVG 是开放的标准。
- SVG 文件是纯粹的 XML。
- SVG 可在图像质量不下降的情况下被放大。
- SVG 图像可在任何的分辨率下被高质量地打印。
- SVG 可被非常多的工具读取和修改(比如记事本)。
- SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
- SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)。
3. 示例
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="red" stroke-width="2" fill="blue" />
</svg>
效果
解析
- version 属性定义所使用的 SVG 版本。
- xmlns 属性定义 SVG 命名空间。
- <circle> 用来创建一个圆。
-
- cx 和 cy 属性定义圆中心的 x 和 y 坐标。如果忽略这两个属性,那么圆点会被设置为 (0, 0)。
- r 属性定义圆的半径。
- stroke 和 stroke-width 属性控制如何显示形状的轮廓。我们把圆的轮廓设置为 2px 宽,红边框。
- fill 属性设置形状内的颜色。我们把填充颜色设置为蓝色。
4. SVG的基本形状
矩形 <rect>
示例一:
<svg>
<rect
x="50"
y="20"
width="150"
height="50"
style="fill:blue;stroke:red;stroke-width:5;fill-opacity:0.5;stroke-opacity:0.5"
/>
</svg>
效果:
代码解析:
- rect 元素的 width 和 height 属性可定义矩形的高度和宽度
- x 属性定义矩形的左侧位置(例如,x="0" 定义矩形到浏览器窗口左侧的距离是 0px)
- y 属性定义矩形的顶端位置(例如,y="0" 定义矩形到浏览器窗口顶端的距离是 0px)
- style 属性用来定义 CSS 属性
-
- CSS 的 fill 属性定义矩形的填充颜色(rgb 值、颜色名或者十六进制值)
- CSS 的 stroke-width 属性定义矩形边框的宽度
- CSS 的 stroke 属性定义矩形边框的颜色
- CSS 的 fill-opacity 属性定义填充颜色透明度(合法的范围是:0 - 1)
- CSS 的 stroke-opacity 属性定义轮廓颜色的透明度(合法的范围是:0 - 1)
示例二:
<svg width="500px" height="500px">
<rect
x="50"
y="20"
rx="25"
ry="25"
width="150"
height="160"
style="fill:blue;stroke:green;stroke-width:1;opacity:0.5"
/>
</svg>
效果:
代码解析:
- rx 和 ry 属性可使矩形产生圆角。
- CSS opacity 属性用于定义了元素的透明值 (范围: 0 到 1)。
圆形 <circle>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="red" stroke-width="2" fill="blue" />
</svg>
效果:
代码解析:
- circle 标签可用来创建一个圆
- cx和cy属性定义圆点的x和y坐标。如果省略cx和cy,圆的中心会被设置为(0, 0)
- r属性定义圆的半径
椭圆 <ellipse>
<svg width="500" height="500">
<ellipse
cx="120"
cy="80"
rx="100"
ry="50"
style="fill:purple;stroke:black;stroke-width:2"
/>
</svg>
效果:
代码解析:
- ellipse 标签可用来创建一个椭圆
- CX属性定义的椭圆中心的x坐标
- CY属性定义的椭圆中心的y坐标
- RX属性定义的水平半径
- RY属性定义的垂直半径
线 <line>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<line x1="10" y1="10" x2="200" y2="100" style="stroke:black;stroke-width:5" />
</svg>
效果:
代码解析:
- line 标签可用来创建一条直线
- x1 属性在 x 轴定义线条的开始
- y1 属性在 y 轴定义线条的开始
- x2 属性在 x 轴定义线条的结束
- y2 属性在 y 轴定义线条的结束
折线 <polyline>
<svg height="200px">
<polyline
points="20,40 40,20 60,60 80,10 120,140 200,40"
style="fill:none;stroke:blue;stroke-width:3"
/>
</svg>
效果:
代码解析:
- polyline 是用于创建任何只有直线的形状
- points是点的集合
示例二:
<svg style="height:300px;width:300px;">
<polyline
points="100 20,40 200,190 80,10 80,160 200"
style="fill:red;stroke:red;stroke-width:1"
/>
</svg>
效果:
代码解析:
利用了填空,因为线段是不闭合的
多边形 <polygon>
<svg height="210" width="500">
<polygon
points="100,10 150,150 40,210"
style="fill:red;stroke:purple;stroke-width:1"
/>
</svg>
效果:
代码解析:
- polygon标签用来创建含有不少于三个边的图形
- points是点的集合
示例二:
<svg style="height:300px;width:300px;">
<polygon
points="100 20,40 200,190 80,10 80,160 200"
style="fill:none;stroke:black;stroke-width:3"
/>
</svg>
效果:
代码解析:
最后一个点会自动闭合,这也是和polyline的一个区别
路径 <path>
path元素的能力
path元素是SVG基本形状中最强大的一个,它不仅能创建其他基本形状,还能创建更多其他形状。
比如矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形等。
更重要的是能够绘制一些曲线,如贝塞尔曲线、二次曲线等。
path元素的形状是通过属性d来定义的,d属性通过“命令和坐标”的序列来控制整个path绘制的路径
路径数据:
- M = moveto:需要两个参数(x轴和y轴坐标,移动到的点的x轴和y轴的坐标
- L = lineto:需要两个参数(x轴和y轴坐标),它会在当前位置和最新的位置(L前面画笔所在的点)之间画一条线段。
- H = horizontal lineto:一个参数,标明在x轴移动到的位置,绘制水平线
- V = vertical lineto:一个参数,标明在y轴移动到的位置,绘制垂直线
- C = curveto
- S = smooth curveto
- Q = quadratic Bézier curve
- T = smooth quadratic Bézier curveto
- A = elliptical Arc
- Z = closepath:从当前点画一条直线到路径的起点
示例:
画一个三角形
<svg>
<path d="M120 0 L25 200 L225 270 Z" />
</svg>
效果:
代码解析:
定义了一条路径,它开始于位置120 0,到达位置25 200,然后从那里开始到225 270,最后在120 0关闭路径。
直线命令
示例:
画一个正方形
<svg width="100px" height="100px">
<path d="M10 10 H 90 V 90 H 10 L 10 10" style="fill: red;"/>
</svg>
效果:
代码解析:
首先定义了一个100x100的画布(坐标系),用M命令在(10,10)创建起点,通过H命令在水平方向移动到x轴为90的位置,y轴不变,也就是移动到(90, 10),再通过V命令移动到y轴为90的位置,x轴不变,也就是坐标为(90,90)的位置,再通过H命令在水平方向移动到x轴为10的位置,y轴不变,此刻的位置为(10,90),最后使用L命令在起点(10,10)的位置与上次的点(10,90)画一条直线,那么四条边就画完了。
思考?
通过上面的参数和示例可以想到,其实最后的一步有几种办法可以实现
<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<!-- 方法一:利用Z命令 -->
<path d="M10 10 H 90 V 90 H 10 Z"/>
<!-- 方法二:利用V命令 -->
<path d="M10 10 H 90 V 90 H 10 V 10"/>
</svg>
实现的效果都是一样的,Z命令是直接从当前点画一条直线到起点,V利用本次示例中最后一步向垂直方向移动,所以它也能够做到。
以上所说的是绝对距离,当然还可以使用相对距离来画,使用小写字母。
<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 h 80 v 80 h -80 Z" />
</svg>
曲线命令
C(curveto)三次贝塞尔曲线
三次贝塞尔曲线需要定义一个点和两个控制点,用C命令来创建。
(x,y)表示的是曲线的终点,(x1,y1)是起点的控制点,(x2,y2)是终点的控制点。控制点描述的是曲线起始点的斜率,曲线上各个点的斜率,是从起点斜率到终点斜率的渐变过程。
命令参数:
C x1 y1, x2 y2, x y
c dx1 dy1, dx2 dy2, dx dy
示例:
<svg width="200px" height="200px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
</svg>
效果:
代码解释:
用M创建一个起点(10,10),C创建一个以(50,10)为终点,(20,20)为起点的控制点,(40,10)为终点的控制点。
原理分析:曲线沿着起点到第一控制点的方向伸出,逐渐弯曲,然后沿着第二控制点到终点的方向结束。
S(smooth curveto)简写的三次贝塞尔曲线
S其实是创建一个特殊的三次贝塞尔曲线。它特殊的地方就是当一个点某一侧的控制点是它另一侧的控制点的对称也就是保持斜率不变。
(x,y)表示的是曲线的终点,(x2,y2)是既是终点的控制点也是起点的控制点。
命令参数:
S x2 y2, x y
s dx2 dy2, dx dy
示例:
先画一个三次贝塞尔曲线
<svg width="400px" height="200px">
<path d="M 10 50 C 40 20, 120 20, 150 50" stroke="black" fill="transparent"/>
</svg>
效果:
在三次贝塞尔曲线后面使用简写的三次贝塞尔曲线,使用S命令画一个简写的三次贝塞尔曲线。
<svg width="400px" height="200px">
<path d="M 10 50 C 40 20, 120 20, 150 50 S 260 80, 290 50" stroke="black" fill="transparent"/>
</svg>
效果:
相当于起始点使用上一个三次贝塞尔曲线终点的斜率,依照这个斜率画出了一个镜像的三次贝塞尔曲线。
注意:如果S命令跟在一个C命令或者另一个S命令的后面,它的第一个控制点,就会被假设成前一个控制点的对称点。如果S命令单独使用,前面没有C命令或者另一个S命令,那么它的两个控制点就会被假设为同一个点。
Q(quadratic Bézier curve)二次贝塞尔曲线
二次贝塞尔曲线Q,只需要一个控制点,用来确定起点和终点的曲线斜率。因此它需要两组参数,控制点和终点坐标。
Q x1 y1, x y
q dx1 dy1, dx dy
示例:
<svg width="200px" height="200px">
<path d="M 10 80 Q 95 20 180 80" stroke="black" fill="transparent"/>
</svg>
效果:
它相比三次贝塞尔曲线,只有一个控制点,也就是一个点同时控制起点和终点
T(smooth quadratic Bézier curveto)简写的二次贝塞尔曲线
简写的二次贝塞尔曲线T,只需要一个终点。
T x y
t dx dy
示例:
<svg width="400px" height="200px">
<path d="M10 80 Q 50 10, 90 80 T 170 80" stroke="black" fill="transparent"/>
</svg>
效果:
注意:T命令前面必须是一个Q命令,或者是另一个T命令,才能达到这种效果。如果T单独使用,那么控制点就会被认为和终点是同一个点,所以画出来的将是一条直线。
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 dx dy
参数说明
- 弧形命令A前两个参数rx和ry分别是x轴半径和y轴半径。
- 弧形命令A的第三个参数表示弧形的旋转情况。
- large-arc-flag决定弧线是大于还是小于180度,0表示小角度弧,1表示大角度弧。
- sweep-flag表示弧线的方向,0表示从起点到终点沿逆时针画弧,1表示从起点到终点沿顺时针画弧。
- x:结束点x坐标。
- y:结束点y坐标。
示例:
<svg width="400px" height="320px">
<path d="M100 210
L 110 200
A 32 36 0 0 1 140 155
L 150 155
A 32 36 -15 0 1 215 96
L 230 80" stroke="black" fill="red" stroke-width="3" />
</svg>
效果:
代码解析:
画布上有一条对角线,中间有两个椭圆弧被对角线切开(x radius = 32, y radius = 36)。
第一个椭圆弧的x-axis-rotation(x轴旋转角度)是0,所以弧形所在的椭圆是正置的(没有倾斜)。
在第二个椭圆弧中,x-axis-rotation设置为-15,所以这是一个旋转了15度的椭圆,并以短轴为分割线,形成了两个弧形。
5. 填充和轮廓
在上面的例子中我们经常用这样的属性:
fill="none" style="stroke: #ff0000"
我想大家看着肯定也会想这是啥玩意?其实这就是我们接下来要说的内容。
5.1. fill
fill属性用于填充图形的颜色
语法:fill= "colour" 或者 style="fill: colour"
<svg>
<circle cx="80" cy="50" r="50" />
<circle cx="200" cy="50" r="50" fill="#ff0000"/>
</svg>
效果:
从上面的示例中可以看出,在不设置fill属性的时候,其实默认是黑色的填充,这也就是为什么上面的很多例子我们设置了 fill='none' 其实就是去掉默认填充。
fill属性其实还有一些延伸属性:
5.1.1. fill-opacity
fill-opacity属性用于设置填充颜色的透明度
<svg width="400" height="400">
<circle cx="80" cy="50" r="50" />
<circle cx="200" cy="50" r="50" fill="#ff0000"/>
<circle cx="80" cy="130" r="50" fill="#00ff00"/>
<circle cx="200" cy="130" r="50" fill="#00ff00" fill-opacity="0.5"/>
</svg>
效果:
5.1.2. fill-rule
fill-rule属性用来设置复杂形状的填充规则。它有两种填充方式:nonzero 和 evenodd。 该属性简单说就是判断某点属于该形状的“内部”还是“外部”。那么判断的规则是什么呢?
nonzero
nonzero为默认值,规则为:要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点情况。从0开始计数,路径从左向右(顺时针)穿过射线则计数加1,从右向左(逆时针)穿过射线则计数减1。得出计数结果后,如果结果是0,则认为点在图形外部,否则认为在内部。
是不是感觉还是有点懵?举个例子看一下。
<svg width="12cm" height="4cm" viewBox="0 0 1200 400">
<defs>
<path id="Triangle" d="M 16,0 L -8,9 v-18 z" fill="#66ff66" stroke="none" />
</defs>
<g fill-rule="nonzero" fill="#6666ff" stroke="#ff6666" stroke-width="3" >
<path d="M 250,75 L 323,301 131,161 369,161 177,301 z" />
<use xlink:href="#Triangle" transform="translate(306.21 249) rotate(72)" />
<use xlink:href="#Triangle" transform="translate(175.16,193.2) rotate(216)" />
<use xlink:href="#Triangle" transform="translate(314.26,161) rotate(0)" />
<use xlink:href="#Triangle" transform="translate(221.16,268.8) rotate(144)" />
<use xlink:href="#Triangle" transform="translate(233.21,126.98) rotate(288)" />
<path d="M 600,81 A 107,107 0 0,1 600,295 A 107,107 0 0,1 600,81 z
M 600,139 A 49,49 0 0,1 600,237 A 49,49 0 0,1 600,139 z" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(0) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(120) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(240) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(60) translate(49,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(180) translate(49,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(300) translate(49,0) rotate(90)" overflow="visible" />
<path d="M 950,81 A 107,107 0 0,1 950,295 A 107,107 0 0,1 950,81 z
M 950,139 A 49,49 0 0,0 950,237 A 49,49 0 0,0 950,139 z" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(0) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(120) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(240) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(60) translate(49,0) rotate(-90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(180) translate(49,0) rotate(-90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(300) translate(49,0) rotate(-90)" overflow="visible" />
</g>
</svg>
PS:上面示例中的绿色三角形只是用来辅助理解的,可以忽略,咱们只需要了解规则是如何填充的就行。
效果图:
evenodd
规则为:要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部。
直接看示例吧:
<svg width="12cm" height="4cm" viewBox="0 0 1200 400">
<defs>
<path id="Triangle" d="M 16,0 L -8,9 v-18 z" fill="#66ff66" stroke="none" />
</defs>
<g fill-rule="evenodd" fill="#6666ff" stroke="#ff6666" stroke-width="3" >
<path d="M 250,75 L 323,301 131,161 369,161 177,301 z" />
<use xlink:href="#Triangle" transform="translate(306.21 249) rotate(72)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(175.16,193.2) rotate(216)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(314.26,161) rotate(0)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(221.16,268.8) rotate(144)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(233.21,126.98) rotate(288)" overflow="visible" />
<path d="M 600,81 A 107,107 0 0,1 600,295 A 107,107 0 0,1 600,81 z
M 600,139 A 49,49 0 0,1 600,237 A 49,49 0 0,1 600,139 z" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(0) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(120) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(240) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(60) translate(49,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(180) translate(49,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(600,188) rotate(300) translate(49,0) rotate(90)" overflow="visible" />
<path d="M 950,81 A 107,107 0 0,1 950,295 A 107,107 0 0,1 950,81 z
M 950,139 A 49,49 0 0,0 950,237 A 49,49 0 0,0 950,139 z" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(0) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(120) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(240) translate(107,0) rotate(90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(60) translate(49,0) rotate(-90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(180) translate(49,0) rotate(-90)" overflow="visible" />
<use xlink:href="#Triangle" transform="translate(950,188) rotate(300) translate(49,0) rotate(-90)" overflow="visible" />
</g>
</svg>
PS:上面示例中的绿色三角形只是用来辅助理解的,可以忽略,咱们只需要了解规则是如何填充的就行。
效果为:
5.2. stroke
stroke属性用来定义线条、文本或元素轮廓的颜色。
语法:stroke="colour" 或者 style="stroke: colour"
<svg>
<circle cx="80" cy="50" r="50" />
<circle cx="200" cy="50" r="50" stroke="#ff6666"/>
</svg>
效果:
stroke属性也有一些延伸属性,下面依次介绍一下。
5.2.1. stroke-width
stroke-width属性定义了轮廓的宽度
<svg width="300" height="300">
<circle cx="80" cy="50" r="50" />
<circle cx="200" cy="50" r="50" stroke="#ff6666" />
<circle cx="80" cy="200" r="50" stroke="#ff6666" stroke-width="5" />
<circle cx="200" cy="200" r="50" stroke="#ff6666" stroke-width="10"/>
</svg>
效果:
5.2.2. stroke-opacity
stroke-opacity属性用于设置轮廓的透明度
<svg width="300" height="500">
<circle cx="80" cy="50" r="50" />
<circle cx="200" cy="50" r="50" stroke="#ff6666" />
<circle cx="80" cy="100" r="10" stroke="#ff6666" stroke-width="50" />
<circle cx="200" cy="100" r="10" stroke="#ff6666" fill="none" stroke-width="50" stroke-opacity="0.5"/>
</svg>
效果:
5.2.3. stroke-linecap
stroke-linecap属性定义了轮廓终点的形状,该属性有三个值:
- butt:默认值,以直边结束线段
- round:以圆角结束线段,圆角的半径由stroke-width(轮廓宽度)控制的
- square:也是以直边结束线段,但和butt不同的是会在结束位置多出一段由stroke-width(轮廓宽度)大小控制的长度。
<svg width="300" height="200">
<g fill="#ffff00" stroke="#ff0000" stroke-width="10">
<path stroke-linecap="butt" d="M20 50 l200 0" />
<path stroke-linecap="round" d="M20 100 l200 0" />
<path stroke-linecap="square" d="M20 150 l200 0" />
</g>
</svg>
效果:
5.2.4. stroke-linejoin
stroke-linejoin属性定义了轮廓连接处的样式。样式有三种类型:
- miter:默认值,表示用方形画笔在连接处形成尖角
- round:用圆角连接,实现平滑效果
- bevel:连接处会形成一个斜面
<svg width="160" height="280">
<g fill="none" stroke="#ff0000" stroke-width="20">
<path d="M40 60 80 20 120 60" stroke-linecap="butt" stroke-linejoin="miter" />
<path d="M40 140 80 100 120 140" stroke-linecap="round" stroke-linejoin="round" />
<path d="M40 220 80 180 120 220" stroke-linecap="square" stroke-linejoin="bevel" />
</g>
</svg>
效果:
5.2.5. stroke-dasharray
stroke-dasharray属性可以定义轮廓为虚线
语法:stroke-dasharray="xxx"
参数:xxx为一列数字字符串,对应的是:线段 空格 线段 空格......
<svg width="300" height="300">
<g fill="#ffff00" stroke="#ff0000" stroke-width="5">
<path d="M20 50 l200 0" />
<path stroke-dasharray="5, 10" d="M20 100 l200 0" />
<path stroke-dasharray="5, 10, 5" d="M20 150 l200 0" />
<path stroke-dasharray="10, 5, 20" d="M20 200 l200 0" />
</g>
</svg>
效果:
stroke-dashoffset
stroke-dashoffset 属性用于指定路径开始的距离。值可为正值、负值、百分比。
示例:
<svg width="300" height="300">
<g fill="#ffff00" stroke="#ff0000" stroke-width="5" stroke-dasharray="20">
<path d="M50 50 l200 0" />
<path d="M50 100 l200 0" stroke-dashoffset="10" />
<path d="M50 150 l200 0" stroke-dashoffset="1%" />
<path d="M50 200 l200 0" stroke-dashoffset="-10" />
</g>
</svg>
效果:
stroke-miterlimit
如果两条线交汇在一起形成一个尖角,而且属性 stroke-linejoin 指定了 miter,斜接有可能扩展到远远超过路径轮廓线的线宽。属性 stroke-miterlimit 对斜接长度和stroke-width的比率强加了一个极限。当极限到达时,交汇处由斜接变成倒角。
<svg width="200" height="500">
<g fill="none" stroke="#ff0000" stroke-width="20">
<path d="M40 60 80 20 120 60 130 20 180 70" stroke-linejoin="miter" stroke-miterlimit="1" />
<path d="M40 140 80 100 120 140 130 100 180 150" stroke-linejoin="miter" stroke-miterlimit="2" />
<path d="M40 220 80 180 120 220 130 180 180 230" stroke-linejoin="miter" stroke-miterlimit="3" />
<path d="M40 300 80 260 120 300 130 260 180 310" stroke-linejoin="miter" stroke-miterlimit="4" />
<path d="M40 380 80 340 120 380 130 340 180 390" stroke-linejoin="miter" stroke-miterlimit="5" />
</g>
</svg>
效果为:
6. 文字
SVG中我们不仅可以绘制各种图形,我们还可也以绘制文字。
6.1. text
通过text标签我们可以在SVG中添加文字,
<svg width="300" height="300">
<text x="50" y="50">Hello Mr. Greedy Wolf !</text>
</svg>
效果为:
从上面的实例我们可以看到,text标签有一些自己的属性,下面我们细说一下text标签的属性。
x和y
x和y属性决定了文字的绘制起点。如上面的例子我们就是从坐标(50,50)的位置开始绘制的文字。
但需要注意的是x和y的值可以是一个数列。如果设置为了一个数列则会应用到每一个字符上
<svg width="880" height="300">
<text
x="30 70 110 150 190 230 270 310 350 390 430 470 510 550 590 630 670 710 750 790"
y="60 70 80 90 100 110 120 130 140 150 160 170 180 170 160 150 140 130 120 110"
fill="#f00"
stroke="#0f0"
font-size="50"
font-weight="bold" >
Hello Mr. Greedy Wolf !
</text>
</svg>
效果为:
dx和dy
dx和dy属性与x和y属性不同的是,x和y属性是绝对的坐标,而dx和dy属性是相对于当前位置的偏移量。
参数也可以是一个数列。如果设置为了一个数列则会应用到每一个字符上
<svg width="880" height="500">
<text
dx="50 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10"
dy="50 20 -20 20 -20 20 -20 20 -20 20 -20 20 -20 20 -20 20 -20 20 -20 20 -20"
fill="#f00"
stroke="#0f0"
font-size="50"
font-weight="bold" >
Hello Mr. Greedy Wolf !
</text>
</svg>
效果为:
rotate
rotate属性可以把文字旋转一个角度。
<svg width="500" height="500">
<text
x="50"
y="50"
rotate="10"
fill="#f00"
stroke="#0f0"
font-size="50"
font-weight="bold" >
Hello Svg !
</text>
</svg>
效果为:
同样的参数也可以是一个数列。如果设置为了一个数列则会应用到每一个字符上
<svg width="1000" height="500">
<text
dx="50 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20"
y="50"
rotate="0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 300 320 340 360 380"
fill="#f00"
stroke="#0f0"
font-size="50"
font-weight="bold" >
Hello Mr. Greedy Wolf !
</text>
</svg>
效果为:
textLength
textLength属性给定了一个字符串的计算长度。在文字的长度和textLength属性给定的长度不一致的情况下渲染引擎会精细调整字型的位置。
<svg width="1000" height="500">
<text x="50" y="50" textLength="400" fill="#f00" stroke="#0f0" font-size="50"font-weight="bold" >
Hello Mr. Greedy Wolf !
</text>
<text x="50" y="100" textLength="810" fill="#f00" stroke="#0f0" font-size="50" font-weight="bold" >
Hello Mr. Greedy Wolf !
</text>
</svg>
效果为:
lengthAdjust
lengthadjust属性可以控制文本以什么方式伸展到由textLength属性定义的长度。
- spacing:只拉伸或压缩间距(文字不变形)
- spacingAndGlyphs:同时拉伸或压缩间距和文字本身(文字变形)
<svg width="1000" height="500">
<text x="50" y="50" textLength="300" lengthadjust="spacing" fill="#f00" stroke="#0f0" font-size="50" font-weight="bold" >
Welcome to the world of svg !
</text>
<text x="50" y="100" textLength="300" lengthadjust="spacingAndGlyphs" fill="#f00" stroke="#0f0" font-size="50" font-weight="bold" >
Welcome to the world of svg !
</text>
<text x="50" y="150" textLength="600" lengthadjust="spacing" fill="#f00" stroke="#0f0" font-size="50" font-weight="bold" >
Hi Mr. Greedy Wolf !
</text>
<text x="50" y="200" textLength="600" lengthadjust="spacingAndGlyphs" fill="#f00" stroke="#0f0" font-size="50" font-weight="bold" >
Hi Mr. Greedy Wolf !
</text>
</svg>
效果为:
fill和stroke
填充和轮廓也都可以应用于文字
<svg width="300" height="300">
<text x="50" y="50" fill="#f00" stroke="#0f0" font-weight="bold">Hello Mr. Greedy Wolf !</text>
</svg>
效果为:
CSS文字属性
一些CSS中的文字样式属性同样也可以应用于SVG的文字中。比如上面例子中我们用到的文字加粗:font-weight 还有很多属性同样也适用,例如:font-size、font-family、font-style、font-variant、font-stretch、font-size-adjust、kerning、letter-spacing、word-spacing、text-decoration等。
<svg width="600" height="300">
<text x="50" y="50" fill="#f00" stroke="#0f0" font-weight="bold" font-size="50" font-family="arial">Hello Mr. Greedy Wolf !</text>
</svg>
效果:
6.2. tspan
tspan标签和text标签一样都可以用来添加文字,但不同的是tspan标签的作用为标记大块文本内的部分内容。比如一段文本其中某个字需要加粗或者颜色不一致,就可以用到tspan标签。
tspan标签的属性和text标签一致,上面说道的text标签的属性在tspan标签中也适用。
需注意的是tspan标签必须是一个text元素的子元素或别的子元素tspan的子元素。
<svg width="700" height="500">
<text x="50" y="50" fill="#f00" stroke="#0f0" font-size="50" >
Hello <tspan fill="#f0f" font-weight="bold"> 小 </tspan> Mr. Greedy Wolf !
</text>
</svg>
效果:
需要注意的是tspan标签的x、y和 dx、dy 会对标签后面的内容造成影响
<svg width="640" height="500">
<text x="50" y="50" fill="#f00" stroke="#0f0" font-size="50" >
Hello <tspan x="150" dy="70" fill="#f0f" font-weight="bold"> 小 </tspan> Mr. Greedy Wolf !
</text>
</svg>
效果:
6.3. tref
tref标签配合xlink:href属性能引用已经定义的文本,实现复制的效果。并且引用之后还可以单独定义他的样式。
但遗憾的是 tref标签是SVG 1.1规范的内容,它已经从SVG 2.0规范中删除了。
因此此处咱们可以使用 use标签来代替它,这里说明一下:
- defs标签可以定义一些之后绘制中需要重复使用的图形元素,defs是definitions的缩写 。
- use标签可以在SVG文档内读取目标节点,并在别的地方复制使用。
<svg width="500" height="500">
<defs>
<text x="50" y="50" id="text" stroke="#000" font-size="30" >今天天气不错!</text>
</defs>
<use x="50" y="100" fill="#f00" xlink:href="#text" />
<use x="50" y="150" fill="#0f0" rotate="45" xlink:href="#text" />
</svg>
效果:
6.4. textPath
textPath标签可以利用它的xlink:href属性取得一个任意路径,并且可以让字符顺着路径渲染。
<svg width="600" height="500">
<path id="pathM" d="M 50 50 100 100 200 50 300 100" fill="none" />
<path id="pathQ" d="M50 100 Q 175 200 300 100 T 600 100" fill="none" />
<text>
<textPath xlink:href="#pathM"> Welcome to the world of SVG ! </textPath>
</text>
<text>
<textPath xlink:href="#pathQ"> Welcome to the world of SVG ! Welcome to the world of SVG ! </textPath>
</text>
</svg>
效果:
7. 渐变
渐变就是从一个颜色过渡到另一个颜色,且渐变都分为两种渐变:线性渐变和径向渐变
在SVG中渐变依旧如此。
但需要注意的是这里我们需要接触两个新的标签:
- defs标签用来定义渐变
- stop标签用来定义渐变的颜色坡度,具有三个属性:offset定义渐变开始和结束的位置、stop-color(定义颜色)和stop-opacity(定义透明度)
线性渐变(linearGradient)
线性渐变就是沿直线改变颜色。
<linearGradient x1="" y1="" x2="" y2="">
<stop offset="0%"/>
...
<stop offset="100%"/>
</linearGradient>
参数:x1、y1定义线性渐变的起点, x2、y2定义渐变的终点。
<svg width="500" height="300">
<defs>
<linearGradient id="linearGradient" x1="0" y1="0" x2="100%" y2="0">
<stop offset="0%" stop-color="rgb(255,255,0)" />
<stop offset="100%" stop-color="rgb(255,0,0)" />
</linearGradient>
</defs>
<ellipse cx="100" cy="70" rx="100" ry="50" fill="url(#linearGradient)" />
</svg>
效果:
改变x1、y1和x2、y2的值可以定义不同方向上的渐变
<svg width="500" height="400">
<defs>
<linearGradient id="linearGradient" x1="0" y1="0" x2="100%" y2="0">
<stop offset="0%" stop-color="rgb(255,255,0)" />
<stop offset="100%" stop-color="rgb(255,0,0)" />
</linearGradient>
<linearGradient id="linearGradient1" x1="50%" y1="0%" x2="50%" y2="100%">
<stop offset="0%" stop-color="rgb(255,255,0)" />
<stop offset="100%" stop-color="rgb(255,0,0)" />
</linearGradient>
<linearGradient id="linearGradient2" x1="100%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="rgb(255,255,0)" />
<stop offset="100%" stop-color="rgb(255,0,0)" />
</linearGradient>
</defs>
<ellipse cx="100" cy="70" rx="100" ry="50" fill="url(#linearGradient)" />
<ellipse cx="100" cy="200" rx="100" ry="50" fill="url(#linearGradient1)" />
<ellipse cx="100" cy="350" rx="100" ry="50" fill="url(#linearGradient2)" />
</svg>
效果:
径向渐变(radialGradient)
径向渐变其实就是以一个点做放射性的渐变。
<radialGradient cx="" cy="" r="" fx="" fy="">
<stop offset="0%"/>
...
<stop offset="100%"/>
</radialGradient>
参数: cx、cy、r分别为圆的坐标和半径,也就是渐变的范围,fx、fy定义渐变的中心点,也叫渐变的焦点。
<svg width="500" height="400">
<defs>
<radialGradient id="radialGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" stop-color="rgb(255, 255, 0)" />
<stop offset="100%" stop-color="rgb(255, 0, 0)" />
</radialGradient>
<radialGradient id="radialGradient1" cx="50%" cy="50%" r="50%" fx="50%" fy="0%">
<stop offset="0%" stop-color="rgb(255, 255, 0)" />
<stop offset="100%" stop-color="rgb(255, 0, 0)" />
</radialGradient>
<radialGradient id="radialGradient2" cx="50%" cy="50%" r="50%" fx="0%" fy="50%">
<stop offset="0%" stop-color="rgb(255, 255, 0)" />
<stop offset="100%" stop-color="rgb(255, 0, 0)" />
</radialGradient>
</defs>
<ellipse cx="100" cy="100" rx="100" ry="50" fill="url(#radialGradient)" />
<ellipse cx="100" cy="210" rx="100" ry="50" fill="url(#radialGradient1)" />
<ellipse cx="100" cy="320" rx="100" ry="50" fill="url(#radialGradient2)" />
</svg>
效果:
不管是线性渐变还是径向渐变,他们不仅可以用于图形还是用于文字
<svg width="1000" height="400">
<defs>
<linearGradient id="linearGradient" x1="0" y1="0" x2="100%" y2="0">
<stop offset="0%" stop-color="rgb(0,255,255)" />
<stop offset="100%" stop-color="rgb(0,0,255)" />
</linearGradient>
<radialGradient id="radialGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="100%">
<stop offset="0%" stop-color="rgb(0, 255, 255)" />
<stop offset="100%" stop-color="rgb(0, 0, 255)" />
</radialGradient>
</defs>
<text fill="url(#linearGradient)" font-size="100" font-family="Verdana" x="50" y="100">Mr. Greedy Wolf</text>
<text fill="url(#radialGradient)" font-size="100" font-family="Verdana" x="50" y="200">Mr. Greedy Wolf</text>
</svg>
效果:
同样的渐变不仅可以用来填充(fill),还能用来绘制轮廓(stroke)
<svg width="1000" height="400">
<defs>
<linearGradient id="linearGradient" x1="0" y1="0" x2="100%" y2="0">
<stop offset="0%" stop-color="rgb(0,255,255)" />
<stop offset="100%" stop-color="rgb(0,0,255)" />
</linearGradient>
<radialGradient id="radialGradient" cx="50%" cy="50%" r="50%" fx="50%" fy="100%">
<stop offset="0%" stop-color="rgb(0, 255, 255)" />
<stop offset="100%" stop-color="rgb(0, 0, 255)" />
</radialGradient>
</defs>
<text stroke-width="3" stroke="url(#linearGradient)" fill="none" font-size="100" font-family="Verdana" x="50" y="100">Mr. Greedy Wolf</text>
<text stroke-width="3" stroke="url(#radialGradient)" fill="none" font-size="100" font-family="Verdana" x="50" y="200">Mr. Greedy Wolf</text>
</svg>
效果:
8. 裁剪和蒙层
裁剪和蒙层是我们在之后的SVG应用中常用的功能之一。总而言之是一些特定场景必不可少的功能。
裁剪
裁剪的功能主要是使用clipPath标签定义一条裁剪路径,然后用来裁剪掉元素的部分内容。且任何透明度的效果都是无效的,它只能要么裁剪掉要么不裁剪。
<svg width="300" height="300">
<defs>
<clipPath id="clipPath">
<path d="M10 50 A50 50 0 0 1 100 50 A50 50 0 0 1 190 50 Q210 100 100 200 Q-5 100 10 50 Z" />
</clipPath>
</defs>
<rect x="0" y="0" width="200" height="200" fill="#f00" clip-path="url(#clipPath)" />
</svg>
效果:
蒙层
蒙层的功能主要实现标签就是mask标签,他的功能和名字正好相反,他不是用来遮住元素的部分内容,而是用来显示元素中mask标签遮住的内容。 他和clipPath标签不同的是他允许使用透明度(透明度为0则无蒙层效果)和灰度值遮罩计算得的软边缘
<svg width="300" height="300">
<defs>
<mask id="Mask">
<path d="M10 50 A50 50 0 0 1 100 50 A50 50 0 0 1 190 50 Q210 100 100 200 Q-5 100 10 50 Z" fill="#fff" fill-opacity="0.5" />
</mask>
</defs>
<rect x="0" y="0" width="200" height="200" fill="#f00" mask="url(#Mask)" />
</svg>
效果:
9. 总结
学到老,活到老。
不积跬步无以至千里,学习亦是如此。
我这里只是总结了 svg 基础部分,有兴趣的朋友可以去深入了解一下,像 svg 动画等等。