深刻理解 SVG 系列(二) —— SVG 座標系統

這一篇是講 SVG 的座標系統,在這以前若是你對 SVG 的基礎知識還不是很瞭解,能夠先點這裏學習 深刻理解 SVG 系列(一) —— SVG 基礎html

網格座標系

和不少計算機繪圖所使用的座標系統同樣,SVG 也使用了網格座標系統。這種座標系有以下幾個特色:segmentfault

  1. 以左上角爲座標系的原點(0,0)
  2. X 軸的正方向向右,從 0,0 點開始向右, x 逐漸增大。Y 軸的正方向向下,從 0,0 點開始向下, y 逐漸增大。
  3. 座標以像素爲單位

Canvas_default_grid.png

<svg width="100" height="100" style="outline: 2px solid red">
    <rect x="0" y="0" width="50" height="50" fill='green'/>
</svg>
以 0,0 爲起始點,畫一個 100 * 100 的矩形

初始座標系

上面咱們提到了畫布和視窗分別對應兩個座標系,一個視窗座標系,一個用戶座標系。這兩個座標系都具備咱們上面提到的網格座標系的幾個特色。svg

  • 視窗座標系就是創建在視窗上的座標系,
  • 用戶座標系是創建在 SVG 畫布上的座標系,也稱當前座標系

這兩個座標系一開始是徹底重合的,它們的原點和座標都是徹底一致的,也就是說初始用戶座標系的原點就位於視窗的左上角,也是 X 軸正向向右,Y 軸正向向下。學習

雖然一開始它們是兩個徹底同樣的座標系,但既然是兩個座標系,就意味着它們能夠是不同的。你能夠經過 viewBox 去改變這種默認對齊的方式,接下來的內容會講到。spa

viewBox

以前的章節中,咱們全部的 SVG 內容看起來都像是基於視圖座標系來繪製的,由於初始視窗座標系和初始用戶座標系徹底相同,但在這一節中,咱們會經過 viewBox 來聲明本身的用戶座標系。3d

viewBox 是用來把 SVG 內容繪製到畫布上的座標系。它的字面意思是視圖盒子,只有出如今這個盒子區域裏面的 SVG 內容才能被看到,你能夠理解爲 SVG 圖形真正的可見區域。code

viewBox 語法

viewBox = <min-x> <min-y> <width> <height>

viewBox 接收四個參數值,分別是 min-xmin-ywidthheighthtm

min-xmin-y 決定了 viewBox 的左上角,widthheight 決定了 viewBox 的寬和高。注意 width 或 height 若是設置成 0 ,會禁止元素的渲染。blog

一個實例

<svg width="100" height="100" viewBox="0 0 50 50">
    <!-- SVG content -->
</svg>

設置 viewBox="0 0 50 50" 以後會發生什麼?ci

  1. 聲明一個特定的區域,原點爲左上角的 0,0 點,寬 50px,高 50px。
  2. 將 SVG 內容繪製到畫布上,可是隻有這個特定的區域可見。
  3. 區域被縮放,以適應整個 SVG 視窗。
  4. 用戶座標系被映射到視窗座標系,這裏一個用戶單位至關於兩個視窗單位。效果就是經過 SVG 視窗看到的 SVG 圖形變大了。

平移

經過改變 min-x 和 min-y 的值能夠將 viewBox 聲明的區域進行平移。

以座標點 0,0 爲圓心,半徑爲 50px 畫一個圓,咱們只能看到圓的 1/4,如圖一:

<svg width=100 height=100 style="outline: 2px solid red">
    <circle cx=0 cy=0 r=50 fill="green"/>
</svg>

image

圖一

經過設置 viewBox="-50 -50 100 100",咱們能夠看到一整個圓。以下圖:

<svg width=100 height=100 style="outline: 2px solid red">
    <circle cx=0 cy=0 r=50 fill="green"/>
</svg>

image

圖二

經過 viewBox 的 min-xmin-y 兩個參數,咱們將 viewBox 聲明的區域分別向左和上進行了平移,這時咱們以 0,0 爲圓心,半徑爲 50 畫圓,正好可以將整個圓顯示到 viwBox 聲明的區域中,而後再將這個座標系映射到 100px * 100px 的視窗中,就大功告成了。

image

縮放

經過改變 width 和 height 的值能夠縮放 viewBox 聲明的區域。

<svg width=100 height=100 style="outline: 2px solid red">
    <circle cx=0 cy=0 r=50 fill="green"/>
</svg>

image

當 viewBox 的寬高小於視窗的寬高時,至關於放大。

<svg width=100 height=100 viewBox="0 0 50 50" style="outline: 2px solid red">
    <circle cx=0 cy=0 r=50 fill="green"/>
</svg>

image

當 viewBox 的寬高大於視窗的寬高時,至關於縮小。

<svg width=100 height=100 viewBox="0 0 200 200" style="outline: 2px solid red">
    <circle cx=0 cy=0 r=50 fill="green"/>
</svg>

image

經過百分比和 viewBox 讓 SVG 圖形進行縮放

由於多設備適配的需求,不少時候咱們指望 SVG 圖形可以在不一樣的屏幕上放大或縮小,可是咱們又不但願每次都去修改 <svg>widthheight,這時百分比就很是有用了。

若是給視窗設置 width: 100%height: 100%,那麼視窗的寬高就由它父元素的寬高決定,咱們能夠經過調整其父元素的寬高來放大和縮小 SVG 視窗,而不用修改 <svg> 的 width 和 height。僅僅是這樣還不夠,咱們還須要經過 viewBox 來將 SVG 圖形放大到整個視窗區域。

<div style="width:100px; height:100px;"> // 你能夠試着經過修改 div 的寬高來改變 SVG 圖形的大小
    <svg width="100%" height="100%" style="outline: 2px solid red" viewBox="0 0 100 100">
        <rect x="0" y="0" width="100" height="100" fill="green"/>
    </svg>
</div>

小練習

  1. 利用 viewBox 實現上半圓

    <svg width=100 height=100 viewBox="-50 -100 100 100" style="outline: 2px solid red">
        <circle cx=0 cy=0 r=50 fill="green"/>
    </svg>
    在紙上畫出 viewBox 聲明的區域,以下圖:

    image

    橙色區域爲 viewBox 聲明的區域,從粉色的區域移動到橙色區域能夠得出 viewBox 的 min-x = -50 min-y = -100,在這個區域只有上半圓可見,所以咱們最後看到的也就只是這個上半圓。
  2. 請參考第一題,在紙上畫出下面 SVG 的座標系,在座標系上畫出每一個元素,以及 viewBox 的區域。

    <svg width=100 height=100 viewBox="0 -50 100 100" style="outline: 2px solid red">
        <circle cx=0 cy=0 r=50 fill="green"/>
    </svg>

    image

preserveAspectRatio

preserveAspectRatio 屬性用來強制統一縮放比,以保持圖形的寬高比。

若是 viewBox 的寬高比和 SVG 視窗的寬高比不一樣,那麼在拉伸 viewBox 來適應視窗的時候,就可能致使 SVG 圖形發生扭曲。這個時候 preserveAspectRatio 就派上用場了。

preserveAspectRatio 語法

preserveAspectRatio = <align> <meetOrSlice>?
  • align 表示 viewBox 如何與 viewport 對齊。
  • meetOrSlice 是可選的,表示如何保持寬高比。

align

align 的值有不少,爲了方便理解,咱們先把它最基本的值拆分出來,以下:

含義
none 經過拉伸 viewBox 來適應整個視窗,無論寬高比
xMin viewBox 和 viewport 左邊緣對齊
xMid viewBox 和 viewport x 軸中心對齊
xMax viewBox 和 viewport 右邊緣對齊
YMin viewBox 和 viewport 上邊緣對齊
YMid viewBox 和 viewport y 軸中心對齊
YMax viewBox 和 viewport 下邊緣對齊

而後再自由組合 x,y 就能能夠了,好比:

xMinYMin => 左-上對齊
xMidYmid => 中-中對齊

meetOrSlice

含義
meet 保持寬高比縮放 viewBox 以適應 viewport,相似於 background-size: contain
slice 保持寬高比同時比例小的方向放大填滿 viewport,相似於 background-size: cover

例子

<svg width="200" height="100" viewBox="0 0 100 100" style="outline: 2px solid red">
    <rect x=10 y=10 width=50 height=50 fill="green"/>
</svg>

image

在上面的例子中,咱們並無設置 preserveAspectRatio ,可是根據咱們以前講過的知識,不難發如今 <svg> 上做用着一個隱形的 preserveAspectRatio="xMidYMid meet"

<svg width="200" height="100" viewBox="0 0 100 100" style="outline: 2px solid red" preserveAspectRatio="xMidYMid meet">
    <rect x=10 y=10 width=50 height=50 fill="green"/>
</svg>

image

那麼 preserveAspectRatio="xMidYMid meet" 是如何做用在 SVG 上的呢?請看下面的圖:

image

上圖中 viewport 寬 200 高 100,viewBox 寬 100 高 100, x 橫軸比例是 2, y 縱軸比例是 1。
xMidYMid 讓 viewBox 和 viewPort 的中心對齊,和 viewport y 軸上邊緣對齊。
meet 的做用是讓 viewBox 保持寬高比的同時,徹底在 viewport 中顯示。
由於這裏最小的縱向比例是 1 ,因此 viewBox 沒有任何的縮放。

爲了更好的去感覺縮放,咱們將 viewBox 的寬度從 100 調整到 300,其它保持不變。

<svg width="200" height="100" viewBox="0 0 300 100" style="outline: 2px solid red" preserveAspectRatio="xMinYMin meet">
    <rect x=10 y=10 width=50 height=50 fill="green"/>
</svg>

這時 viewBox 的寬度超過 viewport 的寬度了(如圖一),因此 viewBox 就會縮小以適應 viewport,由於 meet 會讓 viewBox 保持比例來進行縮放,因此你能夠想象成按住viewBox 的右下角,縮小 viewBox 至 viewport 的大小 (如圖二)。

image

說完了 meet 下面咱們再來講說 slice, slice 雖然會保持寬高比進行縮放,可是會在比例小的方向放大填滿 viewport。好比設置 viewBox 寬 100 高 100,viewport 寬 200 高 100,在 viewport 的 x 軸方向還有空間,因此會將 viewBox 在橫軸上進行放大,結果就是咱們的好好的正方形被拉成了矩形。

<svg width="200" height="100" viewBox="0 0 100 100" style="outline: 2px solid red" preserveAspectRatio="xMidYMid slice">
    <rect x=10 y=10 width=50 height=50 fill="green"/>
</svg>

image

結尾

在學習 SVG 的過程當中,動手畫圖真的很是的重要。這也是爲何我一直嘗試圖解 SVG,在以前的練習中也要求你們去畫圖的緣由。畫圖可以幫助你去理解 SVG 的座標系,理解每個元素或者每個屬性在座標系中是怎樣體現出來的。因此但願你們在學習 SVG 的過程當中,多去動手畫圖,最後達到可以「裸寫」 SVG 的境界!

相關文章
相關標籤/搜索