手撸SVG(入门篇)

435 阅读5分钟

因业务需要,研究了下svg的写法,光看语法,看的有点蒙,几个数字就胡乱猜测才费老劲搞出来。最后静下心来,才发现其实很简单,只不过一开始没仔细琢磨,走了不少弯路,关键那些点网上还找不到解答.特记录下,给和我一样走弯路或者新入门svg的同学答疑!

参考文章

先附上感觉比较有用的参考文档:
SVG入门—如何手写SVG
mdn web docs - SVG
SVG 教程 - 菜鸟教程

关于起点和坐标轴

搞清楚起点和坐标轴方向是最最基础的地方,这个没搞清楚,后续所有的绘制都会糊里糊涂!(才不会说自己一开始没搞清楚,一顿乱猜数据的事情 ༎ຶД༎ຶ )

起点的坐标(x,y)(0,0)这个肯定没问题,需要注意的是,svg中因为起点是在画布的左上角第一个像素那,所以向右x>0,向下y>0 y的方向和普通的几何图形是不一样的

image.png

(如图,白色区域为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"/>

image.png

画折线(如箭头)+ 文字 polyline text

折线其实就是多个点之间的直线相连,只需要找准几个转折点的坐标,就可以了,polyline中的points属性,就是由多个xy组,组合而且,有几个转折点,就有几个组。这里的箭头就是由三个点组成

image.png image.png

<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" />

image.png
不过画线和画面毕竟不一样,画线其实画的是面的border(大概就是这个意思,实际s不是),所以会和上图一样,像素点未闭合(并且仔细看代码,画成这个面用了四个点,如果只用三个点的话,会少一个小个像素点的边)

画路径 path

路径其实效果和折线差不多,但是他可以不用一笔画完,可以设置多个起点的线段。
path中的属性都写在d中。总共有十个属性,每个属性区分大小写,大写是绝对定位,与前一个点位无关,小写为相对定位,起点(0,0)默认等于前一个定位
具体属性如下(来源网上) 网图
简单举个例子:

  • 绝对定位下: (所有的起点都是(0,0)点位)
    image.png
<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" />
  • 相对定位下:(起点为前一个点位的结尾)
    image.png
<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" />

image.png
这个三角形就完美了

<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>

image.png

重复使用元素 <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>

image.png

  • <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>

image.png

  • <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>

image.png

viewBox类似于截图放大功能假设整个画布600*600viewBox="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真要学好,还有很多知识点需要掌握。但是只要掌握了学习方法,了解了基础核心(定位),其他的用到什么就去查找相关语法,还是挺容易的。

共勉!