svg基本图形,路径,分组

589 阅读6分钟

svg基本图形

线段

svg中的line标签,用来表示线段,例如如下代码:
<svg width="200" height="300"> <line x1="40" y1="20" x2="80" y2="20" style="stroke:black;"/> <line x1="0.5cm" y1="1cm" x2="0.5cm" y2="3cm" style="stroke:black;"/> </svg>

1660612482598.png 表示水平和竖直线段。svg的样式控制可以放到style上,我们可以设置线宽:stroke-width,线颜色:stroke支持rgb,16进制颜色还可以是关键字black,blue等。线的透明度:stroke-opacity:线条透明度,和css一样是0-1之间数字,stroke-dasharray:断点线,这个需要解释一下,他的属性值是有一列数字组成,代表虚线长度和空隙长度,例如:stroke-dasharray:5 3,代表5个单位的虚线和3个单位的空隙,看个例子:
<svg width="1000" height="1000"> <line x1="40" y1="20" x2="200" y2="20" style="stroke:black;stroke-dasharray: 10 5;stroke-width: 5;"/> </svg>效果如下:

1660613850313.png
如果stroke-dasharray后面又偶数个数字,正好虚实相间,如果又奇数个数字怎么展示呢?例如,
<svg width="1000" height="1000"> <line x1="40" y1="20" x2="200" y2="20" style="stroke:black;stroke-dasharray: 10 5 20;stroke-width: 5;"/> </svg>
效果如下:

1660614049753.png,可以看到相当于:stroke-dasharray: 10 5 20 10 5 20;将奇数复制一遍,形成偶数。我们会在下一篇文章研究要论stroke-dasharray的应用,能做出炫酷的效果。

矩形

svg中的rect标签用来画矩形,rx,ry属性用来绘制圆角,例如:
<svg width="1000" height="1000"> <rect x="10" y="10" width="500" height="100" rx="30" ry="60" style="stroke: black; stroke-width:5;fill: brown;"/> </svg>
效果如图:

1660614903736.png,svg在这一块并不如css强大,css可以对四个圆角分辨单独设置。

svg中使用circle画圆,cx,cy中心点坐标,半径是r,例如:
<svg width="1000" height="1000"> <circle cx="100" cy="100" r="70" style="fill:none;stroke: black;stroke-width: 5;fill: brown;"/> </svg>

image.png

椭圆

svg用ellipse标签画椭圆,cx,cy中心点坐标,rx为x轴半径,ry为y轴半径,例如:
<svg width="1000" height="1000"> <ellipse cx="100" cy="150" rx="70" ry="100" style="fill:none;stroke: black;stroke-width: 5;fill: brown;"/> </svg>

1660616031240(1).png

多边形

svg使用polygon绘制多边形,例如:
<svg width="1000" height="1000"> <polygon points="35,100 95,100 110,30 125,100 185,100 135,125.8 170,195 110,150 65,195 85,130" style="fill: brown;stroke-width: 5;"/> </svg>

image.png,多变形的填充规则又两种,nonzero和evenodd。先看一下效果, <svg width="1000" height="1000"> <polygon points="35,100 195,100 60,195 110,30 170,195" style="fill: brown;stroke-width: 5;fill-rule: evenodd;"/> </svg>
<svg width="1000" height="1000"> <polygon points="35,100 195,100 60,195 110,30 170,195" style="fill: brown;stroke-width: 5;fill-rule: nonzero;"/> </svg>结果如下:

1660618262244(1).png

1660618310924.png
nonzero规则:判断某点是否在图形内,通过该店画一条直线,如果交叉点从右到左画,则相交总数加1,如果是从左到右画,则相交总数减1,如果最后总数为0,则在图像外部,否则在图像内部。evenodd规则,同样也是画一条射线,判断相交次数,为奇数该点在凸显内部,否则在图像外部。

折线

svg使用polygon画折线。 <svg width="1000" height="1000"> <polyline points="35,100 110,30 190,100 265,170 335,100" style="fill: none;stroke-width: 5;stroke: black;"/> </svg>

1660619025443.png

文本

文字掉落效果

svg使用text元素表示文本,其中font-family,font-size,font-weight,font-style,font-decoration,word-spacing,letter-spacing,都可以参考css属性,对svg文本这里主要介绍tspan元素,这是css里面没有的,例如实现一个文字掉落效果
<svg width="1000" height="1000"> <text x="30" y="30" style="font-size:20px">we will,we will <tspan dy="2">r</tspan> <tspan dy="4">o</tspan> <tspan dy="6">c</tspan> <tspan dy="8">k</tspan> you</text> </svg>

1660619743419.png

文字上下标

svg实现文字上下标比css要好,css实现文字上下标基本上是用vertical-align,svg就好多了。
<svg width="1000" height="1000"> <text x="30" y="30" style="font-size:20px"> H<tspan style="baseline-shift:sub">2</tspan> O<tspan style="baseline-shift:sub">2</tspan> </text> <text x="30" y="100" style="font-size:20px"> 5.9 x 10<tspan style="baseline-shift:super">8</tspan> </text> </svg>

1660620309503(1).png

文本路径

使用css实现文本路径太复杂了,要给每个字符个css,但是这方面svg做起来简单多了。例如
<svg width="1000" height="1000"> <defs> <path id="text_path" d="M100 100 L 200 100 A 50 50 0 0 1 250 150 L250 300" style="fill:none;stroke: black; stroke-width: 2;"/> </defs> <text x="30" y="100" style="font-size:20px"> <textPath xlink:href="#text_path"> we will we will rock you </textPath> </text> </svg>

image.png,再加上startOffset可以做一些炫酷的动画。

svg路径

path标签

path是更加通用的svg线条,是一系列相互链接的线,svg的path和css的clip-path是相通的,关于clip-path可以看我的文章:juejin.cn/post/706371… ,但这篇文章没有详细介绍路径的语法,下面是路径的具体介绍。属性d是data的缩写,路径数据包括,普通的命令有M,L,Z,V,H,v,h。圆弧和贝塞尔曲线比较复杂,下面两节单独介绍。
M:移动画笔到指定点
L:从当前点画一条线到指定点
Z: 曲线闭合
V num:绘制一条线到(currentX,num)
v num:绘制一条线到(currentX,currentY+num)
H num:绘制一条线到(num,currentY)
h num:绘制一条线到(currentX+num,currentY)
举个例子:
<svg width="1000" height="1000"> <path id="text_path" d="M100 100 L 200 100 A 50 50 0 0 1 250 150 h 20 v -20 H 300 V 400 H 270 v -20 h-20 A 50 50 0 0 1 200 430 h-100 Z" style="fill:none;stroke: black; stroke-width: 2;"/> </svg> 效果如下:

1660635331304.png

圆弧

在给定的两点,如果存在椭圆的话,那么再不考虑旋转的情况下可以画出四段圆弧,如图:

1660636083682.png圆弧的参数就是要在这四条弧线上确定一条。 首先要有椭圆的x,y轴两个半径,要有终点坐标,椭圆的旋转先不考虑,是第三个参数,圆弧2,3从起始点到终点按顺时针画。圆弧1,4从起始点到终点按逆时针画。圆弧1,2弧度小于180。圆弧3,4弧度大于180,这样就可以区分出来四条圆弧的那一条,再看看圆弧的语法:
A x半径 y半径 x轴旋转角度 圆弧是否大与180度(0|1) 绘制方向(0|1) 终点x坐标 终点y坐标上图圆弧代码如下: <svg width="1000" height="1000"> <!-- 圆弧1 --> <path d="M 100 100 A 50 100 0 0 0 150 200" style="stroke-width: 5;stroke: black;fill:none"/> <!-- 圆弧2 --> <path d="M 100 100 A 50 100 0 0 1 150 200" style="stroke-width: 5;stroke: aqua;fill:none"/> <!-- 圆弧3 --> <path d="M 100 100 A 50 100 0 1 1 150 200" style="stroke-width: 5;stroke: blueviolet;fill:none"/> <!-- 圆弧4 --> <path d="M 100 100 A 50 100 0 1 0 150 200" style="stroke-width: 5;stroke: brown;fill:none"/> </svg>

贝塞尔曲线

svg和css,以及canvas一样支持二次贝塞尔曲线和三次贝塞尔曲线,其实数学家很早以前就知道这些曲线。只是计算他们比较复杂。

贝塞尔曲线的数学原理

贝塞尔曲线就通过较少的控制点生成复杂的曲线,常言道一图胜千言,看下图二次贝塞尔曲线原理:

1660638241788.png 点A和C为曲线的起点和终点,B为控制点,在线段AB上任意取一点D,在BC上取一点E能使得AD/AB = BE/BC。在连接DE,同时在线段DE上找出点F,使得AD/AB = BE/BC = DF/DE。当D点在线段从A运动到B的过程中,F点的轨迹就是二次贝塞尔曲线。三次贝塞尔曲线和这大同小异。原理一样只是多了一个控制点。

贝塞尔曲线语法

二次贝塞尔曲线:Q x1 y1 x y 控制点坐标和终点坐标
三次贝塞尔曲线:C x1 y1 x2 y2 x y 两个控制点坐标和终点坐标
列子如下:
<svg width="1000" height="1000"> <path d="M 100 100 h50 Q 180 50 210 100 h50 " style="fill:none;stroke: black;"/> <path d="M 100 200 h50 C 170 150 190 150 210 200 h50 " style="fill:none;stroke: black;"/> </svg>

1660639398091.png 按照人们的视觉观点来说,只有一段曲线不太美观,人们天生对对称图形感兴趣,不管是中心对称还是轴对称。 svg给出来另外两个语法T和S:
T x y 绘制一条从当前点到x,y的二次贝塞尔曲线,控制点为Q的控制点的中心对称点。
S x2 y2 x y 绘制一条到x,y的三次贝塞尔曲线,第二个控制点为x2,y2,第一个控制点为C的第二个控制点的中心对称点。先一篇我们介绍贝塞尔曲线在绘图方面的介绍。

svg分组

g标签

svg提供了元素分组的概念这是css所没有的,现在不管是scss,less其实都可以理解文将多个元素作为一个组,方便使用,使文档更加结构化,更容易理解。g标签可以嵌套。

use标签

对于重复出现的内容,可以使用user标签多次引用g的分别分组,而不用重复写代码。 看下面g和use的例子:
<svg width="1000" height="1000"> <g id="pig" style="stroke: black;"> <circle cx="150" cy="150" r="100" style="fill:none"/> <circle cx="100" cy="120" r="20"/> <circle cx="200" cy="120" r="20"/> <circle cx="150" cy="180" r="40" style="fill:none"/> <circle cx="135" cy="180" r="10"/> <circle cx="165" cy="180" r="10"/> </g> <use xlink:href="#pig" x="300" y="0"/> </svg>效果如下:

1660642257921.png

defs标签

上面g和use的例子有个缺点,我们不能在use里面重新定义g的一些渲染方式,这就不太方便了,例如我想修改猪头的背景色。defs标签解决了这个问题。定义到defs标签里的g元素是不显示的。就像是定义了一个模板,在引用的时候可以对模板进行修改,例如:
<svg width="1000" height="1000"> <defs> <g id="pig" style="stroke: black;"> <circle cx="150" cy="150" r="100" style="fill:none"/> <circle cx="100" cy="120" r="20"/> <circle cx="200" cy="120" r="20"/> <circle cx="150" cy="180" r="40" style="fill:none;"/> <circle cx="135" cy="180" r="10"/> <circle cx="165" cy="180" r="10"/> </g> </defs> <use xlink:href="#pig" x="300" y="0" style="fill:brown;"/> </svg>

image.png,这样不止可以在不同的位置使用,而且可以改变填充色。

symbol标签

symbol元素与g类似,有两点不同:
1,即使symbol写到defs元素外,也不会显示。
2,symbol元素可以单独定义viewbox和preseveAspectRatio属性。

image标签

image标签用来引用图片,有两点需要注意
1,不能跨域引用图片,否则图片无法加载
2,svg不会对图片拉伸,只会做等比缩放。