关于SVG的viewBox和preserveAspectRatio

viewport


表示SVG可见区域的大小。
//单位:不写默认为px。

<svg style="width:400; height:200;"></svg>

preserveAspectRatio


preserveAspectRatio=”align meetOrSlice”
or
preserveAspectRatio=”none”
该属性的意思是维持纵横比,作用于viewBox属性
align
参数的值有分为两个部分,第一个部分指定x坐标的对齐方式,第二部分指定y坐标的对齐方式,如下:
- xMin viewBox的最小X值对齐viewport的左边部
- xMid viewBox的X轴中点对齐viewport的X轴中点
- xMax viewBox的最大X值对齐viewport的右边部
- YMin viewBox的最小y值对齐viewport的顶边
- YMid viewBox的y轴中点对齐viewport的y轴中点
- YMax viewBox的最大Y值对齐viewport的底边
X对齐和Y对齐两两结合,组成一个align参数,例如,xMaxYMax
meet or slice
- meet 保持纵横比缩放viewBox适应viewport。ps:整个viewbox包含在viewport里
- slice 保持纵横比同时比例小的方向放大填满viewport
none
- none不保留宽高比,缩放图像适合整个viewport
注意:
1、默认值是xMidYMid meet;


viewBox


viewBox=”x,y,w,h” 该属性的意思是可视区盒子,即画布的可视区。
可以看做,viewBox和viewport分别有两个自己的坐标系,什么都不做的时候,两个坐标系是重合的,并且转换关系是1:1。
当设置viewBox的时候,即将viewBox的坐标系进行转换,或缩小或放大,然后将新的viewBox坐标原点与viewport坐标原点重合,即,坐标之间的转换不再是1:1。
看例子:
注:( red:viewBox ) - ( green:SVG ) - ( 这里写图片描述 : 参考的rectangle)

html:

<svg style="width:400; height:200;">
    <line x1="0" y1="100" x2="400" y2="100" style="stroke:black;stroke-width:1"/>
    <line x1="100" y1="0" x2="100" y2="200" style="stroke:black;stroke-width:1"/>
    <line x1="200" y1="0" x2="200" y2="200" style="stroke:black;stroke-width:1"/>
    <line x1="300" y1="0" x2="300" y2="200" style="stroke:black;stroke-width:1"/>
    <rect x="0" y="0" width="400" height="200" fill="rgba(0,255,0,0.5)"/>
    <rect x="100" y="100" width="100" height="100" fill="#FAC4C4"/>
</svg>

渲染效果如下:
这里写图片描述

一、添加viewBox (meet)
其余代码只贴变化部分
html:

<svg viewBox='0 0 200 200' preserveAspectRatio="xMinYMid meet" >
    <line x1="0" y1="100" x2="400" y2="100" style="stroke:black;stroke-width:1"/>
    <line x1="100" y1="0" x2="100" y2="200" style="stroke:black;stroke-width:1"/>
    <line x1="200" y1="0" x2="200" y2="200" style="stroke:black;stroke-width:1"/>
    <line x1="300" y1="0" x2="300" y2="200" style="stroke:black;stroke-width:1"/>
    <rect x="0" y="0" width="400" height="200" fill="rgba(0,255,0,0.5)"/>
    <rect x="0" y="0" width="200" height="200" fill="rgba(255,0,0,0.5)"/>
    <rect x="100" y="100" width="100" height="100" fill="#FAC4C4"/>
</svg>

渲染效果截图
这里写图片描述

表现原理:xMin即viewBox的x轴的最小值与viewport的最小值贴合在一起,即viewBox的(0,0)根viewport的(0,0)贴合在一起


html:(默认情况)

<svg  viewBox='0 0 200 200' preserveAspectRatio="xMidYMid meet" >
   ...
</svg>

渲染效果截图如下:
这里写图片描述

表现原理:xMid即viewBox的x轴的中点与viewport的中点贴合在一起,即viewBox的(100,0)根viewport的(200,0)贴合在一起


html:

<svg viewBox='0 0 200 200' preserveAspectRatio="xMaxYMid meet" >
    ...
</svg>

渲染效果如下:
这里写图片描述
表现原理:xMax即viewBox的x轴的最大值与viewport的最大值贴合在一起,即viewBox的(200,0)根viewport的(400,0)贴合在一起


二、改变viewBox的位置,
先看viewBox的位置(棕色部分)
html:

<svg style="width:400; height:200;" >
    ...
     <rect x="50" y="50" width="200" height="200" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染结果如下:
这里写图片描述

表现原理:棕色矩形高200,但是y轴距离原点50,而svg只有200高度,所以剩下的隐藏了。


再来看添加viewBox的效果
html:

<svg viewBox='50 50 200 200' preserveAspectRatio="xMinYMid meet" >
    ...
     <rect x="50" y="50" width="200" height="200" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:
这里写图片描述

表现原理:viewBox的X轴的最小值和viewport的X轴最小值,即viewBox的(50,0)和viewport的(0,0)贴合,并且,由于viewBox的坐标系往上往左移,所以棕色矩形的剩下部分也出来了,即下面一部分的红色。(之所以是棕色,是因为底下有个矩形是绿色)


二、改变viewBox的大小,
先看viewBox(棕色部分)
html:

<svg style="width:400; height:200;">
     <rect x="50" y="50" width="200" height="300" fill="rgba(255,0,0,0.5)"/>
    ...
</svg>

渲染效果如下:
这里写图片描述

表现原理:同样的,即便高度增加了,但是svg的高度没有变化,依旧被遮住了。


添加viewBox之后:
html:

<svg viewBox='50 50 200 300' preserveAspectRatio="xMinYMid meet" >
    ...
     <rect x="50" y="50" width="200" height="300" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:
这里写图片描述

表现原理:viewBox坐标系中y轴的300,转为viewport坐标系中y轴的200,所以参考矩形的边长也由100变成了66.7。
有人也许会问,为什么不是以x轴为基准,viewBox的x轴铺满viewport,y轴再拉伸或缩小。我们来看看meet的意思:保持纵横比缩放viewBox适应viewport,整个viewBox都要在vieport中(不是填满,不是填满,不是填满)。而,viewBox的高比viewport高,所以viewBox,要进行缩小,由原来的300,变为现在的200,而又要保持纵横比,所以viewBox的宽度也要进行相应的缩小1/3。
即viewBox坐标系缩小了1/3。
我们再去回头去看之前的,因为viewBox的高度等于viewport的高度都等于200,viewBox的宽度小于viewport的宽度,所以不存在缩放。


再来看一个例子,将viewBox的纵横比改为与viewport相等
html:

<svg style="width:400; height:200;">
    ...
     <rect x="50" y="50" width="200" height="100" fill="rgba(255,0,0,0.5)"/>
</svg>

这里写图片描述
添加viewBox之后
html:

<svg viewBox='50 50 200 100' preserveAspectRatio="xMinYMid meet" >
    ...
     <rect x="50" y="50" width="200" height="100" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:
这里写图片描述

表现原理:刚刚好viewBox放大一倍。


再来改改viewBox的大小,
html:

<svg style="width:400; height:200;">
    ...
     <rect x="50" y="50" width="200" height="80" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:
这里写图片描述

添加viewBox之后
html:

<svg viewBox='50 50 200 80' preserveAspectRatio="xMinYMid meet" >
    ...
     <rect x="50" y="50" width="200" height="80" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:
这里写图片描述
表现原理:viewBox的200 80 要缩放为viewport的400 200,放大两倍,宽变为400 高度变为160。


总结:meet是保持纵横比,然后将整个viewBox放入viewport中,所以,当viewport的纵横比固定为200/400=0.5时,viewBox的缩放以X轴还是Y轴为基准,取决于viewBox的纵横比,当viewBox的纵横比小于viewport的纵横比0.5时,则以X轴为基准,反之亦反,即以比例大的方向为基准。

原理:当viewBox的纵横比小于0.5,说明viewBox的高度要达到viewport的高度,需要放大的倍数要比viewBox的宽度多。若以高度(y轴)为基准,则viewBox的宽度溢出了。


Slice


该属性是保持纵横比同时比例小的方向放大填满viewport,(填满,填满,填满)
html:

<svg style="width:400; height:200;">
    ...
     <rect x="50" y="50" width="200" height="200" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:

这里写图片描述
添加viewBox之后

html:

<svg viewBox='50 50 200 200' preserveAspectRatio="xMinYMin slice" >
    ...
     <rect x="50" y="50" width="200" height="200" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:
这里写图片描述

表现原理:比例小的方向填满viewport,viewBox的200 200变为viewport的400 200,当viewBox的X轴方向有200变为400时,又要保持纵横比,所以高度变成了400,而Ymin是以viewBox的Y轴最小值和viewport的Y轴最小值贴合,并且SVG的高度是200,所以viewBox剩下的一半被裁剪了。


none


则表示不关心比例,直接将viewBox拉伸填满viewport
html:

<svg viewBox='50 50 200 200' preserveAspectRatio="xMinYMin none" >
    ...
     <rect x="50" y="50" width="200" height="200" fill="rgba(255,0,0,0.5)"/>
</svg>

渲染效果如下:
这里写图片描述


总结:

  1. viewport:观察口,代表svg的大小,即可见区域;
  2. viewBox:视区盒子,视区内的直线、图形均按该视区标准去渲染;
  3. preserveAspectRatio作用viewBox显示的效果。

关于viewBox的理解:viewport和viewBox各有一个坐标系,当viewBox属性不设置的时候,天下太平,转换关系一对一。当加了viewBox之后,将viewBox的坐标系进行转换,或缩小或放大,然后再将viewBox的坐标系原点,与viewport坐标系的原点进行重叠。
至于如何进行缩放,是否按比例缩放,则看preserveAspectRatio的参数。

 1. meet:保持纵横比,且整个viewBox都在viewport里面,所以按比例大的方向进行缩放;
 2. slice:保持纵横比,且铺满整个viewport,所以按比例小的方向进行缩放;
 3. none:不保持纵横比,只要铺满viewport即可。

猜你喜欢

转载自blog.csdn.net/zhy13087344578/article/details/80336044