本文正在参加「金石计划」
前言
首先,SVG 是什么?
SVG 是指可缩放矢量图形(Scalable Vector Graphics,SVG),基于 XML 标记语言,可以用于描述二维的矢量图形。显而易见,SVG 格式提供的是矢量图,因此图片可以被无限放大而不失真或降低质量,并且可以方便地修改内容和进行定制化开发。
在前端开发工作中,我们经常会用到 SVG 定义的图标、图片等。本文介绍了SVG中很常见的 d 属性,文中示例来自 MDN文档。
d 属性是什么
在 SVG 中,d 属性定义的是将要绘制的 path 路径。举个例子,这里我们可以借助 d 属性绘制一个红心~
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path
fill="none"
stroke="red"
d="M 10,30
A 20,20 0,0,1 50,30
A 20,20 0,0,1 90,30
Q 90,60 50,90
Q 10,60 10,30 z" />
</svg>
d 属性可以作为CSS属性:
<style>
/*鼠标悬浮时触发*/
#svg_css_ex1:hover path {
d: path(
"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 M5,5 L90,90"
);
}
</style>
<svg id="svg_css_ex1" width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path
fill="none"
stroke="red"
d="M 10,30
A 20,20 0,0,1 50,30
A 20,20 0,0,1 90,30
Q 90,60 50,90
Q 10,60 10,30 z
" />
</svg>
效果如下:
路径命令
SVG 的路径命令是对大小写敏感的,大写的路径命令表示绝对坐标,小写的是相对(于当前位置的)坐标。
具体取值包括:
| 含义 | 命令 |
|---|---|
| 移动到 Moveto | M、m |
| 画线至 Lineto | L、l、H、h、V、v |
| 三次方贝塞尔曲线 | C、c、S、s |
| 二次方贝塞尔曲线 | Q、q、T、t |
| 椭圆曲线 | A、a |
| 封闭路径 ClosePath | Z、z |
负值表示:
- 负的角度是逆时针的;
- 绝对坐标中,负的 x 和 y 将被解释为负坐标;
- 相对坐标中,负的 x 值为向左移动,负的 y 值为向上移动。
示例汇总如下:
移动到
| 命令 | 参数 | 注释 |
|---|---|---|
| M | (x, y) | 从当前位置移动到坐标 (x, y)。 |
| m | (dx, dy) | x坐标增加dx, y坐标增加dy |
单独使用 M 和 m 的意义不大,一般会结合 Lineto 命令使用。
画线到
| 命令 | 参数 | 注释 |
|---|---|---|
| L | (x, y) | 从当前位置画线到坐标 (x, y) |
| l | (dx, dy) | 画线,x坐标增加dx, y坐标增加dy |
| H | x | 画线,y坐标不变,x0 = x |
| h | dx | 画线,y坐标不变,x0 += dx |
| V | y | 画线,x坐标不变,y0 = y |
| v | dy | 画线,x坐标不变,y0 += dy |
举个例子,这里是移动到坐标(10,10),然后水平画30px的直线;接着,向下移动10px(m 0,10),再继续水平画30px的直线。最后,向左移动30px、向下移动10px,再水平向左画线。
<svg
width="100"
height="100"
viewBox="0 0 100 100"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<path fill="none" stroke="red"
d="M 10,10 h 30
m 0,10 h 30
m -30,10 h -30"
/>
</svg>
三次贝塞尔曲线
维基百科 上有详细地介绍了贝塞尔曲线的情况,还包括了很多 gif 动图的示例。
二次贝塞尔曲线:
三次贝塞尔曲线:
三次贝塞尔曲线是使用四个点定义的平滑曲线:
- 起始点 (Po = {xo, yo})
- 终点 (Pn = {xn, yn})
- 起始控制点 (Pcs = {xcs, ycs})
- 终点控制点 (Pce = {xce, yce})
| 命令 | 参数 | 注释 |
|---|---|---|
| C | (x1,y1, x2,y2, x,y) | 在当前位置和终点 (x, y) 之间绘制一条三次贝塞尔曲线。 Pn = {x, y} Pcs = {x1, y1} Pce = {x2, y2} |
| c | (dx1,dy1, dx2,dy2, dx,dy) | 在当前位置和终点(终点为当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处)之间绘制一条三次贝塞尔曲线。 Pn = {xo + dx, yo + dy} Pcs = {xo + dx1, yo + dy1} Pce = {xo + dx2, yo + dy2} |
| S | (x2,y2, x,y) | 在当前位置和终点 x,y 之间绘制一条平滑的三次贝塞尔曲线。 |
| s | (dx2,dy2, dx,dy) | 在当前位置和终点(终点为当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处)之间绘制一条平滑的三次贝塞尔曲线。 |
二次贝塞尔曲线
二次贝塞尔曲线是使用三个点定义的平滑曲线:
- 起始点 (Po = {xo, yo})
- 终点 (Pn = {xn, yn})
- 控制点 (Pc = {xc, yc})
| 命令 | 参数 | 注释 |
|---|---|---|
| Q | (x1,y1, x,y) | 在当前位置和终点 (x, y) 之间绘制一条二次贝塞尔曲线。 Pn = {x, y} Pc = {x1, y1} |
| q | (dx1,dy1, dx,dy) | 在当前位置和终点(终点为当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处)之间绘制一条二次贝塞尔曲线。 Pn = {xo + dx, yo + dy} Pc = {xo + dx1, yo + dy1} |
| T | (x,y) | 在当前位置和终点 x,y 之间绘制一条平滑的二次贝塞尔曲线。Pn = {x, y} |
| t | (dx,dy) | 在当前位置和终点(终点为当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处)之间绘制一条平滑的二次贝塞尔曲线。Pn = {xo + dx, yo + dy} |
椭圆曲线
椭圆曲线是定义为椭圆的一部分的曲线。
| 命令 | 参数 | 注释 |
|---|---|---|
| A | (rx ry angle large-arc-flag sweep-flag x y) | 在当前位置和坐标 x,y 之间绘制一条椭圆曲线。用于绘制圆弧的椭圆中心根据命令的其他参数确定: rx 和ry 是椭圆的两个半径; angle 表示椭圆相对于 x 轴的旋转角度; large-arc-flag 和 sweep-flag 允许选择必须绘制的弧线,因为其他参数可以绘制 4 条可能的弧线。 large-arc-flag 允许选择一个大弧线(1)或一个小弧线(0), sweep-flag 允许选择一条顺时针旋转的弧线(1)或一条逆时针旋转的弧线(0) |
| a | (rx ry angle large-arc-flag sweep-flag dx dy) | 在当前位置和指定位置之间绘制一条椭圆曲线。指定位置为当前位置沿 x 轴偏移 dx 以及沿 y 轴偏移 dy 处。用于绘制圆弧的椭圆中心根据命令的其他参数确定: rx 和 ry 是椭圆的两个半径; angle 表示椭圆相对于 x 轴的旋转角度; large-arc-flag 和 sweep-flag 允许选择必须绘制的弧线,因为其他参数可以绘制 4 条可能的弧线。 large-arc-flag 允许选择一个大弧线(1)或一个小弧线(0), sweep-flag 允许选择一条顺时针旋转的弧线(1)或一条逆时针旋转的弧线(0) |
封闭路径
ClosePath 命令将从当前位置绘制一条直线到路径中的第一个点。
| 命令 | 参数 | 注释 |
|---|---|---|
| Z, z | 通过连接路径的最后一个点与路径的起始点来闭合当前的子路径。如果这两个点的坐标不同,则在两者之间绘制一条直线。 |