理解SVG viewport,viewBox,preserveAspectRatio縮放
viewport
表示SVG可見區域的大小,或者可以想象成舞臺大小,畫布大小。
<svg width="500" height="300"></svg>
上面的SVG程式碼定義了一個視區,寬500單位,高300單位。
注意這裡的措辭是“單位”,不是“畫素”。雖然說,width
/height
如果是純數字,使用的就是“畫素”作為單位的。
也就是說,上面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屬性
這個是本文的重點,也是難點。
先看一個活蹦亂跳的例子,如下HTML程式碼:
<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>
結果如下:
如果不看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):
preserveAspectRatio
上面的例子,SVG的寬高比正好和viewBox的寬高比是一樣的,都是4:3
. 顯然,實際應用viewBox
不可能一直跟viewport
穿同一條開襠褲。此時,就需要preserveAspectRatio
出馬了,此屬性也是應用在<svg>
元素上,且作用的物件都是viewBox。
先看下豬是怎麼跑的:
preserveAspectRatio="xMidYMid meet"
下面我們來吃豬肉。
preserveAspectRatio
屬性的值為空格分隔的兩個值組合而成。例如,上面的xMidYMid
和meet
.
第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是大寫。 |
x
, y
自由合體就可以了,如:
xMaxYMax xMidYMid
親愛的小夥伴,看出啥意思沒?
噔噔蹬蹬,沒錯,就是組合的意思:“右-下”和“中-中”對齊。恭喜你此處的知識點學習順利畢業!
preserveAspectRatio
屬性第2部分的值支援下面3個:
值 | 含義 |
---|---|
meet | 保持縱橫比縮放viewBox適應viewport,受 |
slice | 保持縱橫比同時比例小的方向放大填滿viewport,攻 |
none | 扭曲縱橫比以充分適應viewport,變態 |
現在急需一個活生生的例子,讓大家感受下這三個值的表現。
首先,看下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>
截圖效果如下:
表現原理為:SVG寬400
, 高200
,viewBox寬200
, 高200
. x
橫軸比例是2
, y
縱軸比例是1
. meet
的作用是讓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>
此時的顯示效果為:
改成300
後,viewBox的高度就比viewport的200
高,所以,viewBox要想完全適應viewport,就要進行縮放,所以,我們可以上到上面的矩形面積變小了,就是因為縮放的結果(縮放了200/300
, 差不多原來的66.7%
)。
② 如果是slice
, slice
本身就有剪下的意思。程式碼如下:
<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
也是要保持viewBox的縱橫比的,不過,其作用是儘量填滿viewport. 同樣,這裡viewBox寬度200
,SVG的width
是400
. 顯然,要想最大化充滿,viewBox的寬度就需要擴大為原來的兩倍。於是,就有了上圖viewBox放大兩倍後的效果截圖。由於viewBox部分割槽域超出了viewport, 視區之外內容是不可見的,於是就出現了slice
所表意的“剪下”效果。
③
如果是none
, 則表示不關心比例,viewBox直接拉伸到最大填滿viewport.
<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMinnone" style="border:1px solid #cd0000;"> <rect x="10" y="10" width="150" height="150" fill="#cd0000"/> </svg>
糾正,直接屬性值"none"
即可,例如:
<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="none" style="border:1px solid #cd0000;">
<rect x="10" y="10" width="150" height="150" fill="#cd0000"/>
</svg>
預設狀態下,以及使用工具匯出的SVG圖形子啊設定寬高的時候都是保持比例不拉伸的,這對於圖示等尺寸控制非常有用,但如果我們希望SVG圖形像圖片預設行為一樣,寬高設定直接拉伸,就是設定這裡的preserveAspectRatio="none"
即可!
原本好好的一個正方形,現在因為viewBox的拉伸,變成了一個寬高2:1
的矩形了。
viewBox的對齊
千言萬語不如一個可以自己動手體驗的demo實在,您可以狠狠地點選這裡:viewBox的對齊各個名稱表現感受demo
截兩張圖給大家瞅瞅:
無論是meet
還是slice
,你是不可能在一種狀態下同時看到x
, y
方向上的位移的。因為總會有一個方向是充滿viewport的。
結束語
本文是幾乎沒有個人情緒,個人吐槽的一篇基礎技術文章,以滿足不同群體的胃口。
行文倉促,錯誤難免,歡迎糾錯。歡迎交流。
轉載自:http://www.zhangxinxu.com/wordpress/2014/08/svg-viewport-viewbox-preserveaspectratio/