一文搞懂SVG的`viewBox`属性

一文搞懂SVG的viewBox属性

MDN介绍viewBox属性

viewBox 属性允许指定一个给定的一组图形伸展以适应特定的容器元素。

viewBox 属性的值是一个包含 4 个参数的列表 min-x, min-y, width and height,以空格或者逗号分隔开,在用户空间中指定一个矩形区域映射到给定的元素,查看属性preserveAspectRatio

不允许宽度和高度为负值,0 则禁用元素的呈现。

  • min-x:定义了viewBox的最小x坐标。
  • min-y:定义了viewBox的最小y坐标。
  • width:定义了viewBox的宽度。
  • height:定义了viewBox的高度。

viewBox的作用

  1. 缩放viewBox允许SVG图形在不同的尺寸下进行缩放。无论SVG容器的尺寸如何变化,内部的图形都会根据viewBox定义的比例进行缩放。
  2. 定位:通过设置min-xmin-y,你可以控制SVG图形在容器中的位置。例如,你可以将图形移动到容器的中心、左上角或其他任何位置。
  3. 裁剪viewBox还可以用于裁剪SVG内容,只显示定义区域内的部分。

情况一:已设置svg固定尺寸

画图理解原理

MDN给出的解释,如果不加以实践,是不能直观的理解viewBox概念的,实践才是理解概念的唯一标准。

首先,绘制一个正常的矩形1:300*300,绿色背景,红色边框的矩形,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
		svg {
			display: inline-block;
            border: 1px solid red;
			}
	</style>
</head>
<body style="padding: 200px;">
    <svg width="300" height="300"  >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
</body>
</html>

运行结果为
在这里插入图片描述
然后,绘制矩形2,给svg增加viewBox属性,设置viewBox="0 0 300 300"

<body style="padding: 200px;">
    <svg width="300" height="300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 300 300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
</body>

在这里插入图片描述

如果将viewBox属性的四个值设置为0,0,svgWidth,svgHeight最终视图显示与矩形1一样,无法理解viewBox工作原理
接着,绘制矩形3,修改viewBox="0,0,100,100"

<body style="padding: 200px;">
    <svg width="300" height="300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 300 300" >
       <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 100 100" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
</body>

在这里插入图片描述

三个矩形无任何差别,肉眼无法分辨出差异。此时打开开发者工具,观察矩形3的尺寸大小。可以很明显的看的矩形3的实际尺寸已经到900,svg仅仅显示的是矩形的1/9。这里可以猜测

矩形实际宽度 = svg宽度 / viewBox宽度 * 矩形理论宽度
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c35b708476914cae9c5a871488c1df6a.png#pic_center) 最后,绘制矩形4,令`viewBox=0,0,600,600`,如果上述猜想正确,这一次的矩形的宽高 =` 300/600*300=150`,最终应该显示`150*150`的矩形。
<body style="padding: 200px;">
    <svg width="300" height="300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 300 300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 100 100" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 600 600" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
</body>

在这里插入图片描述

猜想正确,viewBox的宽高与SVG内部元素之间的宽高之间的关系弄明白了,尝试着修改一下viewBox的起始坐标。
接着,绘制矩形5,viewBox="150,150,300,300",依然保持宽高为150不变。

<body style="padding: 200px;">
    <svg width="300" height="300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 300 300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 100 100" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="0 0 600 600" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
    <svg width="300" height="300" viewBox="150 150 300 300" >
        <rect x="0" y="0" width="300" height="300" fill="#47cc47" />
    </svg>
</body>

在这里插入图片描述
根据上图,可见矩形4和矩形5居然一样,但是矩形5的rect节点宽高是300*300,而矩形4的是150*150

情况二:未设置svg固定尺寸

如果没有对svg设置固定尺寸,并且使用了viewBox属性。这种用法多用于响应式图表。

两坐标均等于0

这里讨论两坐标均等于0(min-x=0,min-y=0)情况,即视图框(viewBox)的起始点在坐标原点(0,0)

在矩形1中,添加一个圆,半径=4。这里矩形完全填充svg

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			html,
			body {
				height: 100%;
			}
			svg {
				height: 50%;
				display: inline-block;
			}
		</style>
	</head>
	<body>
		<svg viewBox="0 0 100 100">
			<rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
			<circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
		</svg>
	</body>
</html>

在这里插入图片描述
当使用相对单位时,如百分比、视觉尺寸,无论是否使用viewBox,正方形的外观都不会改变。 使用大viewBox时,圆圈看起来很小。因为它使用用户单位作为r属性:4远小于viewBox中设置的100。

为了进行对比,画矩形2。令viewBox="0 0 10 10"r=4不变。

<body>
    <svg viewBox="0 0 100 100">
        <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
        <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
    </svg>
     <svg viewBox="0 0 10 10">
        <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
        <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
    </svg>
</body>

在这里插入图片描述
使用小viewBox时,圆圈看起来很大。因为它使用用户单位作为r属性:4仅小于viewBox中设置的10。所以矩形2中的圆相对于viewBox尺寸更大。

两坐标有中至少一个小于0

讨论一种特殊情况,当viewBox起始位置为负数时,请看矩形3。

<body>
    <svg viewBox="0 0 100 100">
        <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
        <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
    </svg>
     <svg viewBox="0 0 10 10">
        <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
        <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
    </svg>
    <svg viewBox="-5 -5 10 10">
        <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
        <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
    </svg>
</body>

在这里插入图片描述
可以看到,矩形3已经移到视图的右下角,这是怎么回事呢?

这是因为viewBox属性则定义了SVG内部的坐标系统。视图框(viewBox)的起始点始终为svg的左上角。这个起始点的位置,要相对于屏幕左上角而言。理论见下图。
在这里插入图片描述
由于viewBox="-5 -5 10 10",x=-5,则视图框的起始点向右移动5的单位;y=-5,视图框的起始点向下移动5个单位。此时视图框的起始点正好位于视口的中心。并且100%仍然解析为10个用户单位的宽度或高度,因此矩形看起来已移动到视口的底部/右角。坐标点0,0位于视口中心时,圆心中点值50%解析为5,这意味着圆心为在视口的底部/右角。为什么显示的是1/4个圆角?因为整个视图大小依然是从0 0 10 10范围不变,原来svg偏移后得到新的svg;两者之间的交集部分就形成了1/4圆角。这就是viewBox裁剪SVG的原理,只显示定义区域内的部分。

有了上面原理,就可以实现任意裁剪的视图,只显示定义区域内的部分。例如显示上半圆部分:

<svg viewBox="0 -5 10 10">
    <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
    <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
</svg>

原理图如下:
在这里插入图片描述
显示左半圆(读者自己画理论图):

<svg viewBox="-5 0 10 10">
    <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
    <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
</svg>

在这里插入图片描述
显示右下角1/4圆(读者自己画理论图):

<svg viewBox="5 5 10 10">
    <rect x="0" y="0" width="100%" height="100%" fill="#47cc47" />
    <circle cx="50%" cy="50%" r="4" fill="#3c4acc" />
</svg>

在这里插入图片描述

配合preserveAspectRatio属性使用

有时候,通常我们使用 viewBox 属性时,希望图形拉伸占据整个视口。在其他情况下,为了保持图形的长宽比,必须使用统一的缩放比例。

preserveAspectRatio 属性表示是否强制进行统一缩放。

对于非标签,preserveAspectRatio 只适用于在同一元素上为 viewBox 提供的值。对于这些元素,如果没有提供属性 viewBox,则忽略了 preserveAspectRatio。也就是说,只有设置了viewBox属性,preserveAspectRatio才会起作用。

使用:

<svg viewBox="5 5 10 10" preserveAspectRatio="<align> [<meetOrSlice>]" />

align

<align> 属性值表示是否强制统一缩放,当 SVG 的 viewbox 属性与视图属性宽高比不一致时使用。<align> 属性的值一定是下列的值之一:

  • none 不会进行强制统一缩放,如果需要,会缩放指定元素的图形内容,使元素的边界完全匹配视图矩形。(注意:如果 <align> 的值是 none ,则 <meetOrSlice> 属性的值将会被忽略。)
  • xMinYMin - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的最小值与视图的 X 的最小值对齐。将 SVG 元素的 viewbox 属性的 Y 的最小值与视图的 Y 的最小值对齐。
  • xMidYMin - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的中点值与视图的 X 的中点值对齐。将 SVG 元素的 viewbox 属性的 Y 的最小值与视图的 Y 的最小值对齐。
  • xMaxYMin - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的最小值 + 元素的宽度与视图的 X 的最大值对齐。将 SVG 元素的 viewbox 属性的 Y 的最小值与视图的 Y 的最小值对齐。
  • xMinYMid - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的最小值与视图的 X 的最小值对齐。将 SVG 元素的 viewbox 属性的 Y 的中点值与视图的 Y 的中点值对齐。
  • xMidYMid (默认值) - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的中点值与视图的 X 的中点值对齐。将 SVG 元素的 viewbox 属性的 Y 的中点值与视图的 Y 的中点值对齐。
  • xMaxYMid - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的最小值 + 元素的宽度与视图的 X 的最大值对齐。将 SVG 元素的 viewbox 属性的 Y 的中点值与视图的 Y 的中点值对齐。
  • xMinYMax - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的最小值与视图的 X 的最小值对齐。将 SVG 元素的 viewbox 属性的 Y 的最小值 + 元素的高度与视图的 Y 的最大值对齐。
  • xMidYMax - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的中点值与视图的 X 的中点值对齐。将 SVG 元素的 viewbox 属性的 Y 的最小值 + 元素的高度与视图的 Y 的最大值对齐。
  • xMaxYMax - 强制统一缩放。将 SVG 元素的 viewbox 属性的 X 的最小值 + 元素的宽度与视图的 X 的最大值对齐。将 SVG 元素的 viewbox 属性的 Y 的最小值 + 元素的高度与视图的 Y 的最大值对齐。

meetOrSlice

<meetOrSlice> 是可选的,如果提供的话,与 <align> 间隔一个或多个的空格,参数所选值必须是以下值之一:

  • meet(默认值) - 图形将缩放到:

    • 宽高比将会被保留
    • 整个 SVG viewbox 在视图范围内是可见的
    • 尽可能的放大 SVG viewbox,同时仍然满足其他的条件。

    在这种情况下,如果图形的宽高比和视图窗口不匹配,则某些视图将会超出 viewbox 范围(即 SVG viewbox 视图将会比可视窗口小)。

  • slice-图形将缩放到:

    • 宽高比将会被保留
    • 整个视图窗口将覆盖 viewbox
    • SVG viewbox 属性将会被尽可能的缩小,但是仍然符合其他标准。

    在这种情况下,如果 SVG 的 viewbox 宽高比与可视区域不匹配,则 viewbox 的某些区域将会延伸到视图窗口外部(即 SVG viewbox 将会比可视窗口大)。

彩蛋

你以为读完了这篇博客你就弄懂了viewBox吗?不妨一起思考如下问题:
我们的上述例子中viewBox的宽度和高度都是成比例缩放的,假如

SVG的宽度 / viewBox的宽度 != SVG的高度 / viewBox的高度

SVG会如何缩放画布大小?

如果读取有兴趣可以自行尝试,或者催更我。

iewbox `属性将会被尽可能的缩小,但是仍然符合其他标准。

在这种情况下,如果 SVG 的 `viewbox `宽高比与可视区域不匹配,则 `viewbox `的某些区域将会延伸到视图窗口外部(即 `SVG `的 `viewbox `将会比可视窗口大)。

彩蛋

你以为读完了这篇博客你就弄懂了viewBox吗?不妨一起思考如下问题:
我们的上述例子中viewBox的宽度和高度都是成比例缩放的,假如

SVG的宽度 / viewBox的宽度 != SVG的高度 / viewBox的高度

SVG会如何缩放画布大小?

如果读取有兴趣可以自行尝试,或者催更我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值