目录
想象一下画家 (viewBox) 和画框(SVG 的 width 和 height)的关系:
没有 viewBox(只有 width 和 height):
场景三:控制对齐方式 - preserveAspectRatio
上次讲了SVG的使用,在文章末尾讲到了:为什么svg需要 viewBox?
现在就来讲解一下吧。
你可以想象一下画家 (viewBox) 和画框(SVG 的 width 和 height)的关系:
-
没有
viewBox(只有width和height):-
你指定了一个固定大小的画框(例如
width="200" height="100")。 -
画家就在这个画框里作画。一个
circle的cx="100"就是指离画框左边 100个单位 的地方。 -
问题:如果你突然想把画框缩小到
width="50",里面的图形会按比例扭曲压缩,因为它依然认为 100 个单位就是整个宽度。
-
-
有
viewBox:-
画家首先在自己设定的一块虚拟画布上作画,这块虚拟画布的大小由
viewBox定义(例如viewBox="0 0 200 100")。 -
然后,SVG 的
width和height充当了这个虚拟画布的“画框”或“视口”。 -
SVG 渲染器会自动将整个虚拟画布的内容,完美地缩放、拉伸、对齐到物理视口(即
width和height)中。 -
结果:无论外面的“画框”尺寸如何变化,画布内的所有内容都会保持比例地自适应,永远不会扭曲。
-
viewBox语法
viewBox="min-x min-y width height"
min-x,min-y:虚拟画布左上角的坐标(通常为 0, 0)。
width,height:虚拟画布的比例尺。它定义了用户坐标系统,图形中的所有单位都基于这个坐标系。
三种常见场景
场景一:固定尺寸 vs 响应式尺寸
例1A:不使用 viewBox(错误示范)
SVG 被直接塞进一个固定大小的容器,无法自适应。
<svg width="400" height="200" style="border: 1px solid red;">
<circle cx="200" cy="100" r="50" fill="blue"/>
<text x="200" y="100" text-anchor="middle" fill="white">Static</text>
</svg>
<br>
<svg width="100" height="50" style="border: 1px solid red;">
<!-- 同一个SVG代码,但被硬塞进小容器 -->
<circle cx="200" cy="100" r="50" fill="blue"/>
<text x="200" y="100" text-anchor="middle" fill="white">Static</text>
</svg>
效果:第二个小SVG只显示了蓝色圆圈的左上角一小部分,因为它的坐标系还是按照 cx="200" 来算,但容器只有100宽。

例1B:使用 viewBox(正确示范)
我们告诉SVG:“虚拟画布是 400x200 的,请把整个画布的内容放进任何尺寸的容器里”。
<svg viewBox="0 0 400 200" style="width: 400px; height: 200px; border: 1px solid green;">
<circle cx="200" cy="100" r="50" fill="blue"/>
<text x="200" y="100" text-anchor="middle" fill="white">Responsive</text>
</svg>
<br>
<svg viewBox="0 0 400 200" style="width: 100px; height: 50px; border: 1px solid green;">
<!-- 完全相同的SVG代码!只靠CSS和viewBox控制尺寸 -->
<circle cx="200" cy="100" r="50" fill="blue"/>
<text x="200" y="100" text-anchor="middle" fill="white">Responsive</text>
</svg>
效果:两个SVG显示的内容完全一致(一个完整的圆和文字),只是大小不同。第二个SVG自动将整个 400x200 的画布完美缩放到 100x50 的容器里,所有比例都保持正确。

场景二:纯CSS控制响应式SVG
这是最常见的用法。移除内联的 width 和 height 属性,只保留 viewBox,然后完全用CSS来控制其尺寸。
<!-- SVG文件: icon.svg -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>

在HTML中使用:
<style>
.responsive-icon {
width: 2em; /* 尺寸随字体大小变化 */
height: 2em;
fill: currentColor; /* 颜色随文字颜色变化 */
vertical-align: middle;
margin-right: 8px;
}
.container {
resize: both; /* 允许拖拽调整大小 */
overflow: auto;
border: 1px solid #ccc;
padding: 15px;
margin-bottom: 20px;
background-color: #f9f9f9;
}
.bg-svg-container {
/* 这个容器通过CSS背景图方式显示SVG */
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5' fill='%23333'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center;
background-size: contain; /* 关键:确保SVG保持比例 */
height: 100px; /* 设置容器高度 */
}
</style>
<div class="container">
<p>我是一个可调整大小的容器(拖动右下角):</p>
<p>
<svg class="responsive-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>
这个内联SVG图标会随容器大小自动缩放
</p>
</div>
<div class="container bg-svg-container">
<p>这个div使用CSS背景SVG(通过data URI嵌入):</p>
<p>背景SVG也会保持比例,但无法用CSS控制内部样式</p>
</div>
效果:拖动右下角调整文本域的大小,里面的图标会始终完美缩放,保持清晰。

场景三:控制对齐方式 - preserveAspectRatio
有时画布(viewBox)和视口(CSS宽高)的比例不同。默认行为是保持比例,上下或左右留黑(letterbox)。你可以用 preserveAspectRatio 属性控制这个对齐方式。

<svg viewBox="0 0 200 100" preserveAspectRatio="xMidYMid meet" style="width: 300px; border: 1px solid #333;">
<rect x="0" y="0" width="200" height="100" fill="lightblue"/>
<circle cx="100" cy="50" r="40" fill="tomato"/>
</svg>
preserveAspectRatio值解析:
xMidYMid: 在x轴和y轴上都居中对齐。
meet(默认):保持比例,整个viewBox在视口内可见,像“背景包含”。
slice:保持比例,填充整个视口,超出部分被裁剪,像“背景覆盖”。
none:不保持长宽比,图像会被拉伸以完全填充视口。
----------------完--------------
SVG viewBox的作用与应用
1493

被折叠的 条评论
为什么被折叠?



