理解SVG坐標(biāo)系和變換(第一部分)-viewport漓穿,viewBox,和preserveAspectRatio
(本文轉(zhuǎn)自w3cplus,這里僅修正了部分個(gè)人認(rèn)為翻譯不恰當(dāng)之處;下面是譯文鏈接,英文原文鏈接在結(jié)尾處提供)
- 理解SVG坐標(biāo)系和變換(第一部分)-viewport崖媚,viewBox亦歉,和preserveAspectRatio
- 理解SVG坐標(biāo)系和變換(第二部分)-transform屬性
- 理解SVG坐標(biāo)系和變換(第三部分)-建立新視口
SVG元素不像HTML元素一樣由CSS盒模型管理。這使得我們可以更加靈活定位和變換這些元素-也許一眼看上去不太直觀至扰。然而鳍徽,一旦你理解了SVG坐標(biāo)系和變換,操縱SVG會(huì)非常簡(jiǎn)單并且很有意義敢课。本篇文章中我們將討論控制SVG坐標(biāo)系的最重要的三個(gè)屬性:viewport阶祭, viewBox, 和 preserveAspectRatio直秆。
這是本系列三篇文章中的第一篇濒募,這篇文章討論SVG中的坐標(biāo)系和變換。
為了使文中的內(nèi)容和解釋更形象化圾结,我創(chuàng)建了一個(gè)互動(dòng)演示瑰剃,你可以任意改變viewBox 和 preserveAspectRatio的值。
這個(gè)例子只是主要內(nèi)容的一小部分筝野,所以看完請(qǐng)回來(lái)繼續(xù)閱讀這篇文章
SVG畫(huà)布
canvas是繪制SVG內(nèi)容的一塊空間或區(qū)域晌姚。理論上,畫(huà)布在所有維度上都是無(wú)限的歇竟。所以SVG可以是任意尺寸挥唠。然而,SVG通過(guò)有限區(qū)域展現(xiàn)在屏幕上焕议,這個(gè)區(qū)域叫做viewport宝磨。SVG中超出視口邊界的區(qū)域會(huì)被裁切并且隱藏。
viewport視口
視口是一塊SVG可見(jiàn)的區(qū)域盅安。你可以把視口當(dāng)做一個(gè)窗戶唤锉,透過(guò)這個(gè)窗戶可以看到特定的景象,景象也許完整别瞭,也許只有一部分窿祥。
SVG的視口類似訪問(wèn)當(dāng)前頁(yè)面的瀏覽器視口。網(wǎng)頁(yè)可以是任何尺寸蝙寨;它可以大于視口寬度壁肋,并且在大多數(shù)情況下都比視口高度要高。然而籽慢,每個(gè)時(shí)刻只有一部分網(wǎng)頁(yè)內(nèi)容是透過(guò)視口可見(jiàn)的。
整個(gè)SVG畫(huà)布可見(jiàn)還是部分可見(jiàn)取決于這個(gè)canvas的尺寸以及preserveAspectRatio屬性值猫胁。你現(xiàn)在不需要擔(dān)心這些箱亿;我們之后會(huì)討論更多的細(xì)節(jié)。
你可以在最外層元素上使用width和height屬性聲明視口尺寸弃秆。
<!-- the viewport will be 800px by 600px -->
<svg width="800" height="600">
<!-- SVG content drawn onto the SVG canvas -->
</svg>
在SVG中届惋,值可以帶單位也不可以不帶髓帽。一個(gè)不帶單位的值可以在用戶空間中通過(guò)用戶單位聲明。如果值通過(guò)用戶單位聲明脑豹,那么這個(gè)值的數(shù)值被認(rèn)為和px單位的數(shù)值一樣郑藏。這意味著上述例子將被渲染為800px*600px的視口。
你也可以使用單位來(lái)聲明值瘩欺。SVG支持的長(zhǎng)度單位有:em必盖,ex,px俱饿,pt歌粥,pc,cm拍埠,mm失驶,in和百分比。
一旦你設(shè)定最外層SVG元素的寬高枣购,瀏覽器會(huì)建立初始視口坐標(biāo)系和初始用戶坐標(biāo)系嬉探。
The initial coordinate system初始坐標(biāo)系
The initial viewport coordinate system初始視口坐標(biāo)系是一個(gè)建立在視口上的坐標(biāo)系。原點(diǎn)(0,0)在視口的左上角棉圈,X軸正向指向右涩堤,Y軸正向指向下,初始坐標(biāo)系中的一個(gè)單位等于視口中的一個(gè)"像素"迄损。這個(gè)坐標(biāo)系統(tǒng)類似于通過(guò)CSS盒模型在HTML元素上建立的坐標(biāo)系定躏。
The initial user coordinate system初始用戶坐標(biāo)系是建立在SVG畫(huà)布上的坐標(biāo)系。這個(gè)坐標(biāo)系一開(kāi)始和視口坐標(biāo)系完全一樣-它自己的原點(diǎn)位于視口左上角芹敌,x軸正向指向右痊远,y軸正向指向下。使用viewBox屬性氏捞,初始用戶坐標(biāo)系統(tǒng)-也稱當(dāng)前坐標(biāo)系奈揍,或使用中的用戶空間——可以被修改成與視口坐標(biāo)系不一樣的坐標(biāo)系。我們?cè)谝幌鹿?jié)中討論如何改變坐標(biāo)系隘马。
到現(xiàn)在為止乔妈,我們還沒(méi)有聲明viewBox屬性值。SVG畫(huà)布的用戶坐標(biāo)系統(tǒng)和視口坐標(biāo)系統(tǒng)完全一樣捆等。
下 圖中滞造,視口坐標(biāo)系的"標(biāo)尺"是灰色的,用戶坐標(biāo)系(viewBox)的是藍(lán)色的栋烤。由于它們?cè)谶@個(gè)時(shí)候完全相同谒养,所以兩個(gè)坐標(biāo)系統(tǒng)重合了。
上面SVG中的鸚鵡的外框邊界是200個(gè)單位(這個(gè)例子中是200個(gè)像素)寬和300個(gè)單位高明郭。鸚鵡基于初始坐標(biāo)系在畫(huà)布中繪制买窟。
新用戶空間(即丰泊,新當(dāng)前坐標(biāo)系)也可以通過(guò)在容器元素或圖形元素上使用transform屬性來(lái)聲明變換。我們將在這篇文章的第二部分討論關(guān)于變換的內(nèi)容始绍,更多細(xì)節(jié)在第三部分和最后部分中討論瞳购。
viewBox
我喜歡把viewBox理解為“真實(shí)”坐標(biāo)系。畢竟亏推,它是用來(lái)把SVG圖形繪制到畫(huà)布上的坐標(biāo)系学赛。這個(gè)坐標(biāo)系可以大于視口也可以小于視口,在視口中可以整體可見(jiàn)或部分可見(jiàn)径簿。
在本小節(jié)之前罢屈,這個(gè)坐標(biāo)系-用戶坐標(biāo)系-和視口坐標(biāo)系完全一樣。因?yàn)槲覀儧](méi)有把它聲明成其他坐標(biāo)系篇亭。這就是為什么所有的定位和繪制看起來(lái)是基于視口坐標(biāo)系的缠捌。因?yàn)槲覀円坏﹦?chuàng)建視口坐標(biāo)系(使用width和height),瀏覽器默認(rèn)創(chuàng)建一個(gè)完全相同的用戶坐標(biāo)系译蒂。
你可以使用viewBox屬性聲明自己的用戶坐標(biāo)系曼月。如果你選擇的用戶坐標(biāo)系統(tǒng)和視口坐標(biāo)系統(tǒng)寬高比(高比寬)相同,它會(huì)延伸來(lái)適應(yīng)整個(gè)視口區(qū)域(我們一會(huì)兒會(huì)講一些例子)柔昼。然而哑芹,如果你的用戶坐標(biāo)系寬高比不同,你可以用preserveAspectRatio屬性來(lái)聲明整個(gè)系統(tǒng)在視口內(nèi)是否可見(jiàn)捕透,你也可以用它來(lái)聲明在視口中如何定位聪姿。我們會(huì)在下個(gè)章節(jié)里討論這一情況的細(xì)節(jié)和例子。在這一章里乙嘀,我們只討論viewBox的寬高比符合視口的情況-在這些例子中末购,preserveAspectRatio不產(chǎn)生影響。
在我們討論這些例子前虎谢,我們回顧一下viewBox的語(yǔ)法盟榴。
viewBox語(yǔ)法
viewBox屬性接收四個(gè)參數(shù)值,包括:min-x,min-y , width 和 height婴噩。
viewBox = <min-x><min-y><width><height>
min-x和min-y值決定viewBox的左上角擎场,width和height決定viewBox的寬高。這里要注意視口的寬高不需要和父元素<svg>
的寬高一樣几莽。負(fù)數(shù)對(duì)于width和height是無(wú)效的迅办。值為0的話會(huì)禁止元素渲染。
注意viewport的寬度也可以在CSS中設(shè)置為任何值章蚣。例如:設(shè)置width:100%會(huì)讓SVG視口在文檔中自適應(yīng)礼饱。無(wú)論viewBox的值是多少,它會(huì)映射為外層SVG元素計(jì)算出的寬度值。
設(shè)置viewBox的例子如下:
<!-- The viewbox in this example is equal to the viewport, but it can be different -->
<svg width="800" height="600" viewbox="0 0 800 600">
<!-- SVG content drawn onto the SVG canvas -->
</svg>
如果你之前在其他地方看到過(guò)viewBox镊绪,你也許會(huì)看到一些解釋說(shuō)你可以用viewBox屬性通過(guò)縮放或者變化使SVG圖形變換。這是真的洒忧。我將深入探究并且告訴你甚至可以使用viewBox來(lái)切割SVG圖形蝴韭。
理解viewBox和viewport之間差異最好的方法是親身觀察。所以讓我們看一些例子熙侍。我們將從viewBox和viewport的寬高比相同的例子開(kāi)始榄鉴,所以我們還不需要深入了解preserveAspectRatio。
①與viewport寬高比一致的viewBox
我們從一個(gè)簡(jiǎn)單的例子開(kāi)始蛉抓。這個(gè)例子中的viewBox的尺寸是viewport的尺寸的一半庆尘。在這個(gè)例子中我們不改變viewBox的原點(diǎn),所以min-x和min=y都設(shè)置成0巷送。viewBox的寬高是viewport寬高的一半驶忌。這意味著我們保持寬高比。
<svg width="800" height="600" viewbox="0 0 400 300">
<!-- SVG content drawn onto the SVG canvas -->
</svg>
所以笑跛,viewBox="0 0 400 300"到底有什么用呢付魔?
- 它聲明了一個(gè)特定的區(qū)域,canvas橫跨左上角的點(diǎn)(0,0)到點(diǎn)(400,300)飞蹂。
- SVG圖像被這個(gè)區(qū)域裁切几苍。
- 區(qū)域被拉伸(類似縮放效果)來(lái)充滿整個(gè)視口。
- 用戶坐標(biāo)系被映射到視口坐標(biāo)系-在這種情況下-一個(gè)用戶單位等于兩個(gè)視口單位陈哑。
下面的圖片展示了在我們例子中把上面的viewBox應(yīng)用到 畫(huà)布中的效果妻坝。灰色單位代表視口坐標(biāo)系惊窖,藍(lán)色坐標(biāo)系代表viewBox建立的用戶坐標(biāo)系刽宪。
任何在SVG畫(huà)布中畫(huà)的內(nèi)容都會(huì)被對(duì)應(yīng)到新的用戶坐標(biāo)系中。
我喜歡像Google地圖一樣通過(guò)viewBox把SVG畫(huà)布形象化爬坑。在Google地圖中你可以在特定區(qū)域縮放纠屋;這個(gè)區(qū)域是唯一可見(jiàn)的,并且在瀏覽器視口中按比例增加盾计。然而售担,你知道地圖的剩余部分還在那里,但是不可見(jiàn)因?yàn)樗鲆暱诘倪吔?被裁切了署辉。
現(xiàn)在讓我們?cè)囍淖僲in-x和min-y的值族铆。都設(shè)置為100。你可以設(shè)置成任何你想要的值哭尝。寬高比還是和視口的寬高比一樣哥攘。
<svg width="800" height="600" viewbox="100 100 200 150">
<!-- SVG content drawn onto the SVG canvas -->
</svg>
添加viewBox="100 100 200 150"的效果和之前例子中一樣都是裁切的效果。圖形被裁切然后拉伸來(lái)充滿整個(gè)視口區(qū)域。
同樣逝淹,用戶坐標(biāo)系統(tǒng)被映射到視口坐標(biāo)系統(tǒng)——200個(gè)用戶單元被映射到800個(gè)視口單元耕姊,這樣每個(gè)用戶單元就等于4個(gè)視口單元。這就產(chǎn)生了一個(gè)縮放(放大)效果栅葡,就像你在上面的截圖中看到的那樣茉兰。
另外注意,在這個(gè)時(shí)候欣簇,為和聲明非0的值對(duì)圖形有變換的效果规脸;更加特別的是,SVG 畫(huà)布看起來(lái)向上拉伸100個(gè)單位熊咽,向左拉伸100個(gè)單位(transform="translate(-100 ,-100)"
)莫鸭。
的確,作為規(guī)范說(shuō)明横殴,“viewBox屬性的影響在于用戶代理自動(dòng)添加適當(dāng)?shù)淖儞Q矩陣來(lái)把用戶空間中具體的矩形映射到指定區(qū)域的邊界(通常是視口)”被因。
這只是我們之前提到過(guò)的一種說(shuō)法:圖形被裁切然后被縮放以適應(yīng)視口。這個(gè)說(shuō)明隨后增加了一個(gè)注釋:“在一些情況下用戶代理在縮放變換之外需要增加一個(gè)移動(dòng)變換滥玷。例如氏身,在最外層的svg元素上,如果viewBox屬性對(duì)min-x和min-y聲明非0值得那么就需要移動(dòng)變換惑畴〉靶溃”
為了更好演示移動(dòng)變換,讓我們?cè)囍omin-x和min-y添加-100如贷。移動(dòng)效果類似transform="translate(100, 100)"陷虎;這意味著圖形會(huì)在切割和縮放后移動(dòng)到右下方「芨ぃ回顧倒數(shù)第二個(gè)裁切尺寸為400*300的例子尚猿,添加新的無(wú)效min-x和min-y值,新的代碼如下:
<svg width="800" height="600" viewbox="-100 -100 400 300">
<!-- SVG content drawn onto the SVG canvas -->
</svg>
給圖形添加上述viewBox transformation的結(jié)果如下圖所示:
注意楣富,與transform屬性不同凿掂,因?yàn)関iewBox自動(dòng)添加的tranfomation不會(huì)影響有vewBox屬性的元素的x, y, width和height等屬性。因此纹蝴,在上述例子中展示的帶有width,height和viewBox屬性的svg元素庄萎,width和height屬性代表添加viewBox 變換之前的坐標(biāo)系中的值。在上述例子中你可以看到初始(灰色)viewport坐標(biāo)系甚至在<svg>上使用了viewBox屬性后仍然沒(méi)有影響塘安。
另一方面糠涛,像tranform屬性一樣,它給所有其他屬性和后代元素建立了一個(gè)新的坐標(biāo)系兼犯。你還可以看到在上述例子中忍捡,用戶坐標(biāo)系是新建立的-它不是保持像初始用戶坐標(biāo)系和使用viewBox前的視口坐標(biāo)系一樣集漾。任何后代會(huì)在這個(gè)新的用戶坐標(biāo)系中定位和確定尺寸,而不是初始坐標(biāo)系砸脊。
最后一個(gè)viewBox的例子和前一個(gè)類似具篇,但是它不是切割畫(huà)布,我們將在viewport里擴(kuò)展它并看它如何影響圖形凌埂。我們將聲明一個(gè)寬高比viewport大的viewBox栽连,并依然保持viewport的寬高比。我們?cè)谙乱徽吕镉懻摬煌膶捀弑取?/p>
在這個(gè)例子中侨舆,我們將viewBox的尺寸設(shè)為viewport的1.5倍。
<svg width="800" height="600" viewbox="0 0 1200 900">
<!-- SVG content drawn onto the SVG canvas -->
</svg>
現(xiàn)在用戶坐標(biāo)系會(huì)被放大到1200*900绢陌。它會(huì)被映射到視口坐標(biāo)系挨下,用戶坐標(biāo)系中的每一個(gè)單位水平方向上等于視口坐標(biāo)系中的viewport-width / viewBox-width,豎直方向上等于viewport-height / viewBox-height脐湾。這意味著臭笆,在這種情況下,每一個(gè)用戶坐標(biāo)系中的x-units等于viewport坐標(biāo)系中的0.66個(gè)x-units秤掌,每個(gè)用戶y-unit映射成0.66的viewport y-units愁铺。
當(dāng)然,理解這些最好的方法是把結(jié)果視覺(jué)化闻鉴。viewBox被縮放到適應(yīng)下圖所示的viewport茵乱。因?yàn)閳D形在畫(huà)布里基于新的用戶坐標(biāo)系繪制的,而不是視口坐標(biāo)系孟岛,它看起來(lái)比視口小瓶竭。
②與viewport寬高比不一致的viewBox
到目前為止,我們所有的例子的寬高比都和視口一致渠羞。但是如果viewBox中聲明的寬高比和視口中的不一樣會(huì)發(fā)生什么呢斤贰?例如,試想我們把視口的尺寸設(shè)為1000*500次询。寬高比不再和視口的一樣荧恍。在例子中使用viewBox="0 0 1000 500"的結(jié)果如下圖:
用戶坐標(biāo)系。因此圖形在視口中定位:
- 整個(gè)viewBox適應(yīng)viewport屯吊。
- 保持viewBox的寬高比送巡。viewBox沒(méi)有被拉伸來(lái)覆蓋視口區(qū)域。
- viewBox在視口中水平垂直居中雌芽。
這是默認(rèn)表現(xiàn)授艰。那用什么控制表現(xiàn)呢?如果我們想改變視口中viewBox的位置呢世落?這就需要用到preserveAspectRatio屬性了淮腾。
preserveAspectRatio屬性
preserveAspectRatio屬性強(qiáng)制統(tǒng)一縮放比來(lái)保持圖形的寬高比糟需。
如果你用不同于視口的寬高比定義用戶坐標(biāo)系,如果像我們?cè)谥暗睦又锌吹降哪菢訛g覽器拉伸viewBox來(lái)適應(yīng)視口谷朝,寬高比的不同會(huì)導(dǎo)致圖形在某些方向上扭曲洲押。所以如果上一個(gè)例子中的viewBox被拉伸以在所有方向上適應(yīng)視口,圖形看起來(lái)如下:
當(dāng)給viewBox設(shè)置0 0 200 300的值時(shí)扭曲顯而易見(jiàn)(顯然這很不理想)圆凰,這個(gè)值小于視口尺寸杈帐。我故意選擇這個(gè)尺寸從而讓viewBox匹配鸚鵡邊界盒子的尺寸。如果瀏覽器拉伸圖像來(lái)適應(yīng)整個(gè)視口专钉,看起來(lái)會(huì)像下面這樣:
preserveAspectRatio屬性讓你可以在保持寬高比的情況下強(qiáng)制統(tǒng)一viewBox的縮放比挑童,并且如果不想用默認(rèn)居中你可以聲明viewBox在視口中的位置。
preserveAspectRatio語(yǔ)法
preserveAspectRatio的官方語(yǔ)法是:
preserveAspectRatio = defer? <align> <meetOrSlice>?
它在任何建立新viewport的元素上都有效(我們會(huì)在這個(gè)系列的下一部分討論這個(gè)問(wèn)題)跃须。
①defer聲明是可選的站叼,并且只有當(dāng)你在<img>上添加preserveAspectRatio才被用到。用在任何其他元素上時(shí)它都會(huì)被忽略菇民。本身不在這篇文章的討論范圍尽楔,我們暫時(shí)跳過(guò)defer這個(gè)選項(xiàng)。
-
②align參數(shù)聲明是否強(qiáng)制統(tǒng)一放縮第练,如果是阔馋,對(duì)齊方法會(huì)在viewBox的寬高比不符合viewport的寬高比的情況下生效。
如果align值設(shè)為none娇掏,例如:
preserveAspectRatio = "none"
圖形不在保持寬高比而會(huì)縮放來(lái)適應(yīng)視口呕寝,像我們?cè)谏厦鎯蓚€(gè)例子中看到的那樣。
其他所有preserveAspectRatio值都在保持viewBox的寬高比的情況下強(qiáng)制拉伸驹碍,并且指定在視口內(nèi)如何對(duì)齊viewBox壁涎。我們會(huì)簡(jiǎn)短介紹align的值。
-
③最后一個(gè)屬性志秃,meetOrSlice也是可選的怔球,默認(rèn)值為meet。這個(gè)屬性聲明整個(gè)viewBox在視口中是否可見(jiàn)浮还。如果是竟坛,它和align參數(shù)通過(guò)一個(gè)或多個(gè)空格分隔。例如:
preserveAspectRatio = "xMinYMin slice"
這些值第一眼看起來(lái)也許很陌生钧舌。為了讓它們更易于理解和熟悉担汤,你可以把meetOrSlice的值類比于background-size的contain和cover值;它們非常類似。meet類似于contain洼冻,slice類似于cover崭歧。下面是每個(gè)值的定義和含義:
- meet(默認(rèn)值)
基于以下兩條準(zhǔn)側(cè)盡可能縮放元素:
- 保持寬高比
- 整個(gè)viewBox在視口中可見(jiàn)
在這個(gè)情況下,如果圖形的寬高比不符合視口撞牢,一些視口會(huì)超出viewBox的邊界(即viewBox繪制的區(qū)域會(huì)小于視口)率碾。(在viewBox一節(jié)查看最后的例子叔营。)在這個(gè)情況下,viewBox的邊界被包含在viewport中使得邊界滿足所宰。
這個(gè)值類似于background-size: contain绒尊。背景圖片在保持寬高比的情況下盡可能縮放并確保它適合背景繪制區(qū)域。如果背景的長(zhǎng)寬比和應(yīng)用的元素的長(zhǎng)寬比不一樣仔粥,部分背景繪制區(qū)域會(huì)沒(méi)有背景圖片覆蓋婴谱。
- slice
在保持寬高比的情況下,縮放圖形直到viewBox覆蓋了整個(gè)視口區(qū)域躯泰。viewBox被縮放到正好覆蓋視口區(qū)域(在兩個(gè)維度上)谭羔,但是它不會(huì)縮放任何超出這個(gè)范圍的部分。換而言之麦向,它縮放到viewBox的寬高可以正好完全覆蓋視口口糕。
在這種情況下,如果viewBox的寬高比不適合視口磕蛇,一部分viewBox會(huì)擴(kuò)展超過(guò)視口邊界(即,viewBox繪制的區(qū)域會(huì)比視口大)十办。這會(huì)導(dǎo)致部分viewBox被切片秀撇。
你可以把這個(gè)類比為background-size: cover。在背景圖片的情況中向族,圖片在保持本身寬高比(如何)的情況下縮放到寬高可以完全覆蓋背景定位區(qū)域的最小尺寸呵燕。
所以,meetOrSlice被用來(lái)聲明viewBox是否會(huì)被完全包含在視口中件相,或者它是否應(yīng)該盡可能縮放來(lái)覆蓋整個(gè)視口再扭,甚至意味著部分的viewBox會(huì)被“slice”。
例如夜矗,如果我們聲明viewBox的尺寸為200*300泛范,并且使用了meet和slice值,保持align值為瀏覽器默認(rèn)紊撕,每個(gè)值的結(jié)果會(huì)看起來(lái)如下:
align參數(shù)使用9個(gè)值中的一個(gè)或者為none罢荡。任何除none之外的值都用來(lái)保持寬高比縮放圖片,并且還用來(lái)在視口中對(duì)齊viewBox对扶。
當(dāng)使用百分比值時(shí)区赵,align值類似于background-position。你可以把viewBox當(dāng)做背景圖像浪南。通過(guò)align定位和background-position的不同在于笼才,它不是將viewbox的特定點(diǎn)定位在viewport的相應(yīng)點(diǎn)上,而是將viewbox的特定“軸”與viewport的相應(yīng)“軸”對(duì)齊络凿。
為了理解每個(gè)align值的含義骡送,我們將首先介紹每一個(gè)“軸”昂羡。
還記得viewBox的min-x和min-y值嗎?我們將使用它們來(lái)定義viewBox中的"min-x"和"min-y"軸各谚。另外紧憾,我們將定義兩個(gè)軸“max-x”和”max-y“,各自通過(guò) <min-x>+<width> 和 <min-y>+<height> 來(lái)定位昌渤。最后赴穗,我們定義兩個(gè)軸"mid-x"和"mid-y",根據(jù)<min-x> + (<width>/2) 和 <min-y>+ (<height>/2)來(lái)定位膀息。
這樣做是不是讓事情更復(fù)雜了呢般眉?如果是這樣,讓我們看一下下面的圖片來(lái)看一下每個(gè)軸代表了什么潜支。在這張圖片中甸赃,min-x和min-y 值都設(shè)置為0。viewBox被設(shè)置為viewBox = "0 0 300 300"冗酿。
上面圖片中的灰色虛線代表視口的mid-x和mid-y軸埠对。我們將對(duì)它們賦一些值來(lái)對(duì)齊viewBox的mid-x和mid-y軸。對(duì)于視口裁替,min-x的值等于0项玛,min-y值也等于0,max-x值等于viewBox的寬度弱判,max-y的值等于高度襟沮,mid-x和mid-y代表了寬度和高度的中間值。
對(duì)齊的取值包括:
①none
不強(qiáng)制統(tǒng)一縮放昌腰。如果必要的話开伏,在不統(tǒng)一(即不保持寬高比)的情況下縮放給定元素的圖像內(nèi)容直到元素的邊界盒完全匹配是視口矩形。
換句話說(shuō)遭商,如果有必要的話viewBox被拉伸或縮放來(lái)完全適應(yīng)整個(gè)視口固灵,不管寬高比。圖形也許會(huì)扭曲劫流。
(注意:如果的值是none怎虫,可選的值<meetOrSlice>無(wú)效。)
②xMinYMin
- 強(qiáng)制統(tǒng)一縮放
- 視口X軸的最小值對(duì)齊元素viewBox的<min-x>困介。
- 視口Y軸的最小值對(duì)齊元素viewBox的<min-y>大审。
- 把這個(gè)類比為backrgound-position: 0% 0%;。
③xMinYMid
- 強(qiáng)制統(tǒng)一縮放座哩。
- 視口X軸的最小值對(duì)齊元素viewBox的<min-x>徒扶。
- 視口Y軸的中間值來(lái)對(duì)齊元素的viewBox的中間值。
- 把這個(gè)類比為backrgound-position: 0% 50%;根穷。
④xMinYMax
- 強(qiáng)制統(tǒng)一縮放姜骡。
- 視口X軸的最小值對(duì)齊元素viewBox的<min-x>导坟。
- 視口X軸的最大值對(duì)齊元素的viewBox的<height>+<min-y>。
- 把這個(gè)類比為backrgound-position: 0% 100%;圈澈。
⑤xMidYMin
- 強(qiáng)制統(tǒng)一縮放惫周。
- 視口X軸的中間值對(duì)齊元素的viewBox的X軸中間值。
- 視口Y軸的最小值對(duì)齊元素的viewBox的最小值 康栈。
- 把這個(gè)類比為backrgound-position: 50% 0%;递递。
⑥xMidYMid (默認(rèn)值)
- 強(qiáng)制統(tǒng)一縮放。
- 視口X軸的中間值對(duì)齊元素的viewBox的X軸中間值啥么。
- 視口Y軸的中間值對(duì)齊元素的viewBox的Y軸中間值登舞。
- 把這個(gè)類比為backrgound-position: 50% 50%;。
⑦xMidYMax
- 強(qiáng)制統(tǒng)一縮放悬荣。
- 視口X軸的中間值對(duì)齊元素的viewBox的X軸中間值菠秒。
- 視口Y軸的最大值對(duì)齊元素的viewBox的<height>+<min-y>。
- 把這個(gè)類比為backrgound-position: 50% 100%;氯迂。
⑧xMaxYMin
- 強(qiáng)制統(tǒng)一縮放践叠。
- 視口X軸的最大值對(duì)齊元素的viewBox的 <width>+<min-x>。
- 視口Y軸的最小值對(duì)齊元素的viewBox的<min-y>嚼蚀。
- 把這個(gè)類比為backrgound-position: 100% 0%;酵熙。
⑨xMaxYMid
- 強(qiáng)制統(tǒng)一縮放。
- 視口X軸的最大值對(duì)齊元素的viewBox的 <width>+<min-x>驰坊。
- 視口Y軸的中間值對(duì)齊元素的viewBox的Y軸中間值。
- 把這個(gè)類比為backrgound-position: 100% 50%;哮独。
⑩xMaxYMax
- 強(qiáng)制統(tǒng)一縮放拳芙。
- 視口X軸的最大值對(duì)齊元素的viewBox的 <width>+<min-x>。
- 視口Y軸的最大值對(duì)齊元素的viewBox的 <height>+<min-y>皮璧。
- 把這個(gè)類比為backrgound-position: 100% 100%;舟扎。
所以,通過(guò)使用preserveAspectRatio屬性的align和meetOrSlice值悴务,你可以聲明是否統(tǒng)一縮放viewBox睹限,是否和視口對(duì)齊,在視口中是否整個(gè)可見(jiàn)讯檐。
有時(shí)候羡疗,取決于viewBox的尺寸,一些值可能會(huì)導(dǎo)致相似的結(jié)果别洪,例如在早先viewBox="0 0 200 300"的例子中叨恨,一些對(duì)齊完全用了不同的align值。這時(shí)候就要設(shè)置meetOrSlice的值為meet來(lái)保證viewBox包含在viewport內(nèi)挖垛。
如果我們把meetOrSlice的值改成slice痒钝,不同的值我們將得到不同的結(jié)果秉颗。注意viewBox是如何拉伸來(lái)覆蓋整個(gè)視口的。x軸被拉伸到用200單位來(lái)覆蓋視口800單位送矩。為了達(dá)到這個(gè)目的蚕甥,并且保持viewBox的寬高比,y軸在底部被“裁切”栋荸,但是你可以想象它在視口中高度上的延伸菇怀。
當(dāng)然,不同的viewBox值看起來(lái)不同于我們這里用的200*300蒸其。為了保持簡(jiǎn)潔敏释,我們不再列舉更多的例子,你可以看我創(chuàng)建的一些互動(dòng)演示來(lái)幫助你更好地形象化理解viewBox和preserveAspectRatio在不同值下的效果摸袁。你可以在一下節(jié)中查看互動(dòng)演示例子的鏈接钥顽。
但是在這之前,我想要提醒你注意如果 <min-x>和<min-y> 值改變靠汁,那么mid-x, mid-y, max-x, 和 max-y的值也會(huì)發(fā)生改變蜂大。你可以在互動(dòng)演示中改變這些值來(lái)查看軸以及相關(guān)聯(lián)的viewBox的對(duì)齊方式的改變。
下面圖片展示了定位軸的位置為viewBox = "100 0 200 300"時(shí)的效果蝶怔。和之前用一樣的例子奶浦,但是我們把的<min-x>值設(shè)為100而不是之前的0。你可以設(shè)置成任何你想要的值踢星。注意min-x, mid-x, 和 max-x軸是如何變化的澳叉。這里使用的preserveAspectRatio值為默認(rèn)的xMinYMin meet,意味著mid-*軸和視口軸的中間對(duì)齊沐悦。
互動(dòng)演示
要理解viewport, viewBox, 以及不同的preserveAspectRatio值是如何工作的最好方法是可視化的演示成洗。
出于這個(gè)目的,我創(chuàng)建了一個(gè)簡(jiǎn)單的互動(dòng)演示藏否,你可以改變這些屬性的值來(lái)查看新值導(dǎo)致的結(jié)果瓶殃。
我希望這篇文章在幫助你理解SVG viewport, viewBox, 和 preserveAspectRatio 內(nèi)容時(shí)有作用。如果你想要了解更多關(guān)于SVG坐標(biāo)系的內(nèi)容副签,例如嵌套坐標(biāo)系遥椿,建立一個(gè)新的坐標(biāo)系以及SVG中的變換,繼續(xù)閱讀這一系列接下來(lái)的部分淆储。感謝你的閱讀冠场!
本文根據(jù)SaraSoueidan的《Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, viewBox, and preserveAspectRatio》一文所譯,整個(gè)譯文帶有我們自己的理解與思想本砰,如果譯得不好或有不對(duì)之處還請(qǐng)同行朋友指點(diǎn)慈鸠。如需轉(zhuǎn)載此譯文,需注明英文出處http://sarasoueidan.com/blog/svg-coordinate-systems/。