座標系統
SVG存在兩套座標系統:視窗座標系與使用者座標系。預設情況下,使用者座標系與視窗座標系的點是一一對應的,都為原點在視窗的左上角,x軸水平向右,y軸垂直向下;如下圖所示:
SVG的視窗位置一般是由CSS指定,尺寸由SVG元素的屬性width和height設置,但是如果SVG是存儲在embedded對像中(例如object元素,或者其他SVG元素),而且包含SVG的文檔是用CSS或XSL格式化的,而這些外圍物件的CSS或其他指定尺寸的值已經可以計算出視窗的尺寸了,則此時會使用外圍物件的尺寸。
這裡要區分視窗,視窗座標系,使用者座標系的概念:
視窗:指的是網頁上面可視的矩形局域,長度和寬度都是有限的,這個區域一般與外圍對象的尺寸有關。
視窗座標系:本質是一個座標系,有原點,x軸與y軸;而且在兩個方向上是無限延伸的。預設情況下,原點在視窗的左上角,x軸水平向右,y軸垂直向下。可以對這個座標系的點進行變換。
使用者座標系:本質是一個座標系,有原點,x軸與y軸;而且在兩個方向上是無限延伸的。預設情況下,原點在視窗的左上角,x軸水平向右,y軸垂直向下。可以對這個座標系的點進行變換。
預設情況下,視窗座標系與使用者座標係是重合的,但是這裡需要注意,視窗座標係屬於的是創建視窗的元素,視窗座標系確定好以後,整個視窗的座標基調就確定了。但是使用者座標係是屬於每個圖形元素的,只要圖形進行了座標變換,就會創建新的使用者座標系,這個元素中所有的座標和尺寸都使用這個新的使用者座標系。
簡單點說:視窗座標系描述了視窗中所有元素的初始座標概況,使用者座標系描述了每個元素的座標概況,預設情況下,所有元素都使用預設的與視窗座標系重合的那個使用者座標系。
座標空間變換
讓我們回顧一下canvas使用者座標的變換,它們是透過平移,縮放,旋轉函數實現的;每次變換後對以後繪製的圖形都起作用,除非再次進行變換,這是"當前"使用者座標系統的概念。 canvas只有唯一一個使用者座標系。
在SVG中,情況完全不同。 SVG本身作為一種向量圖元素,它的兩個座標系統本質上都可以算作"使用者座標系統";SVG的兩個座標空間都是可以變換的:視窗空間變換和使用者空間變換。視窗空間變換由相關元素(這些元素創建了新的視窗)的屬性viewBox控制;用戶空間變換由圖形元素的transform屬性控制。視窗空間變換應用於對應的整個視窗,使用者空間變換應用於目前元素及其子元素。
視窗轉換 - viewBox屬性
所有的能建立一個視窗的元素(看下一節),再加上marker,pattern,view元素,都有一個viewBox屬性。
viewBox屬性值的格式為(x0,y0,u_width,u_height),每個值之間以逗號或空格隔開,它們共同決定了視窗顯示的區域:視窗左上角座標設為(x0,y0 )、視窗的寬設為u_width,高為u_height;這個變換對整個視窗都起作用。
這裡一定不要混淆:視窗的大小和位置已經由創建視窗的元素和外圍的元素共同確定了(例如最外層的svg元素建立的視窗由CSS,width和height確定),這裡的viewBox其實是設定這個確定的區域能顯示視窗座標系的哪個部分。
viewBox的設定其實是包含了視窗空間的縮放和平移兩種變換。
變換的計算也很簡單:以最外層的svg元素的視窗為例,假設svg的寬與長設定為width,height,viewBox的設定為(x0,y0,u_width,u_height)。則繪製的圖形,寬和高的縮放比例分別為:width/u_width, height/u_height。視窗的左上角的座標設定為了(x0,y0)。
體會下面幾種程式碼所繪製的結果的差異:
在日常工作中,我們經常需要完成的一個任務就是縮放一組圖形,讓它適應它的父容器。我們可以透過設定viewBox屬性來達到這個目的。
能建立新視窗的元素
任何時候,我們都可以嵌套視窗。建立新的視窗的時候,也會建立新的視窗座標系和使用者座標系,當然也包含裁減路徑也會創造新的。下列是能建立新視窗的元素清單:
svg:svg支援巢狀。
symbol:當被use元素實例化的時候創造新的視窗。
image:引用svg元素時會建立新視窗。
foreignObject:建立新視窗去渲染裡面的物件。
保持縮放的比例- preserveAspectRatio屬性
有些時候,特別是當使用viewBox的時候,我們期望圖形佔據整個視窗,而不是兩個方向上按相同的比例縮放。而有些時候,我們卻是希望圖形兩個方向是依照固定的比例縮放的。使用屬性preserveAspectRatio就可以達到控制這個的目的。
這個屬性是所有能建立一個新視窗的元素,再加上image,marker,pattern,view元素都有的。而且preserveAspectRatio屬性只有在該元素設定了viewBox以後才會運作。如果沒有設定viewBox,則preserveAspectRatio屬性會被忽略。
屬性的語法如下:preserveAspectRatio="[defer]
defer:可選參數,只對image元素有效,如果image元素中preserveAspectRatio屬性的值以"defer"開頭,則表示image元素使用引用圖片的縮放比例,如果被引用的圖片沒有縮放比例,則忽略"defer"。所有其他的元素都忽略這個字串。
align:此參數決定了統一縮放的對齊方式,可以取下列值:
none - 不強制統一縮放,這樣圖形才能完整填充整個viewport。
xMinYMin - 強制統一縮放,並且把viewBox中設定的
xMidYMin - 強制統一縮放,並且把vivewBox中X方向上的中點對齊到viewport的X方向中點處,簡言之就是X方向中點對齊,Y方向與上面相同。
xMaxYMin - 強制統一縮放,並且把viewBox中設定的
類似的還有其他類型的值:xMinYMid,xMidYMid,xMaxYMid,xMinYMax,xMidYMax,xMaxYMax。這些組合的含義與上面的幾種情況類似。
meetOrSlice:可選參數,可以去下列值:
meet - 預設值,統一縮放圖形,讓圖形全部顯示在viewport中。
slice - 統一縮放圖形,讓圖形充滿viewport,超出的部分被剪裁掉。
下圖詮釋了各種填充的效果:
使用者座標系的變換 - transform屬性
該類型變換是透過設定元素的transform屬性來指定的。這裡要注意,transform屬性設定的元素的變換,只影響該元素及其子元素,與別的元素無關,不影響別的元素。
平移 - translate
平移變換把相關的座標值平移到指定的位置,該變換需要傳入兩個軸上平移的量。看範例:
旋轉 - rotate
旋轉一個元素也是一個很常見的任務,我們可以使用rotate變換實現,該變換需要傳入旋轉的角度參數。看範例:
傾斜- skew
transform也支援傾斜變換,可以是沿著x軸的(左右傾斜,正角度為向右傾斜,其實是傾斜了y軸),或是沿著y軸的(上下傾斜,正角度為向下傾斜,其實是傾斜了x軸)傾斜;該變換需要傳入一個角度參數,這個角度參數會決定傾斜的角度。看下面的範例:
從結果中,你可以直接看到同樣尺寸的矩形,在不同的傾斜變換後,得到的位置和形狀。這裡注意矩形的起始位置都已經改變了,這是因為在新的座標系統中,(30,30)已經在不同的位置了。
縮放- scale
1
變換鏈
transform屬性支援設定多個變換,這些變換只要中間用空格分開,然後一起放到屬性中就可以了。執行效果跟依序獨立執行這些變換是一樣的。
不帶單位的值被認為帶的是"用戶單位",就是目前使用者座標系的單位值。
帶單位的情況
svg中相關單位與CSS中是相同的:em,ex,px,pt,pc,cm,mm和in。長度也可以使用"%"。
相對度量單位:em和ex也跟CSS一樣,是相對於目前字體的font-size和x-height來說的。
絕對度量單位:一個px是等於一個"用戶單位"的,也就是"5px"與"5"是一樣的。但是一個px是不是對應一個像素,那就看有沒有進行過一些變換了。
其他的幾個單位基本上都是px的倍數:1pt=1.25px,1pc=15px,1mm=3.543307px,1cm=35.43307px,1in=90px。
如果最外層的SVG元素的width和height沒有指定單位(也就是"用戶單位"),則這些值會被認為單位是px。
這篇比較拗口,其實只要記住“圖形元素的坐標和長度指的是,經過視窗坐標系變換和用戶坐標系變換雙重變換後,新用戶坐標系的坐標和長度” 就可以了。
實用參考:
腳本索引:http://msdn.microsoft.com/zh-cn/library/ff971910(v=vs.85).aspx
開發中心:https://developer.mozilla.org/en/SVG
熱門參考:http://www.chinasvg.com/
官方文件:http://www.w3.org/TR/SVG11/