关于SVG的viewBox和preserveAspectRatio的一些迷思

605 阅读3分钟

一、SVG的viewBox指啥

得先明确svg视口是啥,MDN里说svg的视口是svg图片的可视区域,可以用svg的heightwidth属性设置svg视口大小,当然也可以从父元素那里继承过来heightwidth的值。而svg的viewBox属性用来设置svg内元素如何展示,相当于又开了一个窗口,将窗口里的元素按照一定规则映射到视口中。

来上代码,我们定义了一个视口大小为200*200的svg,里面有一个100*50的红色矩形块,且位置在坐标(10, 20)处。

html

<svg width="200" height="200">
  <rect width="100" height="50" x="10" y="20" fill="red"></rect>
</svg>

css

svg {
  background-color: black;
}

运行结果是:

image.png

如果在svg标签中加入viewBox属性为:

<svg width="200" height="200" viewBox="0 0 100 100">

就会得到如下结果:

image.png

原因是:

image.png 灰色透明部分就是viewBox,相当于viewBox截取了svg画布上的一部分,再放大到和svg视口一样的大小,所以红色矩形看起来放大了一倍,并且超过视口部分就不可见了。

viewBox的四个属性min-xmin-ywidth 和 height分别代表:

  • viewBox左上角的那个原点在svg元素的x轴上的坐标
  • 在y轴上的坐标
  • viewBox的宽度
  • viewBox的高度

而x、y轴是这样的:

image.png

让我们试试viewBox为(0 0 400 400)的情况:

image.png

同样图解为:

image.png

相当于svg画布自动将viewBox空余的部分补齐了,然后viewBox再缩小到svg画布大小,所以看起来红色矩形缩小了一倍。

二、svg的preserveAspectRatio属性是啥

以上都是viewBox宽高比和svg画布宽高比一致的情况,如果viewBox的宽高比例和svg的不一样呢?让我们来看看这个例子:

image.png 上图viewBox是宽比高为2的矩形,可以看到viewBox按照自己原有的宽高比例截取了svg画布区域,然后将其放在画布中间,形成最终的效果。而决定viewBox是否缩放以及缩放后的位置的,就是preserveAspectRatio属性。

preserveAspectRatio用于定义viewBox取得区域后的位置摆放以及视口空白如何处理,包括两个属性,第一个就是描述位置的,值可以为none、xMinYmin、xMidYMid、xMaxYMax、xMinYMax等等;第二个是描述如何处理空白的,可为meetslicepreserveAspectRatio的默认值是xMidYMid meet,比如上面介绍viewBox部分的示例图,虽然没有设置preserveAspectRatio属性,但也默认其为xMidYMid meetxMidYMid意思是将 SVG 元素的 viewbox 属性的 X 的中点值与视图的 X 的中点值对齐;将 SVG 元素的 viewbox 属性的 Y 的中点值与视图的 Y 的中点值对齐(这句话来自于MDN) 我理解的是这样:

image.png 而如果设置的是xMinYMax,那么就会如下一样对齐:

image.png

meet则表示viewBox在svg可视窗口内,尽可能地放大,但不能超过svg视口。

image.png 如果是slice则如下图,表示viewBox尽可能地缩小,但不能小到覆盖不了svg视口。

image.png

ok以上就是对svg的viewBox和preserveAspectRatio的介绍~总的来说这两个属性共同决定了svg画布上的元素如何展示/映射在视口中。