因业务需要,研究了下svg的写法,光看语法,看的有点蒙,几个数字就胡乱猜测才费老劲搞出来。最后静下心来,才发现其实很简单,只不过一开始没仔细琢磨,走了不少弯路,关键那些点网上还找不到解答.特记录下,给和我一样走弯路或者新入门svg的同学答疑!
参考文章
先附上感觉比较有用的参考文档:
SVG入门—如何手写SVG
mdn web docs - SVG
SVG 教程 - 菜鸟教程
关于起点和坐标轴
搞清楚起点和坐标轴方向是最最基础的地方,这个没搞清楚,后续所有的绘制都会糊里糊涂!(才不会说自己一开始没搞清楚,一顿乱猜数据的事情 ༎ຶД༎ຶ )
起点的坐标(x,y)是(0,0)这个肯定没问题,需要注意的是,svg中因为起点是在画布的左上角第一个像素那,所以向右x>0,向下y>0! y的方向和普通的几何图形是不一样的
(如图,白色区域为svg的画布区域,左上角第一个像素是起点。我们自定义一个起点x="300" y="300",便于描述xy的方向
简单入门
其实搞清楚坐标轴方向后,再结合语法其实就很清晰的知道该怎么画基础点线面了
画直线 line
这个是一条横向长200,粗2的红色直线(颜色不设置的话,默认是黑色)
x1和y1是起点的坐标,x2和y2是终点的坐标,两点练成一条直线
要画斜线的话,修改起点和终点的x或者y不相等就行
<line x1="0" y1="0" x2="200" y2="0" class="coor-line" />
.coor-line {
stroke: red;
stroke-width: 2;
}
这个写法和上面的写法是一样的效果
<line x1="0" y1="0" x2="200" y2="0" stroke="red" stroke-width="2"/>
画折线(如箭头)+ 文字 polyline text
折线其实就是多个点之间的直线相连,只需要找准几个转折点的坐标,就可以了,polyline中的points属性,就是由多个xy组,组合而且,有几个转折点,就有几个组。这里的箭头就是由三个点组成
<text x="30" y="25">20,20</text>
<polyline points="0,0 20,20 0,40" style="fill: none; stroke: red; stroke-width: 3" />
文字其实也很简单,就是找准起点就行,唯一注意的就是文字本身就有宽度和高度,想要对准位置,需要在预计的点位上进行微小偏差。
fill表示填充,如果有颜色,在点能组成面的时候,就会自动变成一个三角形
<polyline points="0,0 20,20 0,40 0,0" style="fill: red; stroke: red; stroke-width: 3" />
不过画线和画面毕竟不一样,画线其实画的是面的border(大概就是这个意思,实际s不是),所以会和上图一样,像素点未闭合(并且仔细看代码,画成这个面用了四个点,如果只用三个点的话,会少一个小个像素点的边)
画路径 path
路径其实效果和折线差不多,但是他可以不用一笔画完,可以设置多个起点的线段。
path中的属性都写在d中。总共有十个属性,每个属性区分大小写,大写是绝对定位,与前一个点位无关,小写为相对定位,起点(0,0)默认等于前一个定位
具体属性如下(来源网上)
简单举个例子:
- 绝对定位下: (所有的起点都是
(0,0)点位)
<path d="M 0,0 l 0,40 M 0,0 l0 -40 M0,0 l20,20 M0,0 l-20,20 M0,0 l -20,-20 M0,0 l 20,-20 Z" style="stroke: red; stroke-width: 2" />
- 相对定位下:(起点为前一个点位的结尾)
<path d="m0,0 l 0,40 m 0,0 l0 -40 m0,0 l20,20 m0,0 l-20,20 m0,0 l -20,-20 m0,0 l 20,-20 Z" style="stroke: red; stroke-width: 2" />
- Z 关闭路径后,下一个路径的起点就又是最开始的起点了。
- 其他的属性可参照文档自行摸索
画多边形(面) polygon circle rect ellipse
画面有四个元素,多边形、圆形、方形和椭圆形,再了解了坐标点和坐标轴后,其实参照语法定义,还是很简单的 菜鸟教程 - svg多边形语法
<polygon points="0,0 20,20 0,40" style="fill: red; stroke: purple; stroke-width: 0" />
这个三角形就完美了
<g> 生成组合元素
<g>的作用就是一个将元素变成一个组合元素,类似于<div>的作用,使用<g>不仅可以使代码看起来干净整洁,目前我发现的最大作用就是可以整体移动整个组合的元素的位置。
组合中的各个元素的默认(0,0)是<g>所在的起点,将<g>添上transform="translate(x,y)"就可以移动整体,再也不需要将组合里的单个元素进行挨个移动了
如下代码,<g>中每一个元素的默认的起点都是(300,300)
<circle cx="5" cy="5" r="5" fill="red" />
<text x="0" y="25" fill="red">默认起点(x,y)=(0,0)</text>
<g transform="translate(300,300)">
<text x="-10" y="-7">0,0</text>
<circle cx="0" cy="0" r="2" fill="red" />
<text x="30" y="25">20,20</text>
<circle cx="20" cy="20" r="2" fill="red" />
<circle cx="0" cy="40" r="2" fill="red" />
<text x="-20" y="56">0,40</text>
</g>
重复使用元素 <use> 配合 <g> <defs> <symbol>
在svg中有个id值,将组合元素的父元素设置一个id名称后使用<use>就可以直接复制该组合元素
<use> + <g>(<g>默认可见):
<g id="triangle" transform="translate(300,300)">
<polygon points="0,0 20,20 0,40" style="fill: red; stroke: purple; stroke-width: 0" />
</g>
<use href="#triangle" x="100" y="100"></use>
<use> + <defs>(<defs>默认不可见):
<defs>标签里的内容默认是不可见的,只能通过use来呈现
<defs>
<polygon id="triangle" points="0,0 20,20 0,40" style="fill: red; stroke: purple; stroke-width: 0" />
</defs>
<use href="#triangle" x="100" y="100"></use>
<use> + <symbol>(<symbol>默认不可见):
<symbol>和<defs>差不多,它也是默认不可见的,需要由<use>来呈现,但是使用<symbol>可以对元素的大小进行缩放。
使用viewBox搭配<use>的width和height对内容进行放大处理
<symbol id="triangle2" viewBox="0 0 300 300">
<polygon points="0,0 20,20 0,40" style="fill: red; stroke: purple; stroke-width: 0" />
</symbol>
<use href="#triangle2" x="100" y="100" width="100" height="100"></use>
<use href="#triangle2" x="100" y="150" width="200" height="200"></use>
<use href="#triangle2" x="100" y="200" width="300" height="300"></use>
<use href="#triangle2" x="100" y="250" width="800" height="800"></use>
viewBox类似于截图放大功能假设整个画布600*600,viewBox="0 0 300 300"代表我从三角形的(0,0)的起点开始截300*300尺寸的图,并将该截图放大到600*600,即放大了两倍。
<use>的width和height就是svg画布的宽高的概念,假设width="100" height="100",就是将截出来的300*300尺寸的图,放到一个尺寸为100*100的画布上,截的图必须得缩小3倍才能放的下,即三角形相比于默认大小,缩小3倍。其他尺寸同理
viewBox知识点参考文章: 理解SVG图片标签的viewport、viewBox、preserveAspectRatio缩放
后记
因为只是项目中突然要使用到svg,所以暂时理了这些常用的用法,其实svg真要学好,还有很多知识点需要掌握。但是只要掌握了学习方法,了解了基础核心(定位),其他的用到什么就去查找相关语法,还是挺容易的。
共勉!