7

svg中path贝塞尔曲线和圆弧图文详解

 1 year ago
source link: https://www.joynop.com/p/475.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近研究了一下svg的path标签,功能非常强大,理论上来讲path标签可以画出任意图形。自己记性不太好,记录一下path的使用语法和自己的理解。

path介绍

pathd属性来描述路径,语法格式大概如下:

<svg>
    <path d="路径描述" />
</svg>

其中路径描述包含如下命令:

M = moveto 移动到某点。
L = lineto 画一条直线到某点。
H = horizontal lineto 画一条水平线到某点。
V = vertical lineto 画一条垂直线到某点。
Q = quadratic Bézier curveto 二次贝塞尔曲线
T = smooth quadratic Bézier curveto 平滑二次贝塞尔曲线
C = curveto 三次贝塞尔曲线
S = smooth curveto 平滑三次贝塞尔曲线
A = elliptical Arc 弧形
Z = closepath 从结束点到开始点画一条直线,形成一个闭合的区域。

以上所有命令均允许小写字母:

1. 大写表示绝对定位,绝对的参照点是svg最上角的那一点。
2. 小写表示相对定位,相对的参照点是上一个位置。

每个命令都有自己相关的参数,参考下面介绍。

M(moveto)移动和L(lineto)画直线

其中 M 表示移动到某点,L 表示画一条直接到某点,后面跟一个坐标点,格式如下:

d="M x y" // M是命令:x横轴坐标、y纵轴坐标
d="L x y" // L是命令:x横轴坐标、y纵轴坐标

网上很多文章有各种各样的格式,如:

Mx y
M x y    // 建议是用这种比较容易看,多个坐标用英文逗号,分隔
Mx,y
M x,y 

简单示例:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 20 30         // 移动到 (20 30) 这个点
        L 180 120     // 画一条直线到 (180 120) 这个点
    " stroke="pink" fill="none"></path>
</svg>

运行效果:

1.jpeg

H(horizontal lineto)水平线和V(vertical lineto)垂直线

其中H用于画水平线,y值和上一个点保持不变,所以给x值就可以了,格式如下:

d="H x" // H是命令:x横轴坐标

其中V用于画垂直线,x值和上一个点保持不变,所以给y值就可以了,格式如下:

d="V y" // V是命令:y纵轴坐标

简单示例:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 10 10        // 移动到 (10 10)这个点
        H 190            // 画水平线到 (190 10) 这个点
        V 140            // 画垂直线到 (190 140) 这个点
    " stroke="cadetblue" fill="pink"></path>
</svg>

运行效果:

2.jpeg

Z(cloasPath)闭合

结束点到开始点画一条直线,形成一个闭合的区域。前面的命令都和英文单词相关,这个命名和单词无关,估计是C命令给占用了。

语法格式就是在d属性最后写一个Z,表示闭合。

d="... Z"

接上面的例子,画一个闭合线,然后改一下轮廓颜色和填充色:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 10 10        // 移动到 (10 10) 这个点
        H 190            // 画水平线到 (190 10) 这个点
        V 140            // 画垂直线到 (190 140) 这个点
        Z                    // 闭合
    " stroke="cadetblue" fill="pink"></path>
</svg>

运行效果:

3.jpeg

Q(quadratic Bézier curveto)二次贝赛尔曲线

d="Q x1 y1, x y" // 控制点 (x1,y1),终点 (x,y)

简单示例:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 10 10                      // 移动到 (10 10) 这个点
        Q 100 70, 190 10        // 控制点 (100 70),终点 (190 10)
    " stroke="pink" fill="none"></path>

    <!-- 辅助查看的线(斜率) -->
    <path d="
        M 10 10
        L 100 70
        L 190 10
    " stroke="#888" stroke-dasharray="5" fill="none"></path>
</svg>

运行效果:

4.jpeg

图中黑色线就是实际画的贝塞尔曲线,虚线是斜率。

T(smooth quadratic Bézier curveto) 二次贝塞尔曲线

T命令只需要设置一个终点,它的控制点是通过前一个Q命令或者是T命令计算出来。

d="Q命令 T x y"     // 终点 (x y),控制点通过前面的Q命令计算得出

简单示例:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 10 75                    // 移动到 (10 75) 这个点
        Q 55 10 100 75    // 控制点 (55 10),终点 (100 75)
        T 190 75                // 终点 (190 75),控制器是通过前面Q命令计算出来的
    " stroke="black" fill="none"></path>
    
    <!-- Q命令辅助查看线(斜率) -->
    <path d="
        M 10 75
        L 55 10
        L 100 75
    " stroke="blue" stroke-dasharray="5" fill="none"></path>
    <!-- T命令辅助查看线(斜率) -->
    <path d="
        M 100 75
        L 145 140
        L 190 75
    " stroke="pink" stroke-dasharray="5" fill="none"></path>
</svg>

运行效果:

5.jpeg
黑色色是实际画出的贝塞尔曲线。
蓝色虚线是Q命令的斜率。
粉色虚线是T命令的斜率,其中控制点是电脑计算的。

C(curveto)三次贝塞尔曲线

三次贝塞尔曲线和二次贝塞尔曲线相比就是多一个控制点,MDN画的一个图很好的表达了这个意思:

6.jpeg

通过两个控制点,可以画出任意的曲线。语法格式:

d="C x1 y1, x2 y2, x y" // 控制点1 (x1,y1),控制点2 (x2,y2),终点 (x,y)

简单示例:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 10 10                                 // 移动到(10 10) 这个点
        C 20 130, 160 130, 170 20        // 控制点1(20 130),控制点2(160 130),终点(170 20)
    " stroke="black" fill="none"></path>
    
    <!-- C命令辅助查看的线(斜率) -->
    <path d="
        M 10 10 
        L 20 130
        M 160 130
        L 170 20
    " stroke="blue" fill="none" stroke-dasharray="5"></path>
</svg>

运行效果:

7.jpeg

S(smooth curveto) 平滑三次贝塞尔曲线

这个东西和T命令类似,T是Q的简写方式,S是C的简写方式,为了方便对比,我们把C和S的命令格式放在一起。

d="C x1,y1 x2,y2 x,y" // 控制点1 (x1,y1),控制点2 (x2,y2),终点 (x,y)
d="S x2,y2 x,y"             // S只要控制点2就可以了

简单示例,为了方便查看,我们同样画出辅助线:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 10 75 
        C 30 10, 80 10, 100 75    // 控制点1(30 10),控制点2(80 10),终点(100 75)
        S 170 140, 190 75    // 控制点2(190 75),终点(190 75)
    " stroke="black" fill="none"></path>

    <!-- C命令辅助查看的线(斜率) -->
    <path d="
        M 10 75
        L 30 10
        M 80 10
        L 100 75
    " stroke="blue" fill="none" stroke-dasharray="5"></path>
    <!-- S命令辅助查看的线(斜率) -->
    <path d="
        M 100 75
        L 120 140
        M 170 140
        L 190 75
    " stroke="pink" fill="none" stroke-dasharray="5"></path>
</svg>

运行效果:

8.jpeg
粉丝的虚线就是S的辅助线。
120 140这个点就是电脑计算出来的。

A(elliptical Arc)弧形

A命令也可以用来画弧形,可以理解是圆或者椭圆的一部分。

语法格式如下:

d="A rx ry x-axis-rotation large-arc-flag sweep-flag x y" 
rx ry 分别是是椭圆的x轴半径和y轴半径。
x-axis-rotation 是椭圆相对于坐标系的旋转角度。
large-arc-flag 是标记绘制大弧(1)还是小弧(0)部分。
sweep-flag 是标记向顺时针(1)还是逆时针(0)方向绘制。
x y 是圆弧终点的坐标。

rxrx容易理解,最后的重点xy也容易理解,关键就是中间三个参数:x-axis-rotationlarge-arc-flagsweep-flag 比较难以理解。

large-arc-flag 和 sweep-flag 参数

这边先突破一下 large-arc-flagsweep-flag 两个参数,每个参数都有两个值,那么组合来看就是4种情况,下面挨个情况看看。

1) large-arc-flag=0(小弧),sweep-flag=0(逆时针)。

我们先看其中都为0的情况:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <!-- 黑色圆弧  -->
    <path d="
        M 120 45 
        A 60 45 0 0 0 80 125  // large-arc-flag=0(小弧),sweep-flag=0(逆时针)
    " stroke="black" fill="none"></path> 
</svg>

运行效果:

9.jpeg

这边还不容易看出其中意思,为什么是画出这样的线呢?规律到底是什么呢?我们再看下都是1的情况。

2) large-arc-flag=1(大弧),sweep-flag=1(顺时针)。

增加一条弧线,和上例的的弧线一致,就是调整一下这两个参数:

large-arc-flag=1(大弧),sweep-flag=1(顺时针)

然后把颜色设置为蓝色:

<!-- 蓝色圆弧  -->
<path d="
    M 120 45 
    A 60 45 0 1 1 80 125 // large-arc-flag=1(大弧),sweep-flag=1(顺时针)
" stroke="blue" stroke-dasharray="2" fill="none"></path>

运行效果:

10.jpeg

这下就有点清楚了,就是一个椭圆上的两个点可以顺时针画大弧,也可以逆时针画小弧,两个弧组合成一个椭圆了。

那另外两组参数是什么意思呢?再一起来看看。

3) large-arc-flag=0(小弧),sweep-flag=1(顺时针)。

再增加一条弧线,和上例的的弧线一致,就是调整一下这两个参数:

large-arc-flag=0(小弧),sweep-flag=1(顺时针)

然后把颜色设置为粉色:

<!-- 粉色圆弧  -->
<path d="
    M 120 45 
    A 60 45 0 0 1 80 125 // large-arc-flag=0(小弧),sweep-flag=1(顺时针)
" stroke="pink" stroke-dasharray="4" fill="none"></path> 

运行效果:

11.jpeg

到这边就更加清晰了,粉色圆弧实际和黑色圆弧对称。

剩下最后估计就能猜到了,补上最后一个。

4) large-arc-flag=1(大弧),sweep-flag=0(逆时针)。

再增加一条弧线,和上例的的弧线一致,就是调整一下这两个参数:

large-arc-flag=1(大弧),sweep-flag=0(逆时针)

然后把颜色设置为深粉色:

<!-- 深粉色圆弧  -->
<path d="
    M 120 45 
    A 60 45 0 1 0 80 125 // large-arc-flag=1(大弧),sweep-flag=0(逆时针)
" stroke="deeppink" stroke-dasharray="6" fill="none"></path>

运行效果:

12.jpeg

这边两个参数就介绍完了。

x-axis-rotation

这个参数就是用来旋转用的,可以为正和负数:

整数表示顺时间旋转。
负数表示逆时针旋转。

我们把上面的例子做一下旋转,顺时针旋转30度:

<svg width="200" height="150" style="border:1px solid steelblue;">
    <!-- 黑色圆弧  -->
    <path d="
        M 120 45 
        A 60 45 30 0 0 80 125 
    " stroke="black" fill="none"></path>

    <!-- 蓝色圆弧  -->
    <path d="
        M 120 45 
        A 60 45 30 1 1 80 125
    " stroke="blue" stroke-dasharray="2" fill="none"></path>

    <!-- 粉色圆弧 -->
    <path d="
        M 120 45 
        A 60 45 30 0 1 80 125
    " stroke="pink" stroke-dasharray="4" fill="none"></path>

    <!-- 深粉色圆弧  -->
    <path d="
        M 120 45 
        A 60 45 30 1 0 80 125
    " stroke="deeppink" stroke-dasharray="6" fill="none"></path>
</svg>

运行效果:

13.jpeg

逆时针也是一样的道理,就是不再演示了。

前面演示的例子,都是绝对位置,相对位置也很简单,写个例子看看就明白了。我们用最开始画线的例子,然后改成相对定位。

<!-- 绝对定位 -->
<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 20 30 
        L 180 120
    " stroke="pink" fill="none"></path>
</svg>

这边的L是绝对位置 180 120,是相对于svg左上角的坐标0 0,那么相对的写法就是:

L点坐标(180 120) - M点坐标(20 30)
= 相对位置(160 90)

再颜色修改成深粉色,方便看出效果,最后给出代码:

<!-- 相对定位 -->
<svg width="200" height="150" style="border:1px solid steelblue;">
    <path d="
        M 20 30
        l 160 90 // 相对定位
    " stroke="deeppink"></path>
</svg>

运行效果:

14.jpeg

其它命令的原理都是类似的,就不再赘述了。

至此path相关的命令就介绍完毕了,欢迎大家一起学习交流。

MDN svn路径:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK