您的位置:首页 > 编程语言 > ASP

理解SVG的viewport,viewBox,preserveAspectRatio

2015-08-21 17:55 656 查看

转载了大神的博客,不是我写的

viewport

表示SVG可见区域的大小,或者可以想象成舞台大小,画布大小。

<svg width="500" height="300"></svg>


上面的SVG代码定义了一个视区,宽500单位,高300单位。

注意这里的措辞是“单位”,不是“像素”。虽然说,
width
/
height
如果是纯数字,使用的就是“像素”作为单位的。

也就是说,上面SVG的视区大小就是
500px * 300px
.

当然,故弄“单位”这个措辞,潜台词就是你可以使用其他类型的单位,涵盖常见CSS单位:

单位含义
em相对于父元素的字体大小
ex相对于小写字母"x"的高度
px相对于屏幕分辨率而不是视窗大小:通常为1个点或1/72英寸
ininch, 表英寸
cmcentimeter, 表厘米
mmmillimeter, 表毫米
pt1/72英寸
pc12点活字,或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>


结果如下:

或者亲自围观demo

如果不看
viewBox
, 你一定会觉得诧异——SVG尺寸明明有400*300像素,而小小的
<rect>
大小只有其
1/20
,但是显示出来的却占据了半壁江山!不科学啊!

OK, 之所以小小矩形大显神威就是这里的
viewBox
起了推波助澜的作用。

viewBox
值有4个数字:

viewBox="x, y, width, height"  // x:左上角横坐标,y:左上角纵坐标,width:宽度,height:高度


viewBox
顾名思意是“视区盒子”的意思,好比在说:“SVG啊,要不你就让我铺满你吧~”

更形象的解释就是:SVG就像是我们的显示器屏幕,viewBox就是截屏工具选中的那个框框,最终的呈现就是把框框中的截屏内容再次在显示器中全屏显示!

更直观的解释:
1. 如果没有
viewBox
, 应该是长这样的:



<rect>
大小只有整个SVG舞台的
1/20
.

2.
viewBox="0,0,40,30"
相当于在SVG上圈了下图左上角所示的一个框框:



3. 然后把这个框框,连同框框里的小矩形一起放大到整个SVG大小(如下gif):



到手里的才是自己的,您可以狠狠地点击这里:SVG viewBox属性原理分步演示demo



preserveAspectRatio

上面的例子,SVG的宽高比正好和viewBox的宽高比是一样的,都是
4:3
. 显然,实际应用
viewBox
不可能一直跟
viewport
穿同一条开裆裤。此时,就需要
preserveAspectRatio
出马了,此属性也是应用在
<svg>
元素上,且作用的对象都是viewBox

先看下猪是怎么跑的:

preserveAspectRatio="xMidYMid meet"


下面我们来吃猪肉。

preserveAspectRatio
属性的值为空格分隔的两个值组合而成。例如,上面的
xMidYMid
meet
.

第1个值表示,viewBox如何与SVG viewport对齐;第2个值表示,如何维持高宽比(如果有)。

其中,第1个值又是由两部分组成的。前半部分表示
x
方向对齐,后半部分表示
y
方向对齐。家族成员如下:

含义
xMinviewport和viewBox左边对齐
xMidviewport和viewBox x轴中心对齐
xMaxviewport和viewBox右边对齐
YMinviewport和viewBox上边缘对齐。注意Y是大写。
YMidviewport和viewBox y轴中心点对齐。注意Y是大写。
YMaxviewport和viewBox下边缘对齐。注意Y是大写。
x
,
y
自由合体就可以了,如:

xMaxYMax

xMidYMid


亲爱的小伙伴,看出啥意思没?

噔噔蹬蹬,没错,就是组合的意思:“右-下”和“中-中”对齐。恭喜你此处的知识点学习顺利毕业!

preserveAspectRatio
属性第2部分的值支持下面3个:

含义
meet保持纵横比缩放viewBox适应viewport,受
slice保持纵横比同时比例小的方向放大填满viewport,攻
none扭曲纵横比以充分适应viewport,变态
现在急需一个活生生的例子,让大家感受下这三个值的表现。

您可以狠狠地点击这里:meet,slice,none功能演示demo

首先,看下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等比例的同时,完全在SVG的viewport中显示。这里,最小比例是纵向的
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的对齐
千言万语不如一个可以自己动手体验的demo实在,您可以狠狠地点击这里:viewBox的对齐各个名称表现感受demo

截两张图给大家瞅瞅:





无论是
meet
还是
slice
,你是不可能在一种状态下同时看到
x
,
y
方向上的位移的。因为总会有一个方向是充满viewport的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: