Overview
如果你曾经看过一个 icon 的 SVG 代码,你可能会注意到他们通常是有一个 <path> 元素和一个神秘的 d 属性实现的。
你可能以为他们不过是设计师最喜欢的矢量图形编辑器的输出,虽然可能是正确的,但有些过度简化了。
理解这个属性的内部运作机制将是前端技能的一大助力,它让你能够做到以前从未想过的事情,比如制作弯曲的动画。
这份指南将会谈到 d 属性,也被称为 path data。
A Path is a Series of Commands 路径是一系列命令
d 属性实际上是一系列命令,告诉浏览器如何绘制 path,如果将属性内容规范一下,将会是下面这样:
M 12.0 7.2
C 10.5 5.6 8.1 5.2 6.3 6.7
C 4.5 8.1 4.2 10.6 5.7 12.4
L 12.0 18.3
L 18.3 12.4
C 19.7 10.6 19.5 8.1 17.7 6.7
C 15.8 5.2 13.4 5.6 12.0 7.2
Z为了绘制出 path,浏览器按照顺序执行这些命令,每个命令绘制一小部分。 所有的 path 命令都遵循同样的语法,单个字母 + 一系列数字,字母代表命令类型,二数字则是命令的参数。
可以将命令理解为函数调用,字母是函数名称,数字是函数参数:
M(12, 7.2);Absolute and Relative Commands 绝对与相对命令
命令代码既可以是大写,也可以是小写。
- 大写的是绝对的,代表其命令参数是相对于原始的点
(0, 0)。 - 小写的是相对的,代表其命令参数是之前命令的端点。
例如下面命令
M 10.0 10.0 # move
L 5.0 5.0 # line
M 10.0 10.0 # move
l 5.0 5.0 # line这里有两条从 (10, 10) 开始的直线,参数都为 (5, 5)
L命令的线在(5, 5)结束l命令的线在(10, 10)结束
Curors
SVG path 的核心是 cursor。 所有的 path 命令都使用 cursor 决定从哪里开始绘制,并且所有 path 命令都会移动光标,以确保下一条命令移动的起始位置。
考虑下面命令
M 5.0 5.0 # move
v 5.0 # relative vertical line
L 10.0 15.0 # move
h 5.0 #relative vertical line一开始 cursor 在左上角的 (0, 0),然后后面三条命令将 cursor 移动:(5, 5) -> (5, 10) -> (10, 15) -> (15, 15)。
一般来说光标会停在当前 path 结束的地方,毕竟大多数时候你希望路径连接起来。 当前路径的结束位置取决于是 absolute (绝对) 还是 relative (相对)。
- 对于 absolute commands,cursor 将会在命令的
(x, y)处结束。例如,L 10 15将会移动到(10, 15),无论光标现在的位置在哪里PLAINTEXTM 5.0 5.0 L 10.0 10.0 - 对于 realtive commands,cursor 将会在当前位置加上命令参数
(dx, dy)处结束。例如,当前 cursor 在(15, 5)然后l 10 15会将光标移动到(25, 40)PLAINTEXTM 15.0 5.0 l 10.0 15.0
Move Command
该命令只会移动 cursor 并不会绘制任何东西
M <x> <y>
m <dx> <dy>当你想要绘制不相连的路径的时候,这个命令十分有用
M 3.0 5.5 # move
q 2.0 2.0 0.0 4.0 # relative quadratic curve
m 3.0 -6.0 # relative move
q 4.0 4.0 0.0 8.0
m 3.0 -10.0
q 4.0 6.0 0.0 12.0Lines
上面介绍了 cursor 光标,现在来进行绘制。
首先是直线,l 命令绘制一条从当前 cursor 开始,到 (x, y) 结束的直线。
M 5.0 5.0
l 15.0 10.0和 m 命令移动 cursor 一样移动,但是会绘制一条直线。
Vertical and Horizontal Lines
还可以使用 H 和 V 命令绘制具体方向的线条,H 绘制水平线,V 绘制竖线。
M 13.0 5.0
h -6.0
V 15.0
H 13.0
M 7.0 10.0
h 4.0上面命令绘制了一个字母 E 形状的图形,中间略短。
The Close Path Command
最后一个类型的线条命令是 close path command z,这条命令从当前的 cursor 命令开始,到 path 起始的位置结束,绘制一条直线。即无需显式去闭合图形,直接使用 Z 命令就行了。
M 10.0 5.0
l -5.0 10.0
h 10.0
Z上面命令绘制了一个三角形。
有趣的是,Z 命令的确有一个小写的相对命令,但是由于该命令没有任何参数,因此两个命令的效果都相同。
Z 做的闭合不仅是加了一条线而已,例如下面这个爱心的例子
M 11.995 7.23319
C 10.5455 5.60999 8.12832 5.17335 6.31215 6.65972
C 4.4959 8.14609 4.2403 10.6312 5.66654 12.3892
L 11.995 18.25
L 18.3235 12.3892
C 19.7498 10.6312 19.5253 8.13046 17.6779 6.65972
C 15.8305 5.18899 13.4446 5.60999 11.995 7.23319这个心的 icon 中,起始和结束都是 (11.995, 7.23319) 但实际上如果仔细观察连接处,就会发现这里的两条曲线交汇处会有部分不自然的连接,如果最后再加上 Z 就能让两跳曲线更加自然地闭合。
Curves
实际上,如果只使用直线的话,只用 <line /> 元素是就行了,SVG path 真正的强大之处是能够绘制曲线,因此下面来探讨曲线。
在 SVG path 中有 3 种绘制的曲线:quadratic bezier curves, cube berizer curves 和 arcs.
Beizer Curves
Beizer curve 是由一系列叫做 control points 的控制点定义的。 SVG path 支持两类 beizer curves:
- quadratic beizer curves, 该曲线只有一个控制点
- cubic beizer curves, 该曲线有两个控制点
控制点越多,曲线也就越复杂
Quadratic Curves
虽然 cube beizer curves 更加灵活,但当不需要更加复杂形状的时候,quadratic beizer curves 更加容易使用
使用命令 Q 绘制曲线该
Q controlX controlY endX endY例如这条曲线,创建了一个圆角
M 5.0 5.0
v 5.0
Q 5.0 15.0 15.0 15.0
h 5.0Chaining Quadratic Curves
如果想要写多个连续的二次曲线,可以这样实现
Q 5 10 10 10
Q 15 10 15 15但实际上有更好的实现该功能的方法 - 即使用 T 命令
M 5.0 5.0
Q 5.0 10.0 10.0 10.0
T 15.0 15.0T 命令将使用之前曲线控制点的反射绘制一条新的曲线。
修改前面曲线的控制点,也会导致后面曲线的控制点被修改,从而影响整个曲线的样式。
Cubic Curves
二次曲线很好,但十分具有局限性,例如下面这个药丸形状的图形,使用二次曲线看起来就不太对(两侧很尖)。
M 5.0 5.0
h 5.0
q 5.0 2.5 0.0 5.0
h -5.0
q -5.0 -2.5 0.0 -5.0
Z但如果将二次曲线换成三次曲线,看起来就顺滑多了:
M 5.0 5.0
h 5.0
c 4.0 0.0 4.0 5.0 0.0 5.0 h -5.0
c -4.0 0.0 -4.0 -5.0 0.0 -5.0
Z如果能对曲线有更多的控制,就能让曲线看起来更好看。
Syntax
绘制一个三次曲线,使用 C 命令:
C x1 y1 x2 y2 x y前面两对是两个控制点的位置,最后一对是曲线结束点的位置。
可以将三次曲线看成二次曲线的推广,任何二次曲线都可以通过三次曲线表示。 有趣的是,当三次曲线的两个控制点重合的时候,其对应控制点的二次曲线与其并不是同一条曲线。
Multiple Beizer Curves
就像二次曲线可以使用 T 命令连接一样,三次曲线可以使用 S 命令连接在一起。
S 的语法是第二条控制点的位置和最后曲线端点的位置:
S x2 y2 x yArcs
最后一个但同样重要的是 A arc command 弧命令。
弧命令使用下面语法绘制椭圆的一部分:
A rx ry rotation large-arc-flag sweep-flag x y- 开始的
(rx, ry)定义了椭圆的半径:横和竖的长度 - 最后的
(x, y)是从当前点开始,曲线结束的位置
为了绘制出曲线,浏览器会根据当前点位置,以及上面两个位置,找到一个符合该位置的椭圆:也就是说,一个半径为 rx 和 ry 的椭圆,且保证当前点和 (x, y) 都在圆周上。
当没法找到合适椭圆的时候,椭圆不够大无法容纳所有点,会隐式的将椭圆按比例放大,使曲线仍然遵循椭圆(只是这个椭圆比指定的大)。
x-axis-rotation是水平 x 肘方向顺时针的偏移角度(水平半径偏移)。large-arc-flag和sweep-flag是两个标志,都只能是 0 或 1,这两个标志控制绘制匹配上的椭圆的哪一部分。因为每两个点直接实际上可以匹配到两个椭圆,每个椭圆又有两个部分,使用这两个 flag 来控制。- large-arc-falg 控制绘制同一个方向上的哪个弧,0 代表小的,1 代表大的
- sweep 控制哪个方向的被绘制,0 代表逆时针绘制,1 代表顺时针绘制
最后给一个绘制指纹图案的例子
M 3.0 15.0
q 1.5 -2.0 1.5 -5.0
q 0.0 -2.0 1.5 -4.0
M 8.0 4.0
a 8.0 8.0 0.0 0.0 1.0 12.0 6.0
q 0.5 4.0 -2.0 9.0
M 13.0 21.0
q 1.5 -2.0 2.0 -5.0
M 16.0 12.0
v -1.0
a 4.0 4.0 0.0 0.0 0.0 -8.0 0.0
q 0.0 4.0 -2.5 7.0
M 8.5 20.0
q 3.0 -3.0 3.5 -9.0Summary
Ok, 这就是对 SVG 图像绘制的总结,下面给几个常用的示例。
- 点赞
<div class="ds-icon" style="font-size: 16px; width: 16px; height: 16px;">
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.27861 0.811633
C8.81985 0.142255 9.79016 0.0422445 10.4537 0.557662
L10.5823 0.669367
L10.6065 0.693605
L10.6097 0.695713
L10.6392 0.72522
C11.3549 1.44685 11.6336 2.49474 11.3716 3.47675
L11.3705 3.48097
L11.361 3.5168
L11.36 3.51891
L10.8889 5.2261
C10.8796 5.26003 10.8706 5.29164 10.8626 5.32094
C10.8934 5.32101 10.927 5.322 10.9627 5.322
H11.9006
C12.4263 5.322 12.783 5.31906 13.0651 5.36731
C14.8182 5.66725 15.9851 7.34574 15.6564 9.09363
C15.6035 9.37493 15.4769 9.70926 15.2939 10.2023
L14.337 12.7799
C14.1401 13.3105 13.9773 13.7518 13.8101 14.1025
C13.6375 14.4646 13.4385 14.7794 13.1441 15.0425
C12.9712 15.197 12.7801 15.3303 12.5751 15.4387
C12.2259 15.6232 11.8608 15.7 11.4612 15.7359
C11.0742 15.7705 10.6034 15.7696 10.0374 15.7696
H4.87371
C4.08047 15.7696 3.42922 15.7703 2.90728 15.7138
C2.37206 15.6558 1.88985 15.5311 1.4667 15.2237
C1.22409 15.0475 1.01072 14.834 0.834405 14.5914
C0.52696 14.1683 0.401312 13.6861 0.343323 13.1509
C0.286761 12.6288 0.28747 11.977 0.28747 11.1834
V9.51411
C0.28747 8.84785 0.281286 8.36721 0.399176 7.95656
C0.671091 7.00941 1.41109 6.26838 2.35823 5.99645
C2.76888 5.87855 3.24952 5.88579 3.91579 5.88579
C4.11977 5.88579 4.14542 5.88325 4.16238 5.88053
C4.23526 5.8687 4.30403 5.83669 4.35839 5.78674
C4.37104 5.77511 4.38755 5.7561 4.51436 5.59494
L8.25648 0.839033
L8.25754 0.837979
L8.27861 0.811633Z
M1.69116 11.1834
C1.69116 12.0083 1.69211 12.5712 1.73859 13.0002
C1.78365 13.4158 1.86467 13.6222 1.96937 13.7663
C2.05914 13.8898 2.16727 13.999 2.29079 14.0888
C2.43495 14.1935 2.6421 14.2745 3.05797 14.3195
C3.45891 14.363 3.97631 14.3656 4.71564 14.3659
C4.30795 13.8053 4.06447 13.1172 4.06437 12.371
V8.59412H5.46807
V12.371
C5.46832 13.4734 6.3616 14.367 7.46401 14.367
H10.0374
C10.6286 14.367 11.0269 14.3663 11.3368 14.3385
C11.6339 14.3118 11.7956 14.2639 11.9196 14.1984
C12.024 14.1431 12.1213 14.0747 12.2094 13.996
C12.3139 13.9025 12.4151 13.7679 12.5434 13.4986
C12.6774 13.2177 12.8162 12.8451 13.0219 12.2909
L13.9787 9.71328
C14.1848 9.15822 14.253 8.96737 14.278 8.83439
C14.4617 7.85698 13.8092 6.91901 12.829 6.75098
C12.6956 6.72816 12.4928 6.72464 11.9006 6.72464
H10.9627
C10.7737 6.72464 10.5693 6.72663 10.4 6.70672
C10.2211 6.68568 9.96696 6.6303 9.74764 6.43167
C9.64448 6.33817 9.5595 6.22616 9.49683 6.10183
C9.36384 5.8379 9.37793 5.57905 9.40515 5.40104
C9.43094 5.23267 9.48666 5.03623 9.53688 4.8541
L10.0079 3.14585
L10.0174 3.11108
C10.1488 2.61344 10.0077 2.08344 9.64648 1.71687
L9.60854 1.67893
L9.55058 1.6431
C9.48789 1.62049 9.41419 1.6382 9.36932 1.69368
L9.35773 1.70633
L9.35878 1.70738
L5.61666 6.46224
C5.51816 6.58741 5.42231 6.71336 5.30683 6.81948
C5.05069 7.05477 4.73119 7.20945 4.3879 7.26525
C4.23309 7.29038 4.07507 7.28843 3.91579 7.28843
C3.1535 7.28843 2.9191 7.29576 2.74604 7.34534
C2.26358 7.48385 1.88558 7.86087 1.74702 8.34331
C1.69732 8.51642 1.69116 8.75116 1.69116 9.51411
V11.1834Z"
fill="currentColor"
></path>
</svg>
</div>- 点踩
<div class="ds-icon" style="font-size: 16px; width: 16px; height: 16px;">
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.72451 15.1086C7.18929 15.7706 6.22975 15.8695 5.57357 15.3598L5.44643 15.2493L5.42247 15.2253L5.41934 15.2233L5.39016 15.1941C4.68239 14.4805 4.40679 13.4442 4.66589 12.4731L4.66693 12.4689L4.67631 12.4335L4.67735 12.4314L5.14318 10.7432C5.15243 10.7096 5.1613 10.6784 5.16923 10.6494C5.13878 10.6493 5.10558 10.6484 5.07023 10.6484H4.14274C3.62288 10.6484 3.27015 10.6513 2.9912 10.6035C1.25757 10.3069 0.103662 8.64709 0.42863 6.91861C0.480965 6.64044 0.606164 6.30981 0.787119 5.8223L1.73336 3.27328C1.92812 2.74859 2.08912 2.31215 2.25442 1.96542C2.42515 1.60731 2.62191 1.296 2.91304 1.03584C3.08408 0.883016 3.273 0.751185 3.47579 0.644009C3.82102 0.461569 4.18214 0.385575 4.57731 0.350131C4.95993 0.315849 5.42553 0.316783 5.98521 0.316783H11.0916C11.876 0.316783 12.52 0.316134 13.0362 0.372015C13.5655 0.429358 14.0423 0.552599 14.4608 0.856601C14.7007 1.03091 14.9117 1.24199 15.086 1.48187C15.3901 1.90033 15.5143 2.37716 15.5717 2.90645C15.6276 3.42275 15.6269 4.06727 15.6269 4.85209V6.5028C15.6269 7.16167 15.633 7.63697 15.5164 8.04306C15.2475 8.97969 14.5158 9.71248 13.5791 9.9814C13.173 10.098 12.6977 10.0908 12.0389 10.0908C11.8372 10.0908 11.8118 10.0933 11.795 10.096C11.723 10.1077 11.6549 10.1394 11.6012 10.1888C11.5887 10.2003 11.5724 10.2191 11.447 10.3784L7.74639 15.0815L7.74535 15.0826L7.72451 15.1086ZM14.2388 4.85209C14.2388 4.03635 14.2379 3.47971 14.1919 3.05547C14.1473 2.64449 14.0672 2.44037 13.9637 2.29785C13.8749 2.17569 13.768 2.06776 13.6458 1.97896C13.5033 1.87539 13.2984 1.7953 12.8872 1.75074C12.4907 1.70779 11.979 1.70518 11.2479 1.70489C11.6511 2.25924 11.8918 2.93974 11.8919 3.67762V7.41257H10.5038V3.67762C10.5036 2.58751 9.62023 1.70384 8.53007 1.70384H5.98521C5.40065 1.70384 5.00679 1.70449 4.70028 1.73198C4.40651 1.75836 4.24662 1.80577 4.12399 1.87058C4.02069 1.92518 3.92452 1.99283 3.8374 2.07067C3.73401 2.16312 3.634 2.29627 3.50705 2.56255C3.37462 2.84034 3.23734 3.2088 3.03393 3.75682L2.08768 6.30584C1.88395 6.85474 1.81646 7.04347 1.79172 7.17497C1.61005 8.14152 2.25533 9.06908 3.22464 9.23524C3.35654 9.25781 3.55717 9.26129 4.14274 9.26129H5.07023C5.25717 9.26129 5.4593 9.25932 5.62672 9.27901C5.80364 9.29982 6.05492 9.35458 6.27179 9.551C6.37381 9.64347 6.45784 9.75424 6.51982 9.87719C6.65133 10.1382 6.6374 10.3942 6.61048 10.5702C6.58498 10.7367 6.52988 10.931 6.48022 11.1111L6.01439 12.8003L6.00501 12.8347C5.87513 13.3268 6.01464 13.8509 6.37184 14.2134L6.40935 14.251L6.46667 14.2864C6.52866 14.3088 6.60155 14.2912 6.64591 14.2364L6.65738 14.2239L6.65633 14.2228L10.3569 9.52078C10.4543 9.397 10.5491 9.27245 10.6633 9.1675C10.9166 8.93483 11.2325 8.78186 11.572 8.72669C11.7251 8.70184 11.8814 8.70376 12.0389 8.70376C12.7927 8.70376 13.0245 8.69651 13.1956 8.64748C13.6727 8.51051 14.0465 8.13768 14.1836 7.6606C14.2327 7.48941 14.2388 7.25727 14.2388 6.5028V4.85209Z"
fill="currentColor"
></path>
</svg>
</div>- 填充的赞
<div class="ds-icon" style="font-size: 16px; width: 16px; height: 16px;">
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.0593 12.922L15.0976 10.1247C15.3088 9.55596 15.4144 9.27144 15.4567 9.04665C15.7349 7.56758 14.7472 6.14744 13.2638 5.89363C13.0383 5.85506 12.7349 5.85506 12.1281 5.85506H11.11C10.6615 5.85506 10.4373 5.85506 10.3034 5.73382C10.2607 5.69514 10.2255 5.64892 10.1996 5.59746C10.1183 5.43619 10.1779 5.22003 10.2971 4.78771L10.8082 2.93426L10.819 2.89463C11.0336 2.0903 10.8052 1.23251 10.219 0.641455L10.1899 0.61247L10.1692 0.592133C9.77363 0.210141 9.13565 0.249409 8.7899 0.677031L8.77192 0.699743L4.71082 5.8609C4.52971 6.09107 4.38579 6.35144 4.38579 6.64433V12.7432C4.38579 14.3601 5.6966 15.6709 7.31357 15.6709L10.1068 15.6709C11.3628 15.6709 11.9908 15.6709 12.5044 15.3996C12.6724 15.3108 12.8289 15.2019 12.9706 15.0753C13.4037 14.6883 13.6223 14.0995 14.0593 12.922Z"
fill="currentColor"
></path>
<path
d="M2.91394 13.2114C2.91394 14.6907 4.08505 15.5536 4.08505 15.5536H2.65612C1.46334 15.5536 0.496399 14.5867 0.496399 13.3939V8.34446C0.496399 7.15168 1.46334 6.18473 2.65612 6.18473H2.91394V13.2114Z"
fill="currentColor"
></path>
</svg>
</div>- 填充的踩
<div class="ds-icon" style="font-size: 16px; width: 16px; height: 16px;">
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.92844 3.06818L0.888051 5.87111C0.67651 6.44103 0.570689 6.72612 0.528311 6.95137C0.249475 8.43343 1.23916 9.85643 2.72561 10.1107C2.95155 10.1494 3.25555 10.1494 3.86354 10.1494H4.88377C5.33312 10.1494 5.5578 10.1494 5.69193 10.2709C5.73473 10.3096 5.77 10.356 5.79599 10.4075C5.87745 10.5691 5.81772 10.7857 5.69827 11.2189L5.18615 13.0761L5.17529 13.1158C4.96026 13.9218 5.18916 14.7813 5.77656 15.3735L5.80574 15.4026L5.82641 15.4229C6.2228 15.8057 6.86206 15.7664 7.20852 15.3379L7.22653 15.3151L11.2958 10.1435C11.4773 9.91291 11.6215 9.65202 11.6215 9.35854V3.24741C11.6215 1.62718 10.3081 0.313722 8.68782 0.313722L5.88892 0.313721C4.63038 0.313721 4.00111 0.313721 3.48655 0.585644C3.31822 0.674603 3.16133 0.783714 3.01935 0.910574C2.58537 1.29835 2.36639 1.88831 1.92844 3.06818Z"
fill="currentColor"
></path>
<path
d="M13.0963 2.77822C13.0963 1.29591 11.9229 0.431271 11.9229 0.431271H13.3547C14.5499 0.431271 15.5187 1.40017 15.5187 2.59535V7.65498C15.5187 8.85017 14.5499 9.81906 13.3547 9.81906H13.0963V2.77822Z"
fill="currentColor"
></path>
</svg>
</div>