理解SVG的viewport,viewBox,preserveAspectRatio

viewport

表示SVG可见区域的大小,或者能够想象成舞台大小,画布大小。html

<svg width="500" height="300"></svg>

上面的SVG代码定义了一个视区,宽500单位,高300单位。svg

注意这里的措辞是“单位”,不是“像素”。虽说,width/height若是是纯数字,使用的就是“像素”做为单位的。wordpress

也就是说,上面SVG的视区大小就是500px * 300px.工具

固然,故弄“单位”这个措辞,潜台词就是你可使用其余类型的单位,涵盖常见CSS单位:学习

单位 含义
em 相对于父元素的字体大小
ex 相对于小写字母"x"的高度
px 相对于屏幕分辨率而不是视窗大小:一般为1个点或1/72英寸
in inch, 表英寸
cm centimeter, 表厘米
mm millimeter, 表毫米
pt 1/72英寸
pc 12点活字,或1/12点
% 相对于父元素。正常状况下是经过属性定义自身或其余元素

除了SVG自己,其余一些元素,例如<rect>width/height属性也可使用上面的这些单位,也是默认单位是像素。字体

viewBox属性

这个是本文的重点,也是难点。spa

先看一个活蹦乱跳的例子,以下HTML代码:3d

<svg width="400" height="300" viewBox="0,0,40,30" style="border:1px solid #cd0000;">
    <rect x="10" y="5" width="20" height="15" fill="#cd0000"/>
</svg>

结果以下:code

 

 

或者亲自围观demoorm

若是不看viewBox, 你必定会以为诧异——SVG尺寸明明有400*300像素,而小小的<rect>大小只有其1/20,可是显示出来的却占据了半壁江山!不科学啊!

OK, 之因此小小矩形大显神威就是这里的viewBox起了推波助澜的做用。

viewBox值有4个数字:

viewBox="x, y, width, height"  // x:左上角横坐标,y:左上角纵坐标,width:宽度,height:高度

viewBox顾名思意是“视区盒子”的意思,比如在说:“SVG啊,要不你就让我铺满你吧~”

更形象的解释就是:SVG就像是咱们的显示器屏幕,viewBox就是截屏工具选中的那个框框,最终的呈现就是把框框中的截屏内容再次在显示器中全屏显示!

更直观的解释:
1. 若是没有viewBox, 应该是长这样的:

<rect>大小只有整个SVG舞台的1/20.

2. viewBox="0,0,40,30"至关于在SVG上圈了下图左上角所示的一个框框:

3. 而后把这个框框,连同框框里的小矩形一块儿放大到整个SVG大小(以下gif):
gif演示区域面积扩大

到手里的才是本身的,您能够狠狠地点击这里:SVG viewBox属性原理分步演示demo

demo操做截图示意

preserveAspectRatio

上面的例子,SVG的宽高比正好和viewBox的宽高比是同样的,都是4:3. 显然,实际应用viewBox不可能一直跟viewport穿同一条开裆裤。此时,就须要preserveAspectRatio出马了,此属性也是应用在<svg>元素上,且做用的对象都是viewBox

先看下猪是怎么跑的:

preserveAspectRatio="xMidYMid meet"

下面咱们来吃猪肉。

preserveAspectRatio属性的值为空格分隔的两个值组合而成。例如,上面的xMidYMidmeet.

第1个值表示,viewBox如何与SVG viewport对齐;第2个值表示,如何维持高宽比(若是有)。

其中,第1个值又是由两部分组成的。前半部分表示x方向对齐,后半部分表示y方向对齐。家族成员以下:

含义
xMin viewport和viewBox左边对齐
xMid viewport和viewBox x轴中心对齐
xMax viewport和viewBox右边对齐
YMin viewport和viewBox上边缘对齐。注意Y是大写。
YMid viewport和viewBox y轴中心点对齐。注意Y是大写。
YMax viewport和viewBox下边缘对齐。注意Y是大写。

xy自由合体就能够了,如:

xMaxYMax

xMidYMid

亲爱的小伙伴,看出啥意思没?

噔噔蹬蹬,没错,就是组合的意思:“右-下”和“中-中”对齐。恭喜你此处的知识点学习顺利毕业!

preserveAspectRatio属性第2部分的值支持下面3个:

含义
meet 保持纵横比缩放viewBox适应viewport,受
slice 保持纵横比同时比例小的方向放大填满viewport,攻
none 扭曲纵横比以充分适应viewport,变态

如今急需一个活生生的例子,让你们感觉下这三个值的表现。

您能够狠狠地点击这里:meet,slice,none功能演示demo

首先,看下SVG代码:

<svg width="400" height="200" viewBox="0 0 200 200" style="border:1px solid #cd0000;">
    <rect x="10" y="10" width="150" height="150" fill="#cd0000"/>
</svg>

截取SVG左边一半(200正好宽度400的通常)做为视区,里面有个150*150的红色矩形。

默认展现以下:
默认效果

若是我估计没错,默认应该是"xMidYmid meet"效果。

① 若是是meet效果,代码以下:

<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet" style="border:1px solid #cd0000;">
    <rect x="10" y="10" width="150" height="150" fill="#cd0000"/>
</svg>

截图效果以下:
meet效果

表现原理为:SVG宽400, 高200,viewBox宽200, 高200x横轴比例是2y纵轴比例是1meet的做用是让viewBox等比例的同时,彻底在SVG的viewport中显示。这里,最小比例是纵向的1,因此,实际上viewBox并无任何的缩放。

咱们只要对viewBox属性值作一点小小的修改(200→300),就能够感觉到缩放了:

<svg width="400" height="200" viewBox="0 0 200 300" preserveAspectRatio="xMinYMin meet" style="border:1px solid #cd0000;">
    <rect x="10" y="10" width="150" height="150" fill="#cd0000"/>
</svg>

此时的显示效果为:
viewBox高度改为300后的效果

改为300后,viewBox的高度就比viewport的200高,因此,viewBox要想彻底适应viewport,就要进行缩放,因此,咱们能够上到上面的矩形面积变小了,就是由于缩放的结果(缩放了200/300, 差很少原来的66.7%)。

 若是是sliceslice自己就有剪切的意思。代码以下:

<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin slice" style="border:1px solid #cd0000;">
    <rect x="10" y="10" width="150" height="150" fill="#cd0000"/>
</svg>

效果截图:
slice值下的效果

slice也是要保持viewBox的纵横比的,不过,其做用是尽可能填满viewport. 一样,这里viewBox宽度200,SVG的width400. 显然,要想最大化充满,viewBox的宽度就须要扩大为原来的两倍。因而,就有了上图viewBox放大两倍后的效果截图。因为viewBox部分区域超出了viewport, 视区以外内容是不可见的,因而就出现了slice所表意的“剪切”效果。

 若是是none, 则表示不关心比例,viewBox直接拉伸到最大填满viewport.

<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin none" style="border:1px solid #cd0000;">
    <rect x="10" y="10" width="150" height="150" fill="#cd0000"/>
</svg>

none时候的拉伸填充效果

本来好好的一个正方形,如今由于viewBox的拉伸,变成了一个宽高2:1的矩形了。

viewBox的对齐
千言万语不如一个能够本身动手体验的demo实在,您能够狠狠地点击这里:viewBox的对齐各个名称表现感觉demo

截两张图给你们瞅瞅:
viewBox对齐demo的截图
viewBox对齐演示demo的截图

不管是meet仍是slice,你是不可能在一种状态下同时看到xy方向上的位移的。由于总会有一个方向是充满viewport的。

结束语

本文是几乎没有我的情绪,我的吐槽的一篇基础技术文章,以知足不一样群体的胃口。

行文仓促,错误不免,欢迎纠错。欢迎交流。

行文参考:SVG Viewport and View Box

本文为原创文章,会常常更新知识点以及修正一些错误,所以转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=4323

 
一个全面的例子,能够下来本身在结合文章在细细体验一下:以下
<!DOCTYPE html><html>    <head>        <title>ViewBox 使用演示</title>        <style>            body {                background: #eee;            }            svg {                position: absolute;                border: 1px solid green;                width: 300px;                height: 200px;                left: 50%;                top: 50%;                margin-top: -100px;                margin-left: -150px;                background: white;            }            input[type=number] {                width: 50px;            }        </style>    </head>    <body>        <h1>ViewBox 演示</h1>        <form id="form">            <fieldset>                <legend>viewBox</legend>                <label>x: <input id="vx" type="number" value="0"></label>                <label>y: <input id="vy" type="number" value="0"></label>                <label>width: <input id="vw" type="number" value="300"></label>                <label>height: <input id="vh" type="number" value="200"></label>            </fieldset>            <fieldset>                <legend>preserveAspectRatio</legend>                <label>align: <select id="align">                    <option value="none">none</option>                    <option value="xMinYMin">xMinYMin</option>                    <option value="xMidYMin">xMidYMin</option>                    <option value="xMaxYMin">xMaxYMin</option>                    <option value="xMinYMid">xMinYMid</option>                    <option value="xMidYMid" selected>xMidYMid</option>                    <option value="xMaxYMid">xMaxYMid</option>                    <option value="xMinYMax">xMinYMax</option>                    <option value="xMidYMax">xMidYMax</option>                    <option value="xMaxYMax">xMaxYMax</option>                </select></label>                <label>meetOrSlice: <select id="meetOrSlice">                    <option value="meet">meet</option>                    <option value="slice">slice</option>                </select></label>            </fieldset>        </form>        <p>            <svg id="svg" xmlns="http://www.w3.org/2000/svg">                <!--Face-->                <circle cx="100" cy="100" r="90" fill="#39F" />                <!--Eyes-->                <circle cx="70" cy="80" r="20" fill="white" />                <circle cx="130" cy="80" r="20" fill="white" />                <circle cx="65" cy="75" r="10" fill="black" />                <circle cx="125" cy="75" r="10" fill="black"/>                <!--Smile-->                <path d="M 50 140 A 60 60 0 0 0 150 140"                     stroke="white" stroke-width="3" fill="none" />                <rect id="viewBoxIndicator" stroke="red" stroke-width="3.5" fill="none" />            </svg>        </p>        <script>            function update() {                var viewBox =  [vx.value, vy.value, vw.value, vh.value].join(' ');                var preserveAspectRatio = [align.value, meetOrSlice.value].join(' ');                svg.setAttribute('viewBox', viewBox);                svg.setAttribute('preserveAspectRatio', preserveAspectRatio);                var rect = viewBoxIndicator;                rect.setAttribute('x', vx.value);                rect.setAttribute('y', vy.value);                rect.setAttribute('width', vw.value);                rect.setAttribute('height', vh.value);            }            form.addEventListener('input', update);            update();        </script>    </body></html>
相关文章
相关标签/搜索