SVG understand the viewport, viewBox, preserveAspectRatio

Read catalog

A: Understanding viewport

This attribute indicates the size of the visible area of ​​SVG. Alternatively, you can call the size of the canvas. Like our computer screens, we can only see the contents of the visible area of ​​the inside of our computer screens, but not to see something other than a computer screen. For example the following code:

<svg width="200" height="200" style="border: 1px solid red"></svg>

As the code, we defined a canvas svg width of 200px, 200px height, the border color is red, a pixel 1, a solid line. Thus the display on the page code is shown below:

As the code, we set the svg canvas size to 200px * 200px, if not with the unit, then the default unit is px (pixels). Of course there are other units: For example:

em: relative to parent element's font size. 
ex: height relative to the 'x' lowercase letters (not used) 
PX: pixel (css2 graphics support system, 96 pixels per inch). 
pt: points (1/72 inch) 
PC: 12 points (1/6 inch). 
cm: cm 
mm: mm 
in: inch

Of course, we can also specify the width and height svg element as a percentage, we svg element when nested inside a div to, then it percentages are relative to the width and height of the outer div element calculated. Of course, if we svg element is the root element, then its percentage is relative to the size of the window to be calculated. For example the following code:

<div style="width:400px;height:400px; border: 1px solid red; ">
  <svg width="20%" height="20%" style="border: 1px solid red;"></svg>
</div>

Results as shown below:

As we can see FIG, we svg width and height of 82px; because the width and height of the div element is 400px; 20%, then, 20% * 400 = 80px; 2px plus the frame, thus a total of 82px.

If we do not have to set the width and height svg then it 300px by default width, height by 150px; following code:

<div style="width:400px;height:400px; border: 1px solid red; ">
  <svg style="border: 1px solid red;"></svg>
</div>

运行的效果如下所示:

理解默认用户坐标

在svg中有一个默认的坐标系统,其中 水平坐标(x坐标)向右递增的,垂直坐标(y坐标)是向下递增的。原点坐标是(0, 0).  该坐标系统类似于我们数学几何中的坐标。

比如我们现在建立一个200px宽,200px高的视口,然后我们在里面绘制一个矩形,该矩形左上角在坐标(10, 10)的位置,该矩形的宽度为50px, 高度为 50px,基本代码如下:

<svg style="border: 1px solid red;" width="200" height="200">
  <rect x="10" y="10" width="50" height="50" style="stroke: black; fill:none;"></rect>
</svg>
<div style="width:100px;height:100px;margin-left:10px;background: red;"></div>

运行效果如下:

如上可以看到,我们在svg上绘制了一个小矩形,矩形的宽度为50px,高度也是为50px,然后该矩形的左上角在坐标(10, 10)的位置,因此该坐标点离右边(x坐标向右是递增的)和下边(y坐标向下是递增的)偏移10px;然后绘制了一个宽度为50px,和高度为50px的小矩形。我们也可以看到我们下面还有一个div元素,设置了 margin-left: 10px; 其实在我们的矩形内部设置了偏移10px,和我们的margin-left 是一个意思的。

二:理解viewBox

viewBox="x, y, w, h"; 该属性的含义是可视区盒子,即画布的可视区。

viewport 和 viewBox 分别有自己的坐标系,默认情况下,该两个坐标系是重合的,即转换关系是 1:1。

x: 指左上角的坐标,y: 左上角的纵坐标,w: 指宽度,h: 指高度

1. 画布(viewport)、可视区(viewBox) 的宽度的高度相等情况

比如如下代码:

<div style="width:100%;display:inline-block;">
  <svg style="border: 1px solid red;" width="400" height="200" viewBox="0,0,400,200">
    <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
  </svg>
</div>

如上代码,svg的画布大小,宽度为400px,高度为200px,然后使用viewBox属性定义画布的可视区的大小宽度也是400px,高度也是200px, 因此该两个坐标系是重合的,因此我们使用 rect 来创建矩形的话,定义宽度和高度分别为100px,x轴和y轴的偏移位置为10px; 效果如下所示:

2. 画布不变,可视区的宽度减小的情况

比如如下代码,可视区的宽度减少100px, 如下代码所示:

<div style="width:100%;display:inline-block;">
  <svg style="border: 1px solid red;" width="400" height="200" viewBox="0,0,300,200">
    <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
  </svg>
</div>
<div style="border: 1px solid red;width:300px;height:200px; margin-left: 60px;"></div>

运行结果如下所示:

如上代码,画布大小的宽度是400px,可视区的宽度变成300px; 因此为了使他们的中心点能重合的话,因此需要向右移动的距离 = 400 - 300 / 2 = 50px; 由于 rect 中的x偏移了10px,因此加起来就是偏移了60px了,可以把下面的div作为参照物即可看到。

如下示意图所示解释

下面我们继续把可视区的宽度改为200px; 如下代码:

<div style="width:100%;display:inline-block;">
  <svg style="border: 1px solid red;" width="400" height="200" viewBox="0,0,200,200">
    <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
  </svg>
</div>
<div style="border: 1px solid red;width:200px;height:200px; margin-left: 110px;"></div>

然后我们运行结果如下所示:

可以看到,矩形需要偏移的距离 = 400-200/2 + 10 = 110px; 从下面的div中的margin-left 我们可以看到 偏移110px的时候,才能使 画布(viewport)和可视区(viewBox)的中心点能够重合。我们可以继续看如下示意图所示:

3. 画布不变,可视区的高度减小的情况

如下代码:

<svg style="float:left;border: 1px solid red;" width="200" height="200" viewBox="0,0,200,100">
  <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>
<div style="float:left; margin-left: 20px; border: 1px solid red;width:200px;height:100px;margin-top:60px"></div>

运行结果如下所示:

如上可以看到,矩形向下偏移的距离 = 200 - 100 / 2 + 10 = 60px; 因此我们可以看到我们的下面的div元素 margin-top:60px; 就可以对齐了。

4. 可视区不变,画布宽度变小

如果可视区不变的话,画布宽度减少的话,那么矩形也要等比例缩小,比如如下代码:

<svg style="float:left;border: 1px solid red;" width="100" height="200" viewBox="0,0,200,200">
  <rect x="0" y="0" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>
<div style="float:left; margin-left: 20px; border: 1px solid red;width:100px;height:200px;margin-top:50px"></div>

运行结果如下所示:

如上可以看到,矩形本来大小是 100px*100px,现在画布的宽度改成100px了,那么矩形也变成原来的一半了,至于向下移动距离的计算 = 200 - 100 / 2 = 50px;

5. 可视区不变,画布的高度变小

可视区不变,画布高度变小的话,那么矩形也要等比例缩放;如下代码所示:

<div style="width:100%;display:inline-block;">
  <svg style="float:left;border: 1px solid red;" width="200" height="80" viewBox="0,0,200,200">
    <rect x="0" y="0" width="100" height="100" style="stroke: black; fill:none;"></rect>
  </svg>
</div>
<div style="margin-top:10px;border: 1px solid red;width:200px;height:80px;margin-left:60px"></div>

如上代码;可视区的高度是画布的 200/80 = 2.5倍, 因此矩形高度也变成原来的2.5倍分之1. 因此计算公司如下:

200     100 
-——  =  ----  = 40px
80       x

因此矩形的宽度和高度等比例缩放到 40px; 偏移的距离计算方式 = 200 - 80 / 2 = 60px; 因此向右偏移 60px 即可。

如下所示:

也就是说,如果画布的高度变小的话,那么偏移是向右的,如果画布的宽度变小,那么偏移是向下的。

6. 可视区宽度和高度大于画布的宽度和高度

如下代码:

<svg style="float:left;border: 1px solid red;" width="45" height="135" viewBox="0,0,200,200">
  <rect x="0" y="0" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>
<div style="float:left;margin-left:20px;border: 1px solid red;width:45px;height:135px;margin-top:46px"></div>

运行结果如下所示:

如果可视区宽度和高度大于画布的宽度和高度的话,那么 矩形的宽度和高度的计算方式以 宽度和高度最小的那个来等比例计算,什么意思呢?我们如上的画布的宽度是45px,高度是135px,那么宽度小于高度,因此需要按照45px来计算,因此计算方式 =

200     100
---  =  ----
45       x 

最后 x = 22.5px 了,由于画布的宽度小于高度,因此需要向下偏移,那么偏移的距离计算方式 = 135 - 45 / 2 = 45px; 因此向下偏移45px即可,至于上面的div元素 margin-top 为46px,那是因为带了一像素边框。

为了验证这个逻辑,我们可以让画布的宽度大于高度,如下代码所示:

<svg style="border: 1px solid red;" width="145" height="43" viewBox="0,0,200,200">
  <rect x="0" y="0" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>
<div style="border: 1px solid red;width:145px;height:43px;margin-top:10px; margin-left: 52px;"></div> 

运行效果如下所示:

矩形的大小计算方式  = 

 200   100
 --- = ---- = 21.5px
  43     x

也就是说 画布的宽度和高度,那个小就根据那个来缩放比例,现在是高度为 43 x, 43px 小于 宽度 145px, 因此 按照高度 43px 来计算,因此最后我们的矩形的等比例缩放的大小为 21.5px; 那么向右偏移的距离 = 145 - 43 / 2 = 51px 了,同理我们上面的div参考元素 margin-left: 52px, 那是因为边框有1px;

但是如果如下代码:

<svg style="border: 1px solid red;" width="145" height="43" viewBox="0,0,200,80">
  <rect x="0" y="0" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>
<div style="border: 1px solid red;width:145px;height:43px;margin-top:10px; margin-left: 19px;"></div>

运行效果如下了:

矩形的计算方式 = 

43      x
---  = ---- = 53.75px
80      100

然后偏移的距离 = 80 - 43 / 2 = 37 / 2 = 19px 左右。

三:理解 preserveAspectRatio

该属性的作用是:它允许我们指定被缩放的图像相对视口的对齐方式。基本的使用方法如下所示:

preserveAspectRatio = "alignment [meet | slice]"

其中 alignment 指定轴和位置,默认值为 preserveAspectRatio = "xMidYMid meet";

preserveAspectRatio 该属性是应用在SVG上,且和viewBox属性配合一起使用的。viewBox属性值可以指明是否可以等比例缩放(宽高比相同的情况下),以扩展到viewport指定的大小区域中。

该对象第一个参数有如下9个不同的值,分别为如下:

xMinYMin,
xMinYMid,
xMinYMax,

xMidYMin,
xMidYMid,
xMidYMax,

xMaxYMin,
xMaxYMid,
xMaxYMax

如上 x 和 y 表示对齐的轴线,x 表示水平方向对象(往右边是正数),y表示纵向对象(往下是正数)。min, mid, max 表示对齐的方式。min 是往坐标小的方向对齐,mid是居中对齐,max是往坐标大的方向对齐。

第二个参数有3个值可选,分别为:meet 和 slice 和 none。

meet 的含义是:viewBox保持等比例缩放,整个viewBox在viewport中都是可见的。在满足2个约束的条件基础上,尽可能的放大viewBox,当viewport的宽高比和viewBox的宽高比不匹配的时候,那么取宽高比中较小的那个。

slice 的含义是:修剪viewBox保持等比例缩放,整个viewport区域会被viewBox覆盖。在满足2个约束的条件基础之上,尽可能的缩小viewBox,当viewport的宽高比和viewBox的宽高比不匹配时,取宽高缩放比中比较大的那个。

none 的含义是:不强制等比例缩放,尽量以viewBox和viewport以实际的宽高比来缩放图形,尽量把宽度和高度扩展到这个viewport上。最后的结果就会使图像变模糊。

我们分别来看下demo:

1. preserveAspectRatio="xMinYMin meet"情况下

强制缩放比例,xMin:viewBox的x轴和viewport的x轴最左边对齐,YMin:viewBox的y轴和viewport的y轴最左边对齐。

如下代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMinYMin meet"
>
  <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

运行效果如下:

如上我们看到,当我们设置 xMinYMin 的时候,意味着 x坐标和y轴坐标在原点上(0, 0)。

2. preserveAspectRatio="xMinYMid meet"情况下

强制缩放比例,xMin:viewBox的x轴和viewport的x轴最左边对齐,YMid:viewBox的y轴和viewport的y轴中点对齐。

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMinYMid meet"
>
  <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

运行效果如下:

示意图如下:

注意: 如上 xMinYMid 和 yMidXMin 效果是不一样的,最前面的优先级最大,所以它会先以上面的 xMin最左端对齐。

3. preserveAspectRatio="xMinYMax meet"情况下

强制缩放比例,xMin:viewBox的x轴和viewport的x轴最左边对齐,YMax:viewBox的y轴和viewport的y轴最下边对齐

如下代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMinYMax meet"
>
  <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

运行效果如下图所示:

示意图如下所示:

4. preserveAspectRatio="xMidYMin meet"情况下

强制缩放比例,xMid:viewBox的x轴的中心和viewport的x轴中心对齐,yMin: viewBox的Y轴最上方和viewport的y轴最上方对齐。

如下代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMidYMin meet"
>
  <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

运行效果如下图所示:

示意图如下所示:

5. preserveAspectRatio="xMidYMid meet"

强制等比例缩放,xMid:viewBox的x轴中点和viewport的x轴中点对齐,YMid: viewBox的y轴中点 和 viewport的y轴中点对齐。

如下代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMidYMid meet"
>
  <rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

运行结果如下所示:

如上代码,画布大小的宽度是400px,可视区的宽度变成300px; 因此为了使他们的中心点能重合的话,因此需要向右移动的距离 = 400 - 300 / 2 = 50px; 由于 rect 中的x偏移了10px,因此加起来就是偏移了60px了,可以把下面的div作为参照物即可看到。

如下示意图所示解释

如上代码是我们之前分析的代码,因为画布是400px,我们的可视区viewBox的宽度变成300px,但是我们的 preserveAspectRatio 的默认属性值为:"xMidYMid meet"; 也就是说 x 轴方向是居中的,y轴方向是居中的,因此他们的中心点是相同的。

6. preserveAspectRatio="xMidYMax meet"

强制等比例缩放,xMid:viewBox的x轴中点和viewport的x轴中点对齐,YMax: viewBox的y轴最下方和 viewport的y轴最下方对齐。

代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMidYMax meet"
>
<rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

效果如下:

如下示意图所示解释

7. preserveAspectRatio="xMaxYMin meet"

强制等比例缩放,xMax:viewBox的x轴和viewport的x轴最右边对齐,YMax: viewBox的y轴和 viewport的y轴最上方对齐。

代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMaxYMin meet"
>
<rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>
<div style="width:100%;display: inline-block;">
  <div style="margin-left:110px;border: 1px solid red;width:300px;height:200px;"></div>
</div>

效果如下:

如下示意图所示解释

如上代码;xMax是指 viewBox的x轴和viewport的x轴最右边对齐,且 YMax: viewBox的y轴和 viewport的y轴最上方对齐。因此如上示意图,如上面使用了div元素来做参考,margin-left:110px; 因为 画布的大小是400px,我们的viewBox 是300px; 且rect元素向右移动了10px; 因此一共就是110px了。

8. preserveAspectRatio="xMaxYMid meet"

强制等比例缩放,xMax:viewBox的x轴和viewport的x轴最右边对齐,YMax: viewBox的y轴和 viewport的y轴中心对齐。

效果和上面第七点是一样的。这里就不多解释了。

9. preserveAspectRatio="xMaxYMax meet"

强制等比例缩放,xMax:viewBox的x轴和viewport的x轴最右边对齐,YMax: viewBox的y轴和 viewport的y轴最下边对齐。
效果和上面第七点是一样的。这里就不多解释了。

10. preserveAspectRatio="xMinYmin slice"

slice 的含义是:修剪viewBox保持等比例缩放,整个viewport区域会被viewBox覆盖。在满足2个约束的条件基础之上,尽可能的缩小viewBox,当viewport的宽高比和viewBox的宽高比不匹配时,取宽高缩放比中比较大的那个。

代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMinYMin slice"
>
<rect x="10" y="10" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

效果如下:

如上我们可以看到我们的矩形的宽度和高度变为 133.33px * 133.33px了,为什么呢?那是因为我们的viewport的宽度是400px,我们的viewBox是300px; 因此 400/300 = 1.33, 因此rect的宽度和高度的大小都需要在原来的宽度和高度都乘以1.33来铺满我们的viewport(画布)的。

11 preserveAspectRatio="xMinYMid slice"

代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMinYMid slice"
>
<rect x="0" y="0" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

效果如下

示意图如下所示:

如上所示:xMin 的含义是:viewport(画布)的x轴与viewBox(可视区)的x轴的最左侧对齐,YMid的含义是:viewport(画布)的Y轴与viewBox(可视区)的Y轴的中心对齐。所以如上所示, 但是由于宽度和高度都等比例放大了,所以结果会向上偏移了。

12. preserveAspectRatio="xMinYMax slice"

代码:

<svg 
  style="border: 1px solid red;" 
  width="400" 
  height="200" 
  viewBox="0,0,300,200" 
  preserveAspectRatio="xMinYMax slice"
>
  <rect x="0" y="0" width="100" height="100" style="stroke: black; fill:none;"></rect>
</svg>

运行效果如下:

其他的略.....  感觉slice这个属性没有理解透。今天先到这....

Guess you like

Origin www.cnblogs.com/tugenhua0707/p/11279989.html
SVG