SVG小记——viewport,viewBox,preserveAspectRatio

本文详细解析SVG中的viewport和viewBox概念,介绍如何通过设置width、height及viewBox属性控制SVG视窗大小与内容显示范围,同时深入探讨preserveAspectRatio属性的作用及其不同取值的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

viewport ——表示SVG可见区域的大小

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

<svg>元素中通过设置其width和height属性来控制SVG的viewport大小。SVG中超出视窗边界的区域会被裁切并且隐藏。
其中width和hegiht的属性值可以直接是一个简单的数字,也可以指定具体的单位。如果没有指定单位,那么将会认其为“像素px”为单位。
SVG支持的长度单位有:em,ex,px,pt,pc,cm,mm,in和百分比。

viewBox——“视区盒子”

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

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

x和y值决定viewBox的左上角,width和height决定视窗的宽高。这里要注意视窗的宽高不一定和父<svg>元素的宽高一样。<width><height>值为负数是不合法的。值为0的话会禁止元素的渲染。
注意:视窗的宽度也可以在CSS中设置为任何值。例如:设置width:100%会让SVG视窗在文档中自适应。无论viewBox的值是多少,它会映射为外层SVG元素计算出的宽度值。

我喜欢像Google地图一样通过viewBox把SVG画布形象化。在Google地图中你可以在特定区域缩放;这个区域是唯一可见的,并且在浏览器视窗中按比例增加。然而,你知道地图的剩余部分还在那里,但是不可见因为它超出视窗的边界-被裁切了。

<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>

这里写图片描述

preserveAspectRatio

强制统一缩放比来保持图形的宽高比。

preserveAspectRatio="xMidYMid meet"

xMidYMid:

viewBox如何与SVG viewport对齐是由两部分组成的,前半部分表示x方向对齐,后半部分表示y方向对齐。

含义
xMinviewport和viewBox左边对齐
xMidviewport和viewBox x轴中心对齐
xMaxviewport和viewBox右边对齐
YMinviewport和viewBox上边缘对齐。注意Y是大写。
YMidviewport和viewBox y轴中心点对齐。注意Y是大写。
YMaxviewport和viewBox下边缘对齐。注意Y是大写。

meet:

如何维持高宽比(如果有)

含义
meet保持纵横比缩放viewBox适应viewport,受
slice保持纵横比同时比例小的方向放大填满viewport,攻
none扭曲纵横比以充分适应viewport,变态


注:你可以把meet or slice的值类比于background-size的contain和cover值,meet类似于contain,slice类似于cover。

一旦你设定最外层SVG元素的宽高,浏览器会建立初始视窗坐标系和初始用户坐标系。

  • 初始视窗坐标系:一个建立在视窗上的坐标系。原点(0,0)在视窗的左上角
  • 初始用户坐标系:
    • 建立在SVG画布上的坐标系。这个坐标系一开始和视窗坐标系完全一样-它自己的原点位于视窗左上角。
    • 使用viewBox属性,初始用户坐标系统-也称当前坐标系,或使用中的用户空间-可以变成与视窗坐标系不一样的坐标系。

您可以狠狠地点击这里: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的红色矩形。
x轴距离:(400-200)/2+10

默认展示如下:
这里写图片描述
如果我估计没错,默认应该是”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。




效果:
这里写图片描述
原本好好的一个正方形,现在因为viewBox的拉伸,变成了一个宽高2:1的矩形了。

viewBox的对齐

千言万语不如一个可以自己动手体验的demo实在,您可以狠狠地点击这里:viewBox的对齐各个名称表现感受demo。

截两张图给大家瞅瞅:

ViewBox

ViewBox

无论是meet还是slice,你是不可能在一种状态下同时看到x, y方向上的位移的。因为总会有一个方向是充满viewport的。


为了使文中的内容和解释更形象化,我创建了一个互动演示,你可以任意改变viewBox 和 preserveAspectRatio的值。
在线案例:http://sarasoueidan.com/demos/interactive-svg-coordinate-system/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值