svg的path的应用

37次阅读

共计 2284 个字符,预计需要花费 6 分钟才能阅读完成。

用 svg 的 path 标签可以画出任何你想画的图像
这里有一篇详细的指南,有兴趣的可以看下:svg 的 path
这里再引用一位博主写的不错的文章:SVG 之 path

path 标签的 d 属性的命令有

  • M = moveto
  • L = lineto
  • H = horizontal lineto
  • V = vertical lineto
  • C = curveto
  • S = smooth curveto
  • Q = quadratic Bézier curve
  • T = smooth quadratic Bézier curveto
  • A = elliptical Arc
  • Z = closepath

我们这里只要用到 M L A 和 Z 命令就可以了,M L 和 Z 命令比较简单,这里详细讲解 A 命令,A 命令是画弧的命令,里面的 A 命令有 7 个参数:rx ry x-axis-rotation large-arc-flag sweep-flag x y
rx ry 表示椭圆的 x 半径和 y 半径,两个一样画出来的就是圆,最后两个的参数 x y 表示的是终点坐标,接下来的三个参数比较复杂,这里开始详细讲解:
我们来看一张图:
图中的两个点 Arc start 和 Arc end 是起始点和终止点,假设我们已经知道,通过这两个点和半径可以得出两个椭圆,四条弧,那该怎样确定用那条弧呢?在起始点和终止点之间连一条线,在线的左半部分 sweep-flag 的值为 0,在右边为 1,而当 large-arc-flag 为 1 时表示取的是大弧,为 0 就表示取小弧,这两个参数的四种取值就可以分别取出这四条弧。large-arc-flag(约定名称叫大弧,下文也这么叫)= 0 就表示取图中 B 和 C 的两条加黑的小弧,而 sweep-flag(约定名称叫镜像,下文也这么叫)= 0 表示取 B 中的那条小弧,等于 1 表示取图 C 中的那条,(大弧,镜像)的四种取值:(0,0)、(0,1)、(1,0)、(1,1)就分别对应图中的 B、C、D、E。x-axis-rotation 表示的就是 x 轴的旋转角度,如图 F

好,A 命令的参数讲完之后我们开始讲用 path 标签画扇形的原理:

再来看张图:

扇形图是圆的一部分,要画出图中的扇形图分三步:
#1:从圆心(400,300)画一条直线到弧的起点位置
#2:从弧的起点位置画一条弧到终点位置
#3:闭合路径
第一条线比较好画 M L 命令可以实现,但是我们首先要求出起点的坐标 x,y。画第二条弧的时候还要求出终点坐标,最后第三条线用 Z 命令直接闭合就可以了。
所以这里我们要写一个求坐标的函数,还要注意所有的度数都得转成弧度制,再写一个转弧度制的函数,怎么求弧的起点左边 x、y?x 坐标就是圆心的 cx 坐标 + 图示的线段 a,而线段 a =r*sin(ang),r 表示半径,ang 表示角度,角度是我们自己给的,终点坐标同理。

这里写的时候用一个数组存 d 属性的命令,最后用空格拼接在统一设置。

注意:

在画扇形图的时候,当终点和起点之间的角度小于 180°的时候,large-arc-flag 取 0,大于 180°的时候取 1,所以我们可以用三元运算符实现‘?:’;

还有就是 Arc start 和 Arc end 两个点如果重合,svg 将画不出任何曲线。因为经过一个点的弧有无数条

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #oSvg{background: rgba(187, 187, 187, 0.2);
        }
    </style>
    <script>
        window.onload=function(){let oP1=document.getElementById('p1');// 获取 path 对象
            let cx=300,cy=300,r=200;// 圆心坐标、半径
            let ang1=120,ang2=420;// 角度
            
            function d2a(n){// 角度转弧度
                return n*Math.PI/180;
            }
            function pointe(ang){// 求坐标函数
                return {x:cx+r*Math.sin(d2a(ang)),
                    y:cy-r*Math.cos(d2a(ang))
                }
            }
            let arr=[];// 存 d 属性的参数
            //#1
            let {x:x1,y:y1}=pointe(ang1);// 求出弧的起点坐标,线的终止点,命名 x1,y1
            arr.push(`M ${cx} ${cy} L ${x1} ${y1}`);// 画出从圆心到弧的线,但是这里还没画,只是添加到数组里了,最后的时候在一起画
            //#2
            let {x:x2,y:y2}=pointe(ang2);// 求出弧的终止点,命名 x2,y2
            arr.push(`A ${r} ${r} 0 ${ang2-ang1>=180?1:0} 1 ${x2} ${y2}`);// 画出第二条弧,这里也还没开始画,只是加到数组里了
            //#3
            arr.push('Z')// 闭合
            oP1.setAttribute('d',arr.join(' '));// 拼接数组里的字符,开始画
        }
    </script>
</head>
<body>
    <svg width='800' height='600' id="oSvg">
        <path id="p1" style="stroke: rgb(255, 136, 0); stroke-width:5;fill:none"></path>
    </svg>
</body>
</html>

正文完
 0