深入解析SVG 标签的 viewBox属性(超详细)

3 篇文章 0 订阅
2 篇文章 0 订阅

解析SVG 标签的 viewBox属性

案情提要

相信小伙伴们在学习 svg标签viewBox属性 时候,无论是看w3cschool还是 MDN的官方文档,都是一头雾水。比如MDN给出的解释:viewBox 属性允许指定一个给定的一组图形伸展以适应特定的容器元素。viewBox 属性的值是一个包含 4 个参数的列表 min-x, min-y, width and height,以空格或者逗号分隔开,在用户空间中指定一个矩形区域映射到给定的元素。我当时也是尝尽了苦头,绕了很大的弯子才弄懂其中的奥秘。下面我将我的探究成果分享给大家。
先说结论
在这里插入图片描述

话不多说,直接开干

viewBox属性的值是一组相对的值,
我们首先创建一个svg标签,然后规定其宽高为300px*300px(下面我们都用这个大小的svg),绘制其边框,内部再绘制一个矩形,宽高为100px*100px(这个矩形的宽高也不变)。我们只对viewBox的值进行改变。

  1. 设置viewBox="0 0 300 300"
    <svg width="300px" height="300px" viewBox="0 0 300 300" style="border: 1px solid red;">
        <rect width="100" height="100" fill="green"></rect>
    </svg>
    

在这里插入图片描述
       这里的矩形dom为其设置的原始大小。

  1. 现在设置viewBox="0 0 100 100"
    <svg width="300px" height="300px" viewBox="0 0 100 100" style="border: 1px solid red;">
       <rect width="100" height="100" fill="green"></rect>
    </svg>
    

在这里插入图片描述

现在可以发现,第一次矩形渲染出的dom宽度 / 其原始大小 = 第一次svg的width / 第一次viewBox的width = 1;现在矩形放大到原来的3倍,此恰好svg的width / viewBox的width = 3,是不是可以猜想:svg内部的缩放比例就等同于 svg的width / viewBox的width(现在宽高都设置成比例一致的,后面再设置成不同的来探究)。下面进行验证。

  1. 设置viewBox="0 0 150 150"
    <svg width="300px" height="300px" viewBox="0 0 150 150" style="border: 1px solid red;">
    	<rect width="100" height="100" fill="green"></rect>
    </svg>
    
    在这里插入图片描述
    现在,svg的width / viewBox的width = 2,渲染出来的dom节点的宽高变为原来的2倍,遵循我们的假设。如果我们再放大一些呢(超出svg的大小)?
  2. 设置viewBox="0 0 50 50"
    <svg width="300px" height="300px" viewBox="0 0 50 50" style="border: 1px solid red;">
         <rect width="100" height="100" fill="green"></rect>
    </svg>
    
    在这里插入图片描述
    现在,svg的width / viewBox的width = 6,渲染出来的dom节点的宽高变为原来的6倍,遵循我们的假设。那如果我们将渲染出来的图形进行缩小呢?
  3. viewBox="0 0 600 600"
    <svg width="300px" height="300px" viewBox="0 0 600 600" style="border: 1px solid red;">
     	<rect width="100" height="100" fill="green"></rect>
    </svg>
    
    在这里插入图片描述
    同样的,svg的width / viewBox的width = 0.5,渲染出来的dom节点的宽高变为原来的0.5倍,遵循我们的假设。事实证明我们的假设是成立的。
    现在呢,我们想到,这个属性有四个参数,但是我们使用控制变量法,前面两个参数为0,只考虑了后面两个参数,那么前面两个参数的作用是什么呢?

追踪——前面两个参数的作用

前提:我们将原先元素的宽高设置保持不变,只改变viewBox的值。

  1. 设置viewBox="50 50 100 100"
    <svg width="300px" height="300px" viewBox="50 50 100 100" style="border: 1px solid red;">
      	<rect x="0" y="0" width="100" height="100" fill="green"></rect>
    </svg>
    

在这里插入图片描述
这时候我们会发现,渲染的dom大小好像跟之前 viewBox="0 0 100 100"时候的dom大小一致,而且在svg元素中的部分是整个dom的1/4,那么这种位置的变化规律是什么呢?我们多试几次再总结。

  1. 设置viewBox="50 50 150 150"
    <svg width="300px" height="300px" viewBox="50 50 150 150 style="border: 1px solid red;">
      	<rect x="0" y="0" width="100" height="100" fill="green"></rect>
    </svg>
    
    在这里插入图片描述
    这次我们同样看到,在svg元素中的部分是整个dom的1/4,而且渲染出的dom大小仍然遵循之前的规律。这是个巧合吗?那我们再试一组。
  2. viewBox="50 50 200 200"
        <svg width="300px" height="300px" viewBox="50 50 200 200" style="border: 1px solid red;">
          	<rect x="0" y="0" width="100" height="100" fill="green"></rect>
        </svg>
    	~~~
    

在这里插入图片描述
这次我们得到同样的结果,在svg元素中的部分是整个dom的1/4,而且渲染出的dom大小仍然遵循之前的规律。所以我们可以知道,viewBox的前面两个参数对缩放的倍数无影响。此时我们改变前两个参数试试。

  1. viewBox=" 50 100 300 300"
    <svg width="300px" height="300px" viewBox="50 100 300 300" style="border: 1px solid red;">
      	<rect x="0" y="0" width="100" height="100" fill="green"></rect>
    </svg>
    

在这里插入图片描述
这里我们发现,第一个参数控制横向移动的距离,第二个参数控制纵向的移动距离,正方向为左、上。那么移动的距离是如何计算的呢?我们发现,前面放大的倍数虽然不同,但是我们的 viewBox前两个参数没变内部 rect 元素的设置的宽高也没变,但是都是很巧合地均有 1/4 渲染在了 svg 元素中,所以这里的viewBox前两个参数效果有两种可能,要么是具体的像素值,然后在缩放之前进行移动,要么就是存在某种比例关系,在缩放之后移动。下面我们继续进行分析:

  1. viewBox="100 100 300 300"
    <svg width="300px" height="300px" viewBox="20 20 100 100" style="border: 1px solid red;">
      	<rect x="0" y="0" width="100" height="100" fill="green"></rect>
    </svg>
    

在这里插入图片描述
通过这个,如果 上述第一种假设(前两个参数是具体值,先移动,再放大)的话,移动完之后的中心点是(30,30),放大之后的被隐藏掉的部分的宽就应该是 100 * 3 - 30 = 270,但是现在是60,所以这种假设不成立。
现在来验证第二种假设,先放大,那么放大之后的中心点的坐标为(150,150),再进行移动,移动的距离为 20 /100 * 3 = 60,符合事实。那么细心的朋友就会问了,为什么之前的数据刚好对的上呢,是因为 50 这个数字,既可以在第一种假设中充当50px,又可以在后面的缩放中充当 50% 这个比例, 50% * 100 =50,这是一个巧合。
所以我们现在弄清楚viewBox四个参数的作用:后面两个与缩放的倍数有关,前面两个与缩放之后移动的比例有关。

回想——如果宽高的放大的倍数不一致呢

现在我们弄清楚了这四个参数的作用。当时我们留下一个问题,就是缩放时,宽高比不一致该如何呢?

  1. 设置viewBox="0 0 50 100"
    在这里插入图片描述
    渲染的dom的宽高是初始宽高的 3倍,这里 svg的width / viewBox的width = 6svg的height/ viewBox的height = 3,所以我们猜测是按照较小的倍数进行缩放。下面进行验证:
  2. 设置viewBox="0 0 150 100"
    在这里插入图片描述
    上述比值较小的为 2,这个也放大到了原来的 2倍。那我们要是缩小呢?
  3. 设置viewBox="0 0 600 1200"
    在这里插入图片描述
    这里比值较小的为 1/4,渲染出来的dom也是原来的 1/4,由此可以证实结论:如果对应的宽高不一致的话,那么按照比值较小的那个比例进行缩放。

(不过,细心的朋友们会发现,这里并没有在左上角对齐,这里就与<svg>的另一个属性preserverAspectRatio有关系了,这里我们先不讨论)

结案

我们终于将“案情”查了个水落石出,下面就来对“案子”进行总结:
假设有如下svg元素:

<svg width="width-1" height="height-1" viewBox="min-x min-y width-2 height-2">
	/* 内部元素…… */
	<rect width="width-3" height="height-3" fill="green"></rect>
</svg>

那么,内部元素就会先按照 width-1 / width-2height-1 / height-2较小的那个比例进行缩放(假设这个较小的比例为 m),然后在缩放的基础上,水平方向上移动 min-x / width-3 * m 个像素,正值向左移动,负值向右移动,竖直方向上移动 min-y / height-3 * m 个像素,正值向上移动,负值向下移动(这两个方向与通常情况下的坐标系的正方向相反)。最后感谢大家能够看到这里,不妨留下一个三连吧✨!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值