SVG入门

简单介绍

SVG(Scale Vector Graphics),中文名,可缩放矢量图形,基于XML定义,是当今web开发中一项重要的技术,可用于构建图标系统,也可用于开发动效,甚至可以用于开发图表。总之这是一项十分有吸引力的技术。

为什么可缩放呢?

在学习SVG的具体技术之前,我们首先要了解为什么SVG是可缩放的矢量图形。

一个svg文件中所有图形的定义都是包裹在一个svg元素中,如下:

<svg>
 <rect x="120" width="100" height="100"/>
</svg> 

QQ20190506-142235-HD.gif

不过这里的图形却是不可缩放的,因为rect固定了其宽高为100个用户单位,即100px。我们可以通过定义在svg元素上定义viewBox使其真正做到可缩放。

<svg viewBox="0 0 220 100">
 <rect x="120" width="100" height="100"/>
</svg> 

QQ20190506-142728-HD.gif

这里我们相当于定义了一个220*100的空间,而rect中的单位都是基于viewBox的大小。这里我们没有对svg定义长宽,默认是100%。如果我们设置了svg的长宽,会怎么样呢?

<svg viewBox="0 0 220 100" width="400">
 <rect x="120" width="100" height="100"/>
</svg> 

QQ20190506-143215-HD.gif

我们将svg元素大小设为400px,这时svg当然不会缩放,不过其整体高度就变得很有意思了,这里的高度是181.81px。这个高度是 (400 / 220) * 100的结果。那如果设置高度呢?并且外层宽高和viewBox所规定的不成比例呢?

<svg viewBox="0 0 220 100" width="400" height="600">
 <rect x="120" width="100" height="100"/>
</svg> 

这时svg的内层空间是怎么计算坐标的呢?我们先来看看结果:

image.png

很显然,矩形很“诚实”地遵照了220的viewBox宽度,那么600的外层高度在viewBox中代表着多少呢?

我们加一个矩形,并做假设:viewBox高度 = (外层高度 / 外层宽度) * viewBox宽度 = (600/400) * 220 = 330。

<svg viewBox="0 0 220 100" width="400" height="600">
 <rect x="0" y="0" width="220" height="330" stroke="red"/>
 <rect x="120" width="100" height="100" stroke="black"/>
</svg> 

QQ20190506-145312-HD.gif

很显然,我的猜测是正确的,但是为什么红框的矩形没有位于x=0的位置呢?我们接着研究:

之前我们其实隐隐知道,viewBox和外层viewport有一种对应关系。其实这种对应关系是可以控制的,我们可以使用svg上的 preserveAspectRatio 这个属性定义viewBox和外层viewport之间的对应关系。

preserveAspectRatio 这个属性是这样定义的 perserveAspectRatio = "xMidYMid meet"  前半部分定义了viewBox的位置,后半部分定义了适应模式。

位置定义当然不止这一种,其实 xMidYMid 应该切分为 xMid YMid 代表了x和y轴居中,其他值如下:

含义

xMin

viewport和viewBox左侧对齐

xMid

viewport和viewBox X轴中心对齐

xMax

viewport和viewBox右侧对齐

YMin

viewport和viewBox顶端对齐

YMid

viewport和viewBoxY轴中心对齐

YMax

viewport和viewBox底端对齐

现在我们可以轻易地解决我们在上面提出的问题

<svg viewBox="0 0 220 100" width="400" height="600" preserveAspectRatio="xMidYMid meet">
 <rect x="0" y="0" width="220" height="330" stroke="red"/>
 <rect x="120" width="100" height="100" stroke="black"/>
</svg> 

image.png

meet算法会使得viewBox保持横纵比适应viewport

不过, perserveAspectRatio  属性并不止 meet 这种算法,还有 slice 和 none 这种算法,

首先来看 slice

<svg viewBox="0 0 220 100" width="400" height="600" preserveAspectRatio="xMinYMin slice">
 <rect x="0" y="0" width="220" height="100" stroke="red"/>
 <rect x="120" width="100" height="100" stroke="black"/>
</svg> 

image.png

矩形的高度和viewport相等,而矩形的宽度却变成了1320px,这是怎么来的呢?我们做如下假设:

slice 也会保持横纵比,往放大方向适应viewport,

vbWidth = (vpWidth/vpHeight) * vbHeight = (400/600) * 100 = 66.66

rectWith = 220 * (600/100) = 1320

vp为外层viewport,vb为viewBox

image.png

完美印证了我的猜想。

none 是怎么回事儿?

<svg viewBox="0 0 220 100" width="400" height="600" preserveAspectRatio="none">
 <rect x="0" y="0" width="220" height="100" stroke="red"/>
 <rect x="0" width="100" height="100" stroke="black"/>
</svg> 

image.png

很显然, none 模式完全不管横纵比,铺满整个viewport。

常用元素

待更新。。。