理解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>
相關文章
相關標籤/搜索