溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

HTML5中SVG視窗坐標(biāo)系與用戶坐標(biāo)系及變換是怎樣的

發(fā)布時(shí)間:2021-10-08 14:57:07 來源:億速云 閱讀:132 作者:柒染 欄目:web開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)HTML5中SVG視窗坐標(biāo)系與用戶坐標(biāo)系及變換是怎樣的,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

坐標(biāo)系統(tǒng)
SVG存在兩套坐標(biāo)系統(tǒng):視窗坐標(biāo)系與用戶坐標(biāo)系。默認(rèn)情況下,用戶坐標(biāo)系與視窗坐標(biāo)系的點(diǎn)是一一對(duì)應(yīng)的,都為原點(diǎn)在視窗的左上角,x軸水平向右,y軸豎直向下;如下圖所示: 

HTML5中SVG視窗坐標(biāo)系與用戶坐標(biāo)系及變換是怎樣的

SVG的視窗位置一般是由CSS指定,尺寸由SVG元素的屬性width和height設(shè)置,但是如果SVG是存儲(chǔ)在embedded對(duì)象中(例如object元素,或者其他SVG元素),而且包含SVG的文檔是用CSS或者XSL格式化的,并且這些外圍對(duì)象的CSS或者其他指定尺寸的值已經(jīng)可以計(jì)算出視窗的尺寸了,則此時(shí)會(huì)使用外圍對(duì)象的尺寸。

這里需要區(qū)分視窗,視窗坐標(biāo)系,用戶坐標(biāo)系的概念:

視窗:指的是網(wǎng)頁(yè)上面可視的矩形局域,長(zhǎng)度和寬度都是有限的,這個(gè)區(qū)域一般與外圍對(duì)象的尺寸有關(guān)。

視窗坐標(biāo)系:本質(zhì)是一個(gè)坐標(biāo)系,有原點(diǎn),x軸與y軸;而且在兩個(gè)方向上是無限延伸的。默認(rèn)情況下,原點(diǎn)在視窗的左上角,x軸水平向右,y軸豎直向下。可以對(duì)這個(gè)坐標(biāo)系的點(diǎn)進(jìn)行變換。

用戶坐標(biāo)系:本質(zhì)是一個(gè)坐標(biāo)系,有原點(diǎn),x軸與y軸;而且在兩個(gè)方向上是無限延伸的。默認(rèn)情況下,原點(diǎn)在視窗的左上角,x軸水平向右,y軸豎直向下??梢詫?duì)這個(gè)坐標(biāo)系的點(diǎn)進(jìn)行變換。

默認(rèn)情況下,視窗坐標(biāo)系與用戶坐標(biāo)系是重合的,但是這里需要注意,視窗坐標(biāo)系屬于的是創(chuàng)建視窗的元素,視窗坐標(biāo)系確定好以后,整個(gè)視窗的坐標(biāo)基調(diào)就確定了。但是用戶坐標(biāo)系是屬于每個(gè)圖形元素的,只要圖形進(jìn)行了坐標(biāo)變換,就會(huì)創(chuàng)建新的用戶坐標(biāo)系,這個(gè)元素中所有的坐標(biāo)和尺寸都使用這個(gè)新的用戶坐標(biāo)系。

簡(jiǎn)單點(diǎn)說:視窗坐標(biāo)系描述了視窗中所有元素的初始坐標(biāo)概況,用戶坐標(biāo)系描述了每個(gè)元素的坐標(biāo)概況,默認(rèn)情況下,所有元素都使用默認(rèn)的與視窗坐標(biāo)系重合的那個(gè)用戶坐標(biāo)系。

坐標(biāo)空間變換
讓我們回顧一下canvas用戶坐標(biāo)的變換,它們是通過平移,縮放,旋轉(zhuǎn)函數(shù)實(shí)現(xiàn)的;每次變換后對(duì)以后繪制的圖形都起作用,除非再次進(jìn)行變換,這是"當(dāng)前"用戶坐標(biāo)系統(tǒng)的概念。canvas只有唯一一個(gè)用戶坐標(biāo)系。
在SVG中,情況完全不同。SVG本身作為一種向量圖元素,它的兩個(gè)坐標(biāo)系統(tǒng)本質(zhì)上都可以算作"用戶坐標(biāo)系統(tǒng)";SVG的兩個(gè)坐標(biāo)空間都是可以變換的:視窗空間變換和用戶空間變換。視窗空間變換由相關(guān)元素(這些元素創(chuàng)建了新的視窗)的屬性viewBox控制;用戶空間變換由圖形元素的transform屬性控制。視窗空間變換應(yīng)用于對(duì)應(yīng)的整個(gè)視窗,用戶空間變換應(yīng)用于當(dāng)前元素及其子元素。

視窗變換 - viewBox屬性

所有的能建立一個(gè)視窗的元素(看下一節(jié)),再加上marker,pattern,view元素,都有一個(gè)viewBox屬性。

viewBox屬性值的格式為(x0,y0,u_width,u_height),每個(gè)值之間用逗號(hào)或者空格隔開,它們共同確定了視窗顯示的區(qū)域:視窗左上角坐標(biāo)設(shè)為(x0,y0)、視窗的寬設(shè)為u_width,高為u_height;這個(gè)變換對(duì)整個(gè)視窗都起作用。

這里一定不要混淆:視窗的大小和位置已經(jīng)由創(chuàng)建視窗的元素和外圍的元素共同確定了(例如最外層的svg元素建立的視窗由CSS,width和height確定),這里的viewBox其實(shí)是設(shè)置這個(gè)確定的區(qū)域能顯示視窗坐標(biāo)系的哪個(gè)部分。
viewBox的設(shè)置其實(shí)是包含了視窗空間的縮放和平移兩種變換。

變換的計(jì)算也很簡(jiǎn)單:以最外層的svg元素的視窗為例,假設(shè)svg的寬與長(zhǎng)設(shè)置為width,height,viewBox的設(shè)置為(x0,y0,u_width,u_height)。則繪制的圖形,寬和高的縮放比例分別為:width/u_width, height/u_height。視窗的左上角的坐標(biāo)設(shè)置為了(x0,y0)。

體會(huì)下面幾種代碼繪出的結(jié)果的不同:

代碼如下:


<svg width="200" height="200" viewBox="0 0 200 200">
<rect x="0" y="0" width="200" height="200" fill="Red" />
<rect x="0" y="0" width="100" height="100" fill="Green" />
</svg>


上面的例子繪制的圖中你可以看到綠色和紅色的矩形,這種情況下視窗坐標(biāo)系的點(diǎn)還是與視窗上的點(diǎn)是一一對(duì)應(yīng)的,這個(gè)也是默認(rèn)情況。

代碼如下:


<svg width="200" height="200" viewBox="0 0 100 100">
<rect x="0" y="0" width="200" height="200" fill="Red" />
<rect x="0" y="0" width="100" height="100" fill="Green" />
</svg>


上面的例子繪制的圖中這個(gè)你只能看到綠色的矩形,而且綠色的矩形顯示在屏幕上是200*200像素的,這個(gè)時(shí)候坐標(biāo)點(diǎn)已經(jīng)不是一一對(duì)應(yīng)了,圖被放大了。

代碼如下:


<svg width="200" height="200" viewBox="0 0 400 400">
<rect x="0" y="0" width="200" height="200" fill="Red" />
<rect x="0" y="0" width="100" height="100" fill="Green" />
</svg>


上面的例子繪制的圖中,視窗坐標(biāo)系的單位被縮小,所以兩個(gè)矩形都縮小了。

在日常工作中,我們經(jīng)常需要完成的一個(gè)任務(wù)就是縮放一組圖形,讓它適應(yīng)它的父容器。我們可以通過設(shè)置viewBox屬性達(dá)到這個(gè)目的。

建立新視窗的元素
任何時(shí)候,我們都可以嵌套視窗。創(chuàng)建新的視窗的時(shí)候,也會(huì)創(chuàng)建新的視窗坐標(biāo)系和用戶坐標(biāo)系,當(dāng)然也包括裁減路徑也會(huì)創(chuàng)建新的。下列是能建立新視窗的元素列表:
svg:svg支持嵌套。
symbol:當(dāng)被use元素實(shí)例化的時(shí)候創(chuàng)建新的視窗。

image:引用svg元素時(shí)會(huì)創(chuàng)建新視窗。
foreignObject:創(chuàng)建新視窗去渲染里面的對(duì)象。

保持縮放的比例 - preserveAspectRatio屬性
有些時(shí)候,特別是當(dāng)使用viewBox的時(shí)候,我們期望圖形占據(jù)整個(gè)視窗,而不是兩個(gè)方向上按相同的比例縮放。而有些時(shí)候,我們卻是希望圖形兩個(gè)方向是按照固定的比例縮放的。使用屬性preserveAspectRatio就可以達(dá)到控制這個(gè)的目的。
這個(gè)屬性是所有能建立一個(gè)新視窗的元素,再加上image,marker,pattern,view元素都有的。而且preserveAspectRatio屬性只有在該元素設(shè)置了viewBox以后才會(huì)起作用。如果沒有設(shè)置viewBox,則preserveAspectRatio屬性會(huì)被忽略。
屬性的語(yǔ)法如下:preserveAspectRatio="[defer] <align> [<meetOrSlice>]"
注意3個(gè)參數(shù)之間需要使用空格隔開。
defer:可選參數(shù),只對(duì)image元素有效,如果image元素中preserveAspectRatio屬性的值以"defer"開頭,則意味著image元素使用引用圖片的縮放比例,如果被引用的圖片沒有縮放比例,則忽略"defer"。所有其他的元素都忽略這個(gè)字符串。
align:該參數(shù)決定了統(tǒng)一縮放的對(duì)齊方式,可以取下列值:
  none - 不強(qiáng)制統(tǒng)一縮放,這樣圖形能完整填充整個(gè)viewport。
  xMinYMin - 強(qiáng)制統(tǒng)一縮放,并且把viewBox中設(shè)置的<min-x>和<min-y>對(duì)齊到viewport的最小X值和Y值處。
  xMidYMin - 強(qiáng)制統(tǒng)一縮放,并且把vivewBox中X方向上的中點(diǎn)對(duì)齊到viewport的X方向中點(diǎn)處,簡(jiǎn)言之就是X方向中點(diǎn)對(duì)齊,Y方向與上面相同。
  xMaxYMin - 強(qiáng)制統(tǒng)一縮放,并且把viewBox中設(shè)置的<min-x> + <width>對(duì)齊到viewport的X值最大處。
  類似的還有其他類型的值:xMinYMid,xMidYMid,xMaxYMid,xMinYMax,xMidYMax,xMaxYMax。這些組合的含義與上面的幾種情況類似。
meetOrSlice:可選參數(shù),可以去下列值:
  meet - 默認(rèn)值,統(tǒng)一縮放圖形,讓圖形全部顯示在viewport中。
  slice - 統(tǒng)一縮放圖形,讓圖形充滿viewport,超出的部分被剪裁掉。

下圖詮釋了各種填充的效果:

HTML5中SVG視窗坐標(biāo)系與用戶坐標(biāo)系及變換是怎樣的

用戶坐標(biāo)系的變換 - transform屬性
該類型變換是通過設(shè)置元素的transform屬性來指定的。這里需要注意,transform屬性設(shè)置的元素的變換,只影響該元素及其子元素,與別的元素?zé)o關(guān),不影響別的元素。

平移 - translate
平移變換把相關(guān)的坐標(biāo)值平移到指定的位置,該變換需要傳入兩個(gè)軸上平移的量。看例子:

代碼如下:


<rect x="0" y="0" width="10" height="10" transform="translate(30,40)" />


這個(gè)例子繪制一個(gè)矩形,并把它的起點(diǎn)(0,0)平移到(30,40)處。雖然可以直接設(shè)置(x,y)的坐標(biāo)值,但是使用平移變換去實(shí)現(xiàn)也很方便。這個(gè)變換第二個(gè)參數(shù)可以省略,默認(rèn)當(dāng)0處理。

旋轉(zhuǎn) - rotate
旋轉(zhuǎn)一個(gè)元素也是一個(gè)很常見的任務(wù),我們可以使用rotate變換實(shí)現(xiàn),該變換需要傳入旋轉(zhuǎn)的角度參數(shù)??蠢樱?br/>

代碼如下:


<rect x="20" y="20" width="20" height="20" transform="rotate(45)" />


這個(gè)例子會(huì)顯示一個(gè)旋轉(zhuǎn)45度的矩形。有幾點(diǎn)注意:
1.這里的變換是以角度值為參數(shù)的。
2.旋轉(zhuǎn)指的是相對(duì)于x軸的旋轉(zhuǎn)。
3.旋轉(zhuǎn)是圍繞用戶坐標(biāo)系的原點(diǎn)(0,0)展開的。

傾斜 - skew
transform還支持傾斜變換,可以是沿著x軸的(左右傾斜,正角度為向右傾斜,其實(shí)是傾斜了y軸),或者是沿著y軸的(上下傾斜,正角度為向下傾斜,其實(shí)是傾斜了x軸)傾斜;該變換需要傳入一個(gè)角度參數(shù),這個(gè)角度參數(shù)會(huì)決定傾斜的角度??聪旅娴睦樱?br/>

代碼如下:


<svg width="100" height="100">
 <rect x="0" y="0" width="100" height="100" fill="green" />
 <circle cx="15" cy="15" r="15" fill="red" />
 <circle cx="15" cy="15" r="15" fill="yellow" transform="skewX(45)" />
 <rect x="30" y="30" width="20" height="20"  />
 <rect x="30" y="30" width="20" height="20" transform="skewX(45)"  />
 <rect x="30" y="30" width="20" height="20" transform="skewY(45)"  />
</svg>


從結(jié)果中,你可以直接看到同樣尺寸的矩形,在不同的傾斜變換后,得到的位置和形狀。這里注意矩形的起始位置都已經(jīng)改變了,這是因?yàn)樵谛碌淖鴺?biāo)系統(tǒng)中,(30,30)已經(jīng)在不同的位置了。

縮放 - scale
縮放對(duì)象由縮放變換完成,該變換接受2個(gè)參數(shù),分別指定在水平和豎直上的縮放比例,如果第二個(gè)參數(shù)省略則與第一個(gè)參數(shù)取相同的值??聪旅娴睦樱?br/>

代碼如下:


<svg width="500" height="500">
<text x="20" y="20" font-size="20">ABC (scale)</text>
<text x="50" y="50" font-size="20" transform="scale(1.5)">ABC (scale)</text>
</svg>


變換矩陣 - matrix
學(xué)過圖形學(xué)的都知道,所有的變換其實(shí)都是由矩陣表征的,所以上面的變換其實(shí)都可以用一個(gè)3*3矩陣去表示:

代碼如下:


a c e
b d f
0 0 1


由于只有6個(gè)值用到了,所以也簡(jiǎn)寫成[a b c d e f]。把matrix(a,b,c,d,e,f)賦給transfrom就可以實(shí)施相應(yīng)的變換。變換會(huì)把坐標(biāo)和長(zhǎng)度都轉(zhuǎn)換成新的尺寸。上面各種變換對(duì)應(yīng)的矩陣如下:

平移變換[1 0 1 0 tx ty]:

代碼如下:


1 0 tx
0 1 ty
0 0 1


縮放變換[sx 0 0 sy 0 0]:

代碼如下:


sx 0 0
0 sy 0
0  0 1


旋轉(zhuǎn)變換[cos(a) sin(a) -sin(a) cos(a) 0 0]:

代碼如下:


cos(a) -sin(a) 0
sin(a) cos(a)  0
 00     1


沿X軸的傾斜[1 0 tan(a) 1 0 0]:

代碼如下:


1 tan(a) 0
0   1    0
0   0    1


沿Y軸的傾斜[1 tan(a) 0 1 0 0]:

代碼如下:


11 0
tan(a) 1 0
00 1


變換本質(zhì)
前面我們總結(jié)canvas的時(shí)候,我們知道各種變換都是作用在用戶坐標(biāo)系上的。在SVG中,所有的變換也都是針對(duì)兩個(gè)坐標(biāo)系(本質(zhì)上都是"用戶坐標(biāo)系")的。當(dāng)給容器對(duì)象或圖形對(duì)象指定"transform"屬性,或者給"svg,symbol,marker,pattern,view"指定"viewBox"屬性以后,SVG會(huì)根據(jù)當(dāng)前的用戶坐標(biāo)系統(tǒng)進(jìn)行變換,去創(chuàng)建新的用戶坐標(biāo)系,并作用于當(dāng)前的對(duì)象以及它的子對(duì)象。該對(duì)象中指定的坐標(biāo)和長(zhǎng)度的單位不再是1:1的對(duì)應(yīng)到外圍的坐標(biāo)系,而是隨著變形,轉(zhuǎn)換到新的用戶坐標(biāo)系中;這個(gè)新的用戶坐標(biāo)系是只作用于當(dāng)前的元素及其子元素。

變換鏈
transform屬性支持設(shè)置多個(gè)變換,這些變換只要中間用空格分開,然后一起放到屬性中就可以了。執(zhí)行效果跟按順序獨(dú)立執(zhí)行這些變換是一樣的。

代碼如下:


<g transform="translate(-10,-20) scale(2) rotate(45) translate(5,10)">
 <!-- graphics elements go here -->
</g>


上面的效果與下面的一樣:

代碼如下:


<g transform="translate(-10,-20)">
 <g transform="scale(2)">
   <g transform="rotate(45)">
<g transform="translate(5,10)">
 <!-- graphics elements go here -->
</g>
   </g>
 </g>
</g>


單位
最后說一下單位,任何坐標(biāo)和長(zhǎng)度都可以帶和不帶單位。
不帶單位的情況

不帶單位的值被認(rèn)為帶的是"用戶單位",就是當(dāng)前用戶坐標(biāo)系的單位值。
帶單位的情況

svg中相關(guān)單位與CSS中是一樣的:em,ex,px,pt,pc,cm,mm和in。長(zhǎng)度還可以使用"%"。
相對(duì)度量單位:em和ex也與CSS中一樣,是相對(duì)于當(dāng)前字體的font-size和x-height來說的。
絕對(duì)度量單位:一個(gè)px是等于一個(gè)"用戶單位"的,也就是"5px"與"5"是一樣的。但是一個(gè)px是不是對(duì)應(yīng)一個(gè)像素,那就看有沒有進(jìn)行過一些變換了。
其他的幾個(gè)單位基本都是px的倍數(shù):1pt=1.25px,1pc=15px,1mm=3.543307px,1cm=35.43307px,1in=90px。

如果最外層的SVG元素的width和height沒有指定單位(也就是"用戶單位"),則這些值會(huì)被認(rèn)為單位是px。

這一篇比較拗口,其實(shí)只要記住“圖形元素的坐標(biāo)和長(zhǎng)度指的是,經(jīng)過視窗坐標(biāo)系變換和用戶坐標(biāo)系變換雙重變換后,新用戶坐標(biāo)系的坐標(biāo)和長(zhǎng)度”就可以了。

關(guān)于HTML5中SVG視窗坐標(biāo)系與用戶坐標(biāo)系及變換是怎樣的就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI