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。
看例子:
注:( :viewBox ) - ( :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:(默认情况)
表现原理:xMid即viewBox的x轴的中点与viewport的中点贴合在一起,即viewBox的(100,0)根viewport的(200,0)贴合在一起
html:
渲染效果如下:
表现原理:xMax即viewBox的x轴的最大值与viewport的最大值贴合在一起,即viewBox的(200,0)根viewport的(400,0)贴合在一起
二、改变viewBox的位置,
先看viewBox的位置(棕色部分)
html:
表现原理:棕色矩形高200,但是y轴距离原点50,而svg只有200高度,所以剩下的隐藏了。
再来看添加viewBox的效果
html:
表现原理:viewBox的X轴的最小值和viewport的X轴最小值,即viewBox的(50,0)和viewport的(0,0)贴合,并且,由于viewBox的坐标系往上往左移,所以棕色矩形的剩下部分也出来了,即下面一部分的红色。(之所以是棕色,是因为底下有个矩形是绿色)
二、改变viewBox的大小,
先看viewBox(棕色部分)
html:
表现原理:同样的,即便高度增加了,但是svg的高度没有变化,依旧被遮住了。
添加viewBox之后:
html:
表现原理: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:
表现原理:刚刚好viewBox放大一倍。
再来改改viewBox的大小,
html:
添加viewBox之后
html:
渲染效果如下:
表现原理: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:
渲染效果如下:
html:
表现原理:比例小的方向填满viewport,viewBox的200 200变为viewport的400 200,当viewBox的X轴方向有200变为400时,又要保持纵横比,所以高度变成了400,而Ymin是以viewBox的Y轴最小值和viewport的Y轴最小值贴合,并且SVG的高度是200,所以viewBox剩下的一半被裁剪了。
none
则表示不关心比例,直接将viewBox拉伸填满viewport
html:
总结:
关于viewBox的理解:viewport和viewBox各有一个坐标系,当viewBox属性不设置的时候,天下太平,转换关系一对一。当加了viewBox之后,将viewBox的坐标系进行转换,或缩小或放大,然后再将viewBox的坐标系原点,与viewport坐标系的原点进行重叠。
至于如何进行缩放,是否按比例缩放,则看preserveAspectRatio的参数。
1. meet:保持纵横比,且整个viewBox都在viewport里面,所以按比例大的方向进行缩放;
2. slice:保持纵横比,且铺满整个viewport,所以按比例小的方向进行缩放;
3. none:不保持纵横比,只要铺满viewport即可。