SVG探索(四):d 属性

813 阅读5分钟

本文正在参加「金石计划」

前言

首先,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 的路径命令是对大小写敏感的,大写的路径命令表示绝对坐标,小写的是相对(于当前位置的)坐标。

具体取值包括:

含义命令
移动到 MovetoM、m
画线至 LinetoL、l、H、h、V、v
三次方贝塞尔曲线C、c、S、s
二次方贝塞尔曲线Q、q、T、t
椭圆曲线A、a
封闭路径 ClosePathZ、z

负值表示:

  • 负的角度是逆时针的;
  • 绝对坐标中,负的 xy 将被解释为负坐标;
  • 相对坐标中,负的 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
Hx画线,y坐标不变,x0 = x
hdx画线,y坐标不变,x0 += dx
Vy画线,x坐标不变,y0 = y
vdy画线,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 动图的示例。

二次贝塞尔曲线:

二次贝塞尔曲线演示动画.gif

三次贝塞尔曲线:

三次贝塞尔曲线演示动画.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通过连接路径的最后一个点与路径的起始点来闭合当前的子路径。如果这两个点的坐标不同,则在两者之间绘制一条直线。

参考