The viewport, viewBox, and preserveAspectRatio
SVG元素是不受CSS盒模型控制的,这使得定位及变化这些元素没那么直观。但是当你理解呢SVG坐标系统及变化的工作原理,操控SVG将变得非常容易。本篇文章将介绍控制SVG坐标系统的三个非常重要的属性:viewport, viewBox, and preserveAspectRatio

The SVG Canvas

The Canvas 是SVG画图区域,可理解为画布,理论上这画布的边界是无穷大的,但是它实际上是相对于一个有限的区域渲染在屏幕上,这个有限的区域被称作为 viwport 视口。SVG超过vieport的区域将被切除不可见。你可以通过设置svg的width和height属性来设置viwport的大小。

<svg width="800" height="600"></svg>

但你设置完viwport的尺寸大小后,浏览器会初始化一个viwport坐标系统和用户坐标系统。
初始化的viwport坐标系统建立在viwport上,原点(0,0)设立在viwport的左上角,X轴的正方向指向右边,Y轴的正方向指向下。
初始化的用户坐标系统建立在SVG画布上,最开始与viwport坐标系统重合。用户坐标系统也叫做当前坐标系统。

SVG图形区域是全部可见还是部分可见取决于SVG图形的大小和preserveAspectRatio属性的值。这将在下面详细介绍。

The viewBox

你可以把The viewbox当作真正的坐标系统,因为SVG图形是依据这个坐标系统画在画布上面的。这个坐标系统可以比viwport坐标系统大或者小,也可以全部或者部分可见于viwport中。

The viewBox 语法
viewBox = <min-x> <min-y> <width> <height>

决定了原点的位置, 决定viewBox的尺寸大小,不能为负值。
通过设置viweBox的值你可以缩放、移动、甚至裁剪SVG图形。

viewBox属性设置

我们知道当我们没有设置viwBox属性时,用户坐标系统与viwport坐标系统重合的。我们可以通过设置viewBox属性的值来确立当前坐标系统。这分为两种情况:

  1. 与vieport坐标系统的大小等比例设置

1.1 为0时的等比例设置

这时候当前坐标系统将扩展到填充整个viwport区域。

<svg width="800" height="600" viewbox="0 0 400 300"></svg>
viewbox="0 0 400 300"具体做了什么呢?
1.确定当前坐标系统,原点(0,0)宽度=400px;高度=300px;
2.SVG图形相对于这个区域作图
3.缩放到与viwport大小重合,此时用户坐标系统的(0,0)对应viewport坐标系统(0,0),用户坐标系统(400,300)对应(800,600);
4.因此用户坐标系统对应到了viewport上。1user单位=2viwport单位

1.2 不为0时的等比例设置

<svg width="800" height="600" viewbox="100 100 200 150"></svg>
此时viewbox="100 100 200 150"具体做了什么呢?
1.确定当前坐标系统,原点(100,100) 宽度=200px;高度=150px;
2.SVG图形相对于当前坐标系统作图。
3.缩放到与viwport大小重合,故此时用户坐标系统的(100,100)对应viewport坐标系统(0,0),用户坐标系统(200,150)对应(400,200);
4.用户坐标系统对应到了viewport上。因此1user单位=4viwport单位
与上面不同的是,好像SVG图形移动了。(transform="translate(-100 -100)").此时如果有超过当前坐标系统区域而未超过viewport区域的都可以显示出来。记住一点:图像的显示与否,与viewport大小有关。
  1. 与vieport坐标系统的大小不成等比例设置


    宽高比不成比例,默认情况下:
    1.在保持viewBox的宽高比同时,充满viewport
    2.如果按高度500->600,此时宽度就成了600*1000/500=1200px;超过viewport区域;
    3.因此影射关系为1000->800,500->400
    4.viwbox垂直水平居中于viewport中

如果我们想自己设定viewbox在viewport中的位置,那么preserveAspectRatio属性就能派上用场了。

The preserveAspectRatio 语法

preserveAspectRatio = defer? <align> <meetOrSlice>?
defer是可选参数,只用在img元素上。
align:默认值"xMidYMid","none" 表示不维持宽高比例的变形缩放,此时<meetOrSlice>值被忽略。
    xMinYMin:viewBox的左边界与viewport左边界对齐,viewBox的上边界与viewport上边界对齐
    xMinYMid:viewBox的左边界与viewport左边界对齐,viewBox的中线与viewport的中线对齐
    同理可知xMinYMax,xMidYMin,xMidYMid,xMidYMax,xMaxYMin,xMaxYMid,xMaxYMax的对齐方法
<meetOrSlice>: 可选参数,默认为meet。确定整个viewBox是否在viewport内可见。
    meet:尽最大可能等比例缩放图形,但是整个viewBox在veiwport中可见。因此viewBox的宽和高边界只能满足宽或者是高边界与viewport的宽或高边界重合。
    Slice: 尽最大可能等比例缩放图形,使得viewBox可能超过viewport区域,超出区域被裁剪。

其实meet和Slice的区别可以很简单的归结为:如果是放大meet是按viewport和viewBox对应宽高比例的最小比例放大,如果是缩小meet是按viewBox和viewport对应宽高比例的最大比例缩小。Slice则相反。
如果 不为0,则正值代表在值都为0的基础上向左和向上平移 值,负值代表在值都为0的基础上向右和向下平移 值。