viewport
、viewBox
和preserveAspectRatio
它是SVG的几个基本部分,必须理解。如果这些部分不清楚,将来会给你学习SVG的知识和使用带来很大的障碍。
viewport
表示SVG可见区域的大小,或者可以想象成舞台大小、画布大小。
<svg width="500" height="300"></svg>
SVG代码定义了一个视区,宽500单位,高300单位。
请注意,这里的措辞是“单位”,而不是“像素”。虽然,width
/height
若为纯数字,则以“像素”为单位。
也就是说,上面SVG的视区大小是500px * 300px
。
当然,所以“单位”这个词,潜台词是你可以使用其他类型的单位,涵盖常见的CSS单位:
单位 | 含义 |
---|---|
em | 与父元素的字体大小相比 |
ex | 与小写字母相比”“小写字母”x”的高度 |
px | 与屏幕分辨率而不是视窗大小相比,通常是1点或1/72英寸 |
in | inch, 表英寸 |
cm | centimeter, 表厘米 |
mm | millimeter, 表毫米 |
pt | 1/72英寸 |
pc | 12点活字,或1/12点活字 |
% | 与父元素相比。通常是通过属性来定义自己或其他元素。 |
除了SVG本身,还有其他元素,比如<rect>
的width
/height
上述单位也可用于属性,也是默认单位是像素。
viewbox属性
这是本文的重点和难点。
先看一个活蹦乱跳的例子,如下HTML代码:
<svg width="400" height="300" viewBox="0,0,40,30" style="border:1px solid #cd0000;"> <rect x="10" y="5" width="20" height="15" fill=#cd0000> </svg>
结果如下:
如果不看viewBox
, 你会感到惊讶—SVG的尺寸很明显400*300
像素,小的<rect>
大小只有其1/20
,但是显示出来的却占据了半壁江山!不科学!
OK, 小矩形之所以在这里展现神威,是因为它viewBox
起到推波助澜的作用。
viewBox
值有4
个数字:
viewBox="x, y, width, height" // x:左上角横坐标,y:左上角纵坐标,width:宽度,height:高度
viewBox
顾名思义,就是“视区盒”的意思,好像在说:“SVG啊,不然你就让我把你铺满吧~”
更生动的解释是:SVG就像我们的显示屏,viewBox
是截屏工具选择的框架,最终呈现是在显示器中再次显示框架中的截屏内容!
更直观的解释:
-
如果没有
viewBox
, 应该是这样的:
<rect>
只有整个SVG舞台的大小。1/20
。
-
viewBox="0,0,40,30"
相当于在SVG上圈出下图左上角所示的框架:
-
然后将这个框架和框架中的小矩形一起放大到整个SVG大小(如下gif):
手里的是自己的,
preserveAspectRatio
在上面的例子中,SVG的宽高比恰到好处viewBox
宽高比是一样的,都是4:3
。
显然,实际应用viewBox
不可能一直跟着viewport
穿同一条开裆裤。此时,需要preserveAspectRatio
出马了,这个属性也应用到了<svg>
在元素上,作用的对象都是viewBox
。
先看看猪是怎么跑的:
preserveAspectRatio="xMidYMid meet"
让我们吃猪肉。
preserveAspectRatio
属性值由空间分隔的两个值组成。例如,上述值xMidYMid
和meet
。
第一个值表示,viewBox
如何与SVG相匹配 viewport对齐;第二个值表示如何保持高宽比(如果有)。
第一个值由两部分组成。前半部分表示x
方向对齐,后半部分表示y
方向对齐。家庭成员如下:
值 | 含义 |
---|---|
xMin | viewport和viewbox左侧对齐 |
xMid | viewport和viewBox x轴中心对齐 |
xMax | viewport和viewbox右侧对齐 |
YMin | viewport与viewbox上边缘对齐。注意Y是大写。 |
YMid | viewport和viewBox Y轴中心点对齐。注意Y是大写。 |
YMax | viewport与viewbox下边缘对齐。注意Y是大写。 |
x
, y
可以自由合体,如:
xMaxYMax xMidYMid
亲爱的朋友们,你们看到什么意思了吗?
是的,是组合的意思:“右-下”与“中-中”对齐。恭喜您在这里学习知识点,顺利毕业!
preserveAspectRatio
属性第二部分的值支持如下三个:
值 | 含义 |
---|---|
meet | viewbox适应viewport,保持纵横比缩放 |
slice | 同时保持纵横比小的方向放大,填充viewport,攻击 |
none | 扭曲纵横比以充分适应viewport,变态 |
现在迫切需要一个活生生的例子来感受这三个值的表现。
首先,看SVG代码:
<svg width="400" height="200" viewBox="0 0 200 200" style="border:1px solid #cd0000;"> <rect x="10" y="10" width="150" height="150" fill=#cd0000> </svg>
截取SVG左侧的一半(200只是400的宽度)作为视区,里面有一个150*150
红色矩形。
默认显示如下:
如果我估计是对的,默认应该是"xMidYmid meet"
效果。
① 如果是meet
代码如下:
<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet" style="border:1px solid #cd0000;"> <rect x="10" y="10" width="150" height="150" fill=#cd0000> </svg>
截图效果如下:
性能原理如下:SVG宽400
, 高200
,viewBox
宽200
, 高200
。x
横轴比例是2
, y
纵轴比例是1
。meet
的作用是让viewBox
在等比的同时,完全是SVGviewport
中间显示。在这里,最小比例是纵向的1
,所以,实际上viewBox
没有缩放。
我们只要对viewBox
对属性值做一点修改(200→300
),你可以感觉到缩放:
<svg width="400" height="200" viewBox="0 0 200 300" preserveAspectRatio="xMinYMin meet" style="border:1px solid #cd0000;"> <rect x="10" y="10" width="150" height="150" fill=#cd0000> </svg>
此时的显示效果为:
改成300
后,viewBox
的高度就比viewport
的200
高,所以,viewBox
想要完全适应viewport
,因此,由于缩放的结果,我们可以将上述矩形面积缩小(缩放)200/300
, 几乎是原来的66.7%
)。
② 如果是slice
, slice
它本身就意味着剪切。代码如下:
<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin slice" style="border:1px solid #cd0000;"> <rect x="10" y="10" width="150" height="150" fill=#cd0000> </svg>
效果如下:
slice
也是要保持viewBox
然而,纵横比的作用是尽可能地填充viewport
。 同样,这里viewBox
宽度200
,SVG的width
是400
. 显然,为了最大化充实,viewBox
宽度需要扩大到原来的两倍。所以,有上图viewBox
放大两倍后的效果截图。因为viewBox
有些区域超过了viewport
, 视区外的内容是看不见的,所以出现了slice
表示“剪切”效果。
③ 如果是none
, 表示不关心比例,viewBox
直接拉伸到最大填充物viewport
。
<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin none" style="border:1px solid #cd0000;"> <rect x="10" y="10" width="150" height="150" fill=#cd0000> </svg>
效果:
一个原本很好的正方形,现在因为viewBox
拉伸变成了宽高的拉伸2:1
的矩形了。
viewbox对齐
截两张图给大家看:
无论是meet
还是slice
,你不能同时看到一种状态吗?x
, y
方向位移。因为总有一个充满方向的方向viewport
的。