viewBox
我喜欢把viewBox理解为“真实”坐标系。首先,它是用来把SVG图形绘制到画布上的坐标系。这个坐标系可以大于视窗也可以小于视窗,在视窗中可以整体可见或部分可见。
在之前的章节里,这个坐标系-用户坐标系-和视窗坐标系完全一样。因为我们没有把它声明成其他坐标系。这就是为什么所有的定位和绘制看起来是基于视窗坐标系的。因为我们一旦创建视窗坐标系(使用width和height),浏览器默认创建一个完全相同的用户坐标系。
你可以使用viewBox属性声明自己的用户坐标系。如果你选择的用户坐标系统和视窗坐标系统宽高比(高比宽)相同,它会延伸来适应整个视窗区域(一分钟内我们就来讲个例子)。然而,如果你的用户坐标系宽高比不同,你可以用preserveAspectRatio属性来声明整个系统在视窗内是否可见,你也可以用它来声明在视窗中如何定位。我们会在下个章节里讨论这一情况的细节和例子。在这一章里,我们只讨论viewBox的宽高比符合视窗的情况-在这些例子中,preserveAspectRatio不产生影响。
在我们讨论这些例子前,我们回顾一下viewBox的语法。
viewBox语法
viewBox属性接收四个参数值,包括:min-x, min-y, width 和 height。
- viewBox = <min-x> <min-y> <width> <height>
min-x 和 min-y 值决定viewBox的左上角,width和height决定视窗的宽高。这里要注意视窗的宽高不一定和父svg元素的宽高一样。width和height值为负数是不合法的。值为0的话会禁止元素的渲染。
注意视窗的宽度也可以在CSS中设置为任何值。例如:设置width:100%会让SVG视窗在文档中自适应。无论viewBox的值是多少,它会映射为外层SVG元素计算出的宽度值。
设置viewBox的例子如下:
- <!-- The viewBox in this example is equal to the viewport, but it can be different -->
- <svg width="800" height="600" viewBox="0 0 800 600">
- <!-- SVG content drawn onto the SVG canvas -->
- </svg>
如果你之前在其他地方看到过viewBox,你也许会看到一些解释说你可以用viewBox属性通过缩放或者变化使SVG图形变换。这是真的。我将深入探究并且告诉你甚至可以使用viewBox来切割SVG图形。
理解viewBox和视窗之间差异最好的方法是亲身观察。所以让我们看一些例子。我们将从viewBox和viewport的宽高比相同的例子开始,所以我们还不需要深入了解preserveAspectRatio。
与viewport宽高比相同的viewBox
我们从一个简单的例子开始。这个例子中的viewBox的尺寸是视窗尺寸的一半。在这个例子中我们不改变viewBox的原点,所以min-x和min-y都设置成0。viewBox的宽高是viewport宽高的一半。这意味着我们保持宽高比。
- <svg width="800" height="600" viewBox="0 0 400 300">
- <!-- SVG content drawn onto the SVG canvas -->
- </svg>
所以,viewBox=”0 0 400 300”到底有什么用呢?
它声明了一个特定的区域,canvas横跨左上角的点(0,0)到点(400,300)。
SVG图像被这个区域裁切。
区域被拉伸(类似缩放效果)来充满整个视窗。
用户坐标系被映射到视窗坐标系-在这种情况下-一个用户单位等于两个视窗单位。
下面的图片展示了在我们例子中把上面的viewBox应用到svg 画布中的效果。灰色单位代表视窗坐标系,蓝色坐标系代表viewBox建立的用户坐标系。
任何在SVG画布中画的内容都会被对应到新的用户坐标系中。
我喜欢像Google地图一样通过viewBox把SVG画布形象化。在Google地图中你可以在特定区域缩放;这个区域是唯一可见的,并且在浏览器视窗中按比例增加。然而,你知道地图的剩余部分还在那里,但是不可见因为它超出视窗的边界-被裁切了。
现在让我们试着改变min-x和min-y的值。都设置为100。你可以设置成任何你想要的值。宽高比还是和视窗的宽高比一样。
- <svg width="800" height="600" viewBox="100 100 200 150">
- <!-- SVG content drawn onto the SVG canvas -->
- </svg>
web前端开发
再一次,用户坐标系被映射到视窗坐标系-200用户单位映射为800视窗单位因此每个用户单位等于四个视窗单位。结果像你看到的那样是放大的效果。
另外注意,在这个时候,为min-x和min-y声明非0的值对图形有变换的效果;更加特别的是,SVG 画布看起来向上拉伸100个单位,向左拉伸100个单位(transform=”translate(-100 -100)”)。
的确,作为规范说明,“viewBox属性的影响在于用户代理自动添加适当的变换矩阵来把用户空间中具体的矩形映射到指定区域的边界(通常是视窗)”。
这是一个很棒的说明我们之前已经提到的内容的方法:图形被裁切然后被缩放以适应视窗。这个说明随后增加了一个注释:“在一些情况下用户代理在缩放变换之外需要增加一个移动变换。例如,在最外层的svg元素上,如果viewBox属性对min-x和min-y声明非0值得那么就需要移动变换。”
为了更好演示移动变换,让我们试着给和添加-100。移动效果类似transform=”translate(100 100)”;这意味着图形会在切割和缩放后移动到右下方。回顾倒数第二个裁切尺寸为400*300的例子,添加新的无效min-x和min-y值,新的代码如下:
- <svg width="800" height="600" viewBox="-100 -100 300 200">
- <!-- SVG content drawn onto the SVG canvas -->
- </svg>
给图形添加上述viewBox transformation的结果如下图所示:
注意,与transform属性不同,因为viewBox自动添加的tranfomation不会影响有vewBox属性的元素的x,y,宽和高等属性。因此,在上述例子中展示的带有width,height和viewBox属性的svg元素,width和height属性代表添加viewBox 变换之前的坐标系中的值。在上述例子中你可以看到初始(灰色)viewport坐标系甚至在svg上使用了viewBox属性后仍然没有影响。
另一方面,像tranform属性一样,它给所有其他属性和后代元素建立了一个新的坐标系。你还可以看到在上述例子中,用户坐标系是新建立的-它不是保持像初始用户坐标系和使用viewBox前的视窗坐标系一样。任何svg后代会在这个新的用户坐标系中定位和确定尺寸,而不是初始坐标系。
最后一个viewBox的例子和前一个类似,但是它不是切割画布,我们将在viewport里扩展它并看它如何影响图形。我们将声明一个宽高比视窗大的viewBox,并依然保持viewport的宽高比。我们在下一章里讨论不同的宽高比。
在这个例子中,我们将viewBox的尺寸设为viewport的1.5倍。
- <svg width="800" height="600" viewBox="0 0 1200 900">
- <!-- SVG content drawn onto the SVG canvas -->
- </svg>
现在用户坐标系会被放大到1200*900。它会被映射到视窗坐标系,用户坐标系中的每一个单位水平方向上等于视窗坐标系中的viewport-width / viewBox-width,竖直方向上等于viewport-height / viewBox-height。这意味着,在这种情况下,每一个用户坐标系中的x-units等于viewport坐标系中的0.66个x-units,每个用户y-unit映射成0.66的viewport y-units。
当然,理解这些最好的方法是把结果视觉化。viewBox被缩放到适应下图所示的viewport。因为图形在画布里基于新的用户坐标系绘制的,而不是视窗坐标系,它看起来比视窗小。
到目前为止,我们所有的例子的宽高比都和视窗一致。但是如果viewBox中声明的宽高比和视窗中的不一样会发生什么呢?例如,试想我们把视窗的尺寸设为1000*500。宽高比不再和视窗的一样。在例子中使用viewBox=”0 0 1000 500”的结果如下图:
转载请注明: 文章转载自:爱思资源网 http://www.aseoe.com/show-80-745-1.html