<path>
元素在 SVG 中是终极绘图元素。 它可以绘制任何东西! 我听说,在幕后,所有其他绘图元素最终都使用路径。 path 元素采用单个属性来描述它所绘制的内容:d
属性。 它具有的值本身就是一个小型语法。 它看起来可能相当难以理解。 它是一大堆数字和字母,压缩成一个长字符串。 就像任何计算机一样,这里是有规律可循的。 我不是专家,但我认为深入研究会很有趣。
这是一个中等复杂路径的示例,我认为
<path d="M213.1,6.7c-32.4-14.4-73.7,0-88.1,30.6C110.6,4.9,67.5-9.5,36.9,6.7C2.8,22.9-13.4,62.4,13.5,110.9
C33.3,145.1,67.5,170.3,125,217c59.3-46.7,93.5-71.9,111.5-106.1C263.4,64.2,247.2,22.9,213.1,6.7z"/>
我们可以重新格式化它以开始理解它(仍然是有效代码)
<path d="
M 213.1,6.7
c -32.4-14.4-73.7,0-88.1,30.6
C 110.6,4.9,67.5-9.5,36.9,6.7
C 2.8,22.9-13.4,62.4,13.5,110.9
C 33.3,145.1,67.5,170.3,125,217
c 59.3-46.7,93.5-71.9,111.5-106.1
C 263.4,64.2,247.2,22.9,213.1,6.7
z" />
字母是 **命令**。 数字是 **传递给这些命令的值**。 所有逗号都是可选的(它们可以是空格)。
例如,第一个命令是 M
。 M
从比喻意义上说,表示 *拿起笔并将其移动到 213.1, 6.7
的确切位置*。 现在还不要画任何东西,只是移动笔的位置。 因此,如果其他命令进行绘制,它现在将从该位置开始。
M
只是许多路径命令中的一种。 我数了一下,总共有 18 个。
许多(但不是全部)命令成对出现。 有一个 **大写** 版本和一个小写版本。 大写版本是 **绝对** 版本,小写版本是 **相对** 版本。 让我们继续以 M 为例
M 100,100
表示“拿起笔并将其移动到 100,100 的确切坐标”。m 100,100
表示“从当前位置将笔移动 100 向下,100 向右”。
许多命令都有相同的设置。 小写版本会考虑“笔”当前的位置。
让我们看一下两个绝对命令
然后是一个相对命令
就像 M
和 m
命令一样,L
和 l
接受两个数字:绝对或相对坐标。 还有另外四个命令本质上是线条命令的简化版本。 它们也绘制线条,但只接受一个值:水平或垂直。 当我们使用 l 25,0
时,我们可以使用 h 25
,它表示“从笔当前位置开始,向右绘制 25”。 我想,更简洁。 它的兄弟 H
,正如我们所料,表示绘制到确切的水平坐标 25。 V
和 v
分别向上和向下移动绝对位置和相对位置,正如您所料。
查看 Chris Nager 的这个演示,他用极少量的代码绘制了一个十字架,这得益于相对坐标绘制
看到 Chris 最后使用的字符了吗? Z
。 Z
(或 z
,这没关系)“关闭”路径。 与任何其他命令一样,它是可选的。 这是一个简单易行的方法,可以绘制一条直接回到“笔”最后放下位置(可能是最后一个 M
或 m
命令)的直线。 它可以节省您重复第一个位置并使用线条命令回到那里的麻烦。
让我们看看我们迄今为止涵盖的命令。
**M** x,y | 移动到 x,y 的绝对坐标 |
**m** x,y | 向右移动 x,向下移动 y(或向左和向上,如果值为负数) |
**L** x,y | 绘制一条到 x,y 的绝对坐标的直线 |
**l** x,y | 绘制一条到相对位置(向右移动 x,向下移动 y(或向左和向上,如果值为负数))的直线 |
**H** x | 绘制一条水平线到确切的坐标 x |
**h** x | 绘制一条相对于笔的水平线,向右移动 x(或向左移动,如果值为负数) |
**V** y | 绘制一条垂直线到确切的坐标 y |
**v** y | 绘制一条相对向下移动 y(或向上移动,如果值为负数)的垂直线 |
**Z**(或 **z**) | 绘制一条直线回到路径的起点 |
到目前为止,我们只看到了直线。 Path 对于直线来说是一个完全可以接受的元素和语法,尽管可以说,像 <line>
这样的元素对于直线形状可能具有更简单的语法,即使略微受限。
Path 的超能力是曲线! 有很多不同的类型。
记得我们看过的第一个示例代码使用了大量的 C
和 c
命令。 它们是“贝塞尔曲线”,需要更多数据才能完成它们的工作。
C 命令接受三个点。 前两个点定义了两个贝塞尔曲线控制柄的位置。 也许这个概念在 Adobe Illustrator 的钢笔工具等工具中很熟悉

最后三个点中的一个是曲线的终点。 曲线应该结束的位置。 这是一个插图
小写 c
命令完全相同,只是所有三个点都使用相对值。
S
(或 s
)命令与 C 命令是伙伴关系,因为它只需要 *两个* 点,因为它假定第一个贝塞尔点是最后一个 S 或 C 命令中使用的最后一个贝塞尔点的反射。
Q
命令是最简单的命令之一,因为它只需要两个点。 它想要的贝塞尔点是一个“二次”曲线控制点。 就像起点和终点都共享一个控制柄结束位置一样。
我们不妨同时介绍 T
。 它与 Q
是伙伴关系,就像 S
与 C
是一样。 当 T 出现在 Q 之后时,假定控制点是前一个控制点的反射,因此您只需要提供最终点。
A
命令可能是最复杂的命令。 或者至少需要最多的数据。 您需要提供定义椭圆宽度、高度和椭圆旋转方式的信息,以及终点。 然后是有关您希望路径沿着该椭圆走哪条路径的更多信息。 来自 MDN
路径有两种可能的椭圆,并且每个椭圆上有两种不同的可能路径,总共四种可能的路径。 第一个参数是大弧标志。 它只是确定弧度应该大于或小于 180 度; 最终,此标志决定了弧将在给定圆的哪个方向上移动。 第二个参数是扫掠标志。 它决定了弧线应该从负角度还是正角度开始移动,这实际上选择了你将绕行的两个圆中的哪一个。
Joni Trythall 的图形解释了来自 她关于 SVG 路径的文章 的 A,非常清晰

以下是这些曲线命令的文字解释。
**C** cX1,cY1 cX2,cY2 eX,eY | 根据 **两个** 贝塞尔控制点绘制一条贝塞尔曲线,并在指定坐标处结束 |
c | 所有值都为相对值 |
**S** cX2,cY2 eX,eY | 基本上是一个 C 命令,它假定第一个贝塞尔控制点是前一个 S 或 C 命令中使用的最后一个贝塞尔点的反射 |
s | 所有值都为相对值 |
**Q** cX,cY eX,eY | 根据 **单个** 贝塞尔控制点绘制一条贝塞尔曲线,并在指定坐标处结束 |
q | 所有值都为相对值 |
**T** eX,eY | 基本上是一个 Q 命令,它假定第一个贝塞尔控制点是前一个 Q 或 T 命令中使用的最后一个贝塞尔点的反射 |
t | 所有值都为相对值 |
**A** rX,rY rotation, arc, sweep, eX,eY | 绘制一条基于椭圆曲线的弧线。 首先定义椭圆的宽度和高度。 然后是椭圆的旋转。 连同终点,这将产生两个可能的椭圆。 因此弧线和扫掠要么是 0 要么是 1,并决定了哪个椭圆以及它将走哪条路径。 |
a | eX,eY 的相对值相同 |
想看一些例子吗? 好吧
如果您正在最近发布的基于 Blink 的浏览器中查看,并且您有鼠标,您会看到一些悬停动画! 事实证明,您现在可以在 CSS 中设置路径数据。 例如……
<svg viewBox="0 0 10 10">
<path d="M2,5 C2,8 8,8 8,5" />
</svg>
svg:hover path {
transition: d 0.2s;
d: path("M2,5 C2,2 8,2 8,5");
}
这个 SVG Path Visualizer 非常酷!

想了解更多关于 SVG 的信息吗? 我保证它真的非常酷。 我写了一整本书关于它。 它叫做 Practical SVG 而且它并不贵。
让浏览器动画化 d 属性太疯狂了!
但这也会给供应商特定的实现留下很多空间。
我希望它不会是一场血战。
目前,我看到 Blink 只有在顶点数量匹配的情况下才能动画化路径, *并且* 如果段是用相同的命令或它们的另一案例对应命令(例如“L”与“l”,但不是与“V”或“H”)生成的。
我为 canvas 写了一个类似的路径函数,它将相当冗长的路径语法缩减为更易于管理的内容
http://www.rgraph.net/blog/svg-style-paths-for-canvas-with-the-rgraph-path-function.html
这是打错了吗? 应该说“……第一个位置……”吗? (这是我对“关闭路径”命令的期望。)
没关系——我以为“笔最后放下位置”是指前一个命令,而不是第一个命令。
是的,这有点令人困惑。“笔最后放下位置”指的是最后一个 M/m 命令。 这很重要,因为您可以通过多个 M/m 命令创建多个不同的子路径,并且关闭路径会关闭最后一个子路径,它不会回到最开始。
简直是……震惊了我的大脑……
我不确定你从哪里获得的信息,但确实有一个使用小写
a
的相对弧命令。弧的终点相对于之前的终点。半径和标志参数不会改变。http://codepen.io/AmeliaBR/pen/42635482644f7e132aedece04ef8f3ac?editors=1100
此外,要感谢原作者:椭圆图形是来自原始 SVG 规范的一个副本。Joni 的参考对于许多其他事情来说很棒,但她并没有创建这个。
最后,请注意,目前在 Chrome 中实现的
d
CSS 属性的语法 **不是** 规范中的最终版本。当该功能在所有浏览器中稳定后,它应该只需要一个字符串,而不是path()
函数表示法。该函数意味着一个通用形状,这意味着可以使用 其他 CSS 形状函数,但浏览器还没有准备好这样做。我已经在 Chrome 上提交了一个错误来更新他们的实现,希望很快就会发生,这样 Web 作者就不必担心多种语法。如果你想立即使用它,也许可以添加两个版本。我们不希望 Chrome 无限期地维护对草案版本的支持!
除此之外:一个很棒、易于理解的解释!(就像这本书一样!)
我已经修正了 A/a 的问题。不确定我从哪里获得了“没有小写版本”的信息。
语法部分非常有趣。我想不出我脑海中的哪些属性使用“CSS 形状”。
Motion-path(将被重命名为
offset-path
)已经使用path()
,如下所示在查看显然已经采用特定语法的属性时,跳过 path() 更有意义。
关于
d
作为 CSS 属性的澄清(因为我从未明确说明)最终规范是让属性直接与属性匹配,除了值将是一个带引号的字符串。
如果你想尝试一下当前的 Chrome 实现,可以试试以下方法(理想情况下,使用预处理器混合来保持组织)
关于所有其他使用 CSS 形状函数的属性(clip-path、shape-outside、motion/offset-path)
在这些情况下,函数描述了一个完整的形状,任何形状都可以使用:圆形、椭圆形、多边形。
path(string)
语法仍然将在那里使用,并且应该在所有这些属性中可用。这样做的目的是,这些属性接受<shape-function>
数据类型。path()
函数只是定义了一个新的 shape-function。如果将来某个规范定义了octagon()
shape-function,它也将在所有接受形状的属性中可用。但是,
d
的处理方式类似于其他 SVG 形状的单个属性(x
、y
、cx
、cy
、r
等)。它们定义了 如何 绘制形状的参数的一部分,但它们并没有完全定义形状。完整的形状(无论你得到的是圆形、椭圆形、矩形还是路径)仍然由 SVG 元素类型决定。这不是理想的。我们正在进行 SVG 形状的 CSS 化,但还没有完全实现。最终,我想为 SVG 几何创建一个独立的逻辑 CSS 模型 (GitHub 讨论在此处)。但我们还没有达到那个阶段。
哦,还有 PS
points
用于多边形尚未 CSS 化。另一个不完整的项目。无法决定是遵循 SVG 语法(没有单位,并且对逗号和空格比较宽松),还是遵循polygon()
函数中使用的 CSS 语法。因此,我们没有做出糟糕的决定,而是没有对其进行规范,至少目前还没有。PS
SVG 2 中还有一些其他的酷炫路径功能即将推出,但目前还没有浏览器实现它们。
该 “方位角”命令(B 或 b) 将允许你旋转用于所有相对命令的基础角度。相对的
h
命令表示沿当前方位角前进(如果为负则后退),而相对的v
命令表示垂直于该角度移动。大写B
将方位角设置为精确角度,小写b
相对于前一个路径段的切线角度调整角度。因此,SVG 路径变得更像传统的“海龟”绘制命令。该 Z/z 命令 也将变得更加强大。它将能够自动完成曲线命令,这样你就可以始终确保曲线准确地连接回起点,而无需跟踪起点的精确坐标,并且无需插入零长度直线结束段(这在你使用线条标记时会导致问题)。
太棒的资源……谢谢!:)。我将我的徽标变成了 SVG,太棒了。我可以在任何设备、任何尺寸上使用它!
Chris,这篇文章真的太棒了,感谢你解释了 SVG 中我一直都不明白的一部分,我一直都在回避。我认为这需要创建一个生成随机 SVG 的 codepen 动画:D
我制作了这个 CodePen,它生成随机的 SVG 路径并将其相互变形,只是为了看看它会是什么样子
http://codepen.io/JeffSturgis/pen/GjPpoR