理解SVG中的 viewport,viewBox, preserveAspectRatio

閱讀目錄css

一:理解viewportsvg

該屬性表示的是SVG可見區域的大小。或者也能夠叫畫布的大小。就比如咱們的電腦屏幕,咱們只能看到咱們電腦屏幕的可視區裏面的內容,可是看不到電腦屏幕以外的內容。好比以下代碼:字體

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

如上代碼,咱們定義了一個svg的畫布,寬度爲200px,高度爲200px,邊框的顏色爲紅色,1像素,實線。所以該代碼的顯示效果在頁面上顯示以下:spa

如上代碼,咱們設置了svg的畫布大小爲200px*200px, 若是沒有帶單位的話,該單位默認是 px(像素)。固然也有其餘單位:好比:3d

em: 相對於父元素的字體大小。
ex: 相對於小寫字母的 'x' 的高度(不經常使用)
px: 像素(在支持css2的圖形系統中,每英寸爲96像素)。
pt: 點(1/72英寸)
pc: 12點(1/6英寸)。
cm: 釐米
mm: 毫米
in: 英寸

固然咱們還能夠指定svg元素的width和height爲百分比,當咱們的svg元素嵌套在一個div裏面去的話,那麼它的百分比是相對於外層的div元素的寬度和高度進行計算的。固然若是咱們的svg元素爲根元素的話,那麼它的百分比是相對於窗口的尺寸來計算的。好比以下代碼:code

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

效果以下所示:對象

如上圖咱們能夠看到,咱們的svg的寬度和高度爲82px; 由於div元素的寬度和高度爲400px; 20%的話,20% * 400 = 80px; 再加上2px的邊框,所以一共82px。blog

若是咱們沒有給svg設置寬度和高度的話,它默認的寬度爲300px,高度爲150px; 以下代碼:數學

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

運行的效果以下所示:io

理解默認用戶座標

在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這個屬性沒有理解透。今天先到這....

相關文章
相關標籤/搜索