2018-09-16_svgPart1_viewport&viewBox&preserveAspectRatio

理解SVG坐標(biāo)系和變換(第一部分)-viewport,viewBox,和preserveAspectRatio

(本文轉(zhuǎn)自w3cplus,這里僅修正了部分個(gè)人認(rèn)為翻譯不恰當(dāng)之處;下面是譯文鏈接,英文原文鏈接在結(jié)尾處提供)

SVG元素不像HTML元素一樣由CSS盒模型管理。這使得我們可以更加靈活定位和變換這些元素-也許一眼看上去不太直觀。然而,一旦你理解了SVG坐標(biāo)系和變換,操縱SVG會(huì)非常簡單并且很有意義。本篇文章中我們將討論控制SVG坐標(biāo)系的最重要的三個(gè)屬性:viewport, viewBox, 和 preserveAspectRatio。

這是本系列三篇文章中的第一篇,這篇文章討論SVG中的坐標(biāo)系和變換。

為了使文中的內(nèi)容和解釋更形象化,我創(chuàng)建了一個(gè)互動(dòng)演示,你可以任意改變viewBox 和 preserveAspectRatio的值。

在線案例

這個(gè)例子只是主要內(nèi)容的一小部分,所以看完請回來繼續(xù)閱讀這篇文章

SVG畫布

canvas是繪制SVG內(nèi)容的一塊空間或區(qū)域。理論上,畫布在所有維度上都是無限的。所以SVG可以是任意尺寸。然而,SVG通過有限區(qū)域展現(xiàn)在屏幕上,這個(gè)區(qū)域叫做viewport。SVG中超出視口邊界的區(qū)域會(huì)被裁切并且隱藏。

viewport視口

視口是一塊SVG可見的區(qū)域。你可以把視口當(dāng)做一個(gè)窗戶,透過這個(gè)窗戶可以看到特定的景象,景象也許完整,也許只有一部分。

SVG的視口類似訪問當(dāng)前頁面的瀏覽器視口。網(wǎng)頁可以是任何尺寸;它可以大于視口寬度,并且在大多數(shù)情況下都比視口高度要高。然而,每個(gè)時(shí)刻只有一部分網(wǎng)頁內(nèi)容是透過視口可見的。

整個(gè)SVG畫布可見還是部分可見取決于這個(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è)不帶單位的值可以在用戶空間中通過用戶單位聲明。如果值通過用戶單位聲明,那么這個(gè)值的數(shù)值被認(rèn)為和px單位的數(shù)值一樣。這意味著上述例子將被渲染為800px*600px的視口。

你也可以使用單位來聲明值。SVG支持的長度單位有: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)類似于通過CSS盒模型在HTML元素上建立的坐標(biāo)系。

The initial user coordinate system初始用戶坐標(biāo)系是建立在SVG畫布上的坐標(biāo)系。這個(gè)坐標(biāo)系一開始和視口坐標(biāo)系完全一樣-它自己的原點(diǎn)位于視口左上角,x軸正向指向右,y軸正向指向下。使用viewBox屬性,初始用戶坐標(biāo)系統(tǒng)-也稱當(dāng)前坐標(biāo)系,或使用中的用戶空間——可以被修改成與視口坐標(biāo)系不一樣的坐標(biāo)系。我們在一下節(jié)中討論如何改變坐標(biāo)系。

到現(xiàn)在為止,我們還沒有聲明viewBox屬性值。SVG畫布的用戶坐標(biāo)系統(tǒng)和視口坐標(biāo)系統(tǒng)完全一樣。

下 圖中,視口坐標(biāo)系的"標(biāo)尺"是灰色的,用戶坐標(biāo)系(viewBox)的是藍(lán)色的。由于它們在這個(gè)時(shí)候完全相同,所以兩個(gè)坐標(biāo)系統(tǒng)重合了。

The initial coordinate systems established on the viewport and SVG canvas. Grey units represent the viewport coordinate system; blue units represent the user coordinate system. Both coordinate systems are identical and coincide.->initial-coordinate-systems.jpg

上面SVG中的鸚鵡的外框邊界是200個(gè)單位(這個(gè)例子中是200個(gè)像素)寬和300個(gè)單位高。鸚鵡基于初始坐標(biāo)系在畫布中繪制。

新用戶空間(即,新當(dāng)前坐標(biāo)系)也可以通過在容器元素或圖形元素上使用transform屬性來聲明變換。我們將在這篇文章的第二部分討論關(guān)于變換的內(nèi)容,更多細(xì)節(jié)在第三部分和最后部分中討論。

viewBox

我喜歡把viewBox理解為“真實(shí)”坐標(biāo)系。畢竟,它是用來把SVG圖形繪制到畫布上的坐標(biāo)系。這個(gè)坐標(biāo)系可以大于視口也可以小于視口,在視口中可以整體可見或部分可見。

在本小節(jié)之前,這個(gè)坐標(biāo)系-用戶坐標(biāo)系-和視口坐標(biāo)系完全一樣。因?yàn)槲覀儧]有把它聲明成其他坐標(biāo)系。這就是為什么所有的定位和繪制看起來是基于視口坐標(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ì)延伸來適應(yīng)整個(gè)視口區(qū)域(我們一會(huì)兒會(huì)講一些例子)。然而,如果你的用戶坐標(biāo)系寬高比不同,你可以用preserveAspectRatio屬性來聲明整個(gè)系統(tǒng)在視口內(nèi)是否可見,你也可以用它來聲明在視口中如何定位。我們會(huì)在下個(gè)章節(jié)里討論這一情況的細(xì)節(jié)和例子。在這一章里,我們只討論viewBox的寬高比符合視口的情況-在這些例子中,preserveAspectRatio不產(chǎn)生影響。

在我們討論這些例子前,我們回顧一下viewBox的語法。

viewBox語法

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ù)對于width和height是無效的。值為0的話會(huì)禁止元素渲染。

注意viewport的寬度也可以在CSS中設(shè)置為任何值。例如:設(shè)置width:100%會(huì)讓SVG視口在文檔中自適應(yīng)。無論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>

如果你之前在其他地方看到過viewBox,你也許會(huì)看到一些解釋說你可以用viewBox屬性通過縮放或者變化使SVG圖形變換。這是真的。我將深入探究并且告訴你甚至可以使用viewBox來切割SVG圖形。

理解viewBox和viewport之間差異最好的方法是親身觀察。所以讓我們看一些例子。我們將從viewBox和viewport的寬高比相同的例子開始,所以我們還不需要深入了解preserveAspectRatio。

①與viewport寬高比一致的viewBox

我們從一個(gè)簡單的例子開始。這個(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ū)域被拉伸(類似縮放效果)來充滿整個(gè)視口。
  • 用戶坐標(biāo)系被映射到視口坐標(biāo)系-在這種情況下-一個(gè)用戶單位等于兩個(gè)視口單位。

下面的圖片展示了在我們例子中把上面的viewBox應(yīng)用到 畫布中的效果。灰色單位代表視口坐標(biāo)系,藍(lán)色坐標(biāo)系代表viewBox建立的用戶坐標(biāo)系。

Specifying a viewbox has a result similar to cropping the graphic to that viewbox and then zooming it in so that it fills the entire viewport area. Remember that we're still maintaining the same aspect ratio as the viewport in this case.->viewbox-400-300-crop.jpg

任何在SVG畫布中畫的內(nèi)容都會(huì)被對應(yīng)到新的用戶坐標(biāo)系中。

我喜歡像Google地圖一樣通過viewBox把SVG畫布形象化。在Google地圖中你可以在特定區(qū)域縮放;這個(gè)區(qū)域是唯一可見的,并且在瀏覽器視口中按比例增加。然而,你知道地圖的剩余部分還在那里,但是不可見因?yàn)樗鲆暱诘倪吔?被裁切了。

現(xiàn)在讓我們試著改變min-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"的效果和之前例子中一樣都是裁切的效果。圖形被裁切然后拉伸來充滿整個(gè)視口區(qū)域。

The result of "cropping" the graphic to a viewbox with an origin at (100, 100) and width 200 and height 150.->viewbox-200-150-crop.jpg

同樣,用戶坐標(biāo)系統(tǒng)被映射到視口坐標(biāo)系統(tǒng)——200個(gè)用戶單元被映射到800個(gè)視口單元,這樣每個(gè)用戶單元就等于4個(gè)視口單元。這就產(chǎn)生了一個(gè)縮放(放大)效果,就像你在上面的截圖中看到的那樣。

另外注意,在這個(gè)時(shí)候,為和聲明非0的值對圖形有變換的效果;更加特別的是,SVG 畫布看起來向上拉伸100個(gè)單位,向左拉伸100個(gè)單位(transform="translate(-100 ,-100)")。

的確,作為規(guī)范說明,“viewBox屬性的影響在于用戶代理自動(dòng)添加適當(dāng)?shù)淖儞Q矩陣來把用戶空間中具體的矩形映射到指定區(qū)域的邊界(通常是視口)”。

這只是我們之前提到過的一種說法:圖形被裁切然后被縮放以適應(yīng)視口。這個(gè)說明隨后增加了一個(gè)注釋:“在一些情況下用戶代理在縮放變換之外需要增加一個(gè)移動(dòng)變換。例如,在最外層的svg元素上,如果viewBox屬性對min-x和min-y聲明非0值得那么就需要移動(dòng)變換。”

為了更好演示移動(dòng)變換,讓我們試著給min-x和min-y添加-100。移動(dòng)效果類似transform="translate(100, 100)";這意味著圖形會(huì)在切割和縮放后移動(dòng)到右下方。回顧倒數(shù)第二個(gè)裁切尺寸為400*300的例子,添加新的無效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é)果如下圖所示:

viewbox-400-300-crop-translate.jpg

注意,與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屬性后仍然沒有影響。

另一方面,像tranform屬性一樣,它給所有其他屬性和后代元素建立了一個(gè)新的坐標(biāo)系。你還可以看到在上述例子中,用戶坐標(biāo)系是新建立的-它不是保持像初始用戶坐標(biāo)系和使用viewBox前的視口坐標(biāo)系一樣。任何后代會(huì)在這個(gè)新的用戶坐標(biāo)系中定位和確定尺寸,而不是初始坐標(biāo)系。

最后一個(gè)viewBox的例子和前一個(gè)類似,但是它不是切割畫布,我們將在viewport里擴(kuò)展它并看它如何影響圖形。我們將聲明一個(gè)寬高比viewport大的viewBox,并依然保持viewport的寬高比。我們在下一章里討論不同的寬高比。

在這個(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é)果視覺化。viewBox被縮放到適應(yīng)下圖所示的viewport。因?yàn)閳D形在畫布里基于新的用戶坐標(biāo)系繪制的,而不是視口坐標(biāo)系,它看起來比視口小。

A 1200x900 user coordinate system mapped into the 800x600 viewport coordinate system. The grey units represent the viewport coordinate system; the blue units represent the system established from the viewBox.->viewbox-1200-900.jpg

②與viewport寬高比不一致的viewBox

到目前為止,我們所有的例子的寬高比都和視口一致。但是如果viewBox中聲明的寬高比和視口中的不一樣會(huì)發(fā)生什么呢?例如,試想我們把視口的尺寸設(shè)為1000*500。寬高比不再和視口的一樣。在例子中使用viewBox="0 0 1000 500"的結(jié)果如下圖:

The result of defining a 1000x500 user coordinate system in a 800x600 viewport.->viewbox-1000-500.jpg

用戶坐標(biāo)系。因此圖形在視口中定位:

  • 整個(gè)viewBox適應(yīng)viewport。
  • 保持viewBox的寬高比。viewBox沒有被拉伸來覆蓋視口區(qū)域。
  • viewBox在視口中水平垂直居中。

這是默認(rèn)表現(xiàn)。那用什么控制表現(xiàn)呢?如果我們想改變視口中viewBox的位置呢?這就需要用到preserveAspectRatio屬性了。

preserveAspectRatio屬性

preserveAspectRatio屬性強(qiáng)制統(tǒng)一縮放比來保持圖形的寬高比。

如果你用不同于視口的寬高比定義用戶坐標(biāo)系,如果像我們在之前的例子中看到的那樣瀏覽器拉伸viewBox來適應(yīng)視口,寬高比的不同會(huì)導(dǎo)致圖形在某些方向上扭曲。所以如果上一個(gè)例子中的viewBox被拉伸以在所有方向上適應(yīng)視口,圖形看起來如下:

The result of mapping the user coordinate system to the viewport without preserving its aspect ratio. The graphic is distorted and looks shrunk horizontally while also being stretched vertically.->viewbox-1000-500-stretched.jpg

當(dāng)給viewBox設(shè)置0 0 200 300的值時(shí)扭曲顯而易見(顯然這很不理想),這個(gè)值小于視口尺寸。我故意選擇這個(gè)尺寸從而讓viewBox匹配鸚鵡邊界盒子的尺寸。如果瀏覽器拉伸圖像來適應(yīng)整個(gè)視口,看起來會(huì)像下面這樣:

The result of mapping the user coordinate system to the viewport without preserving its aspect ratio. The graphic is distorted.->viewbox-200-300-stretched.jpg

preserveAspectRatio屬性讓你可以在保持寬高比的情況下強(qiáng)制統(tǒng)一viewBox的縮放比,并且如果不想用默認(rèn)居中你可以聲明viewBox在視口中的位置。

preserveAspectRatio語法

preserveAspectRatio的官方語法是:

preserveAspectRatio = defer? <align> <meetOrSlice>?

它在任何建立新viewport的元素上都有效(我們會(huì)在這個(gè)系列的下一部分討論這個(gè)問題)。

  • ①defer聲明是可選的,并且只有當(dāng)你在<img>上添加preserveAspectRatio才被用到。用在任何其他元素上時(shí)它都會(huì)被忽略。本身不在這篇文章的討論范圍,我們暫時(shí)跳過defer這個(gè)選項(xiàng)。

  • ②align參數(shù)聲明是否強(qiáng)制統(tǒng)一放縮,如果是,對齊方法會(huì)在viewBox的寬高比不符合viewport的寬高比的情況下生效。

    如果align值設(shè)為none,例如:

    preserveAspectRatio = "none"
    

    圖形不在保持寬高比而會(huì)縮放來適應(yīng)視口,像我們在上面兩個(gè)例子中看到的那樣。

    其他所有preserveAspectRatio值都在保持viewBox的寬高比的情況下強(qiáng)制拉伸,并且指定在視口內(nèi)如何對齊viewBox。我們會(huì)簡短介紹align的值。

  • ③最后一個(gè)屬性,meetOrSlice也是可選的,默認(rèn)值為meet。這個(gè)屬性聲明整個(gè)viewBox在視口中是否可見。如果是,它和align參數(shù)通過一個(gè)或多個(gè)空格分隔。例如:

    preserveAspectRatio = "xMinYMin slice"
    

    這些值第一眼看起來也許很陌生。為了讓它們更易于理解和熟悉,你可以把meetOrSlice的值類比于background-size的contain和cover值;它們非常類似。meet類似于contain,slice類似于cover。下面是每個(gè)值的定義和含義:

    • meet(默認(rèn)值)

    基于以下兩條準(zhǔn)側(cè)盡可能縮放元素:

    • 保持寬高比
    • 整個(gè)viewBox在視口中可見

    在這個(gè)情況下,如果圖形的寬高比不符合視口,一些視口會(huì)超出viewBox的邊界(即viewBox繪制的區(qū)域會(huì)小于視口)。(在viewBox一節(jié)查看最后的例子。)在這個(gè)情況下,viewBox的邊界被包含在viewport中使得邊界滿足。

    這個(gè)值類似于background-size: contain。背景圖片在保持寬高比的情況下盡可能縮放并確保它適合背景繪制區(qū)域。如果背景的長寬比和應(yīng)用的元素的長寬比不一樣,部分背景繪制區(qū)域會(huì)沒有背景圖片覆蓋。

    • slice

    在保持寬高比的情況下,縮放圖形直到viewBox覆蓋了整個(gè)視口區(qū)域。viewBox被縮放到正好覆蓋視口區(qū)域(在兩個(gè)維度上),但是它不會(huì)縮放任何超出這個(gè)范圍的部分。換而言之,它縮放到viewBox的寬高可以正好完全覆蓋視口。

    在這種情況下,如果viewBox的寬高比不適合視口,一部分viewBox會(huì)擴(kuò)展超過視口邊界(即,viewBox繪制的區(qū)域會(huì)比視口大)。這會(huì)導(dǎo)致部分viewBox被切片。

    你可以把這個(gè)類比為background-size: cover。在背景圖片的情況中,圖片在保持本身寬高比(如何)的情況下縮放到寬高可以完全覆蓋背景定位區(qū)域的最小尺寸。

    所以,meetOrSlice被用來聲明viewBox是否會(huì)被完全包含在視口中,或者它是否應(yīng)該盡可能縮放來覆蓋整個(gè)視口,甚至意味著部分的viewBox會(huì)被“slice”。

    例如,如果我們聲明viewBox的尺寸為200*300,并且使用了meet和slice值,保持align值為瀏覽器默認(rèn),每個(gè)值的結(jié)果會(huì)看起來如下:

viewbox-200-300-meet-vs-slice.jpg

align參數(shù)使用9個(gè)值中的一個(gè)或者為none。任何除none之外的值都用來保持寬高比縮放圖片,并且還用來在視口中對齊viewBox。

當(dāng)使用百分比值時(shí),align值類似于background-position。你可以把viewBox當(dāng)做背景圖像。通過align定位和background-position的不同在于,它不是將viewbox的特定點(diǎn)定位在viewport的相應(yīng)點(diǎn)上,而是將viewbox的特定“軸”與viewport的相應(yīng)“軸”對齊。

為了理解每個(gè)align值的含義,我們將首先介紹每一個(gè)“軸”。

還記得viewBox的min-x和min-y值嗎?我們將使用它們來定義viewBox中的"min-x"和"min-y"軸。另外,我們將定義兩個(gè)軸“max-x”和”max-y“,各自通過 <min-x>+<width> 和 <min-y>+<height> 來定位。最后,我們定義兩個(gè)軸"mid-x"和"mid-y",根據(jù)<min-x> + (<width>/2) 和 <min-y>+ (<height>/2)來定位。

這樣做是不是讓事情更復(fù)雜了呢?如果是這樣,讓我們看一下下面的圖片來看一下每個(gè)軸代表了什么。在這張圖片中,min-x和min-y 值都設(shè)置為0。viewBox被設(shè)置為viewBox = "0 0 300 300"。

The pink and orange solid lines represent the min-y and min-x values respectively. The dashed pink and orange lines represent the mid and max x and y values.->viewbox-x-y-axes.jpg

上面圖片中的灰色虛線代表視口的mid-x和mid-y軸。我們將對它們賦一些值來對齊viewBox的mid-x和mid-y軸。對于視口,min-x的值等于0,min-y值也等于0,max-x值等于viewBox的寬度,max-y的值等于高度,mid-x和mid-y代表了寬度和高度的中間值。

對齊的取值包括:

①none

不強(qiáng)制統(tǒng)一縮放。如果必要的話,在不統(tǒng)一(即不保持寬高比)的情況下縮放給定元素的圖像內(nèi)容直到元素的邊界盒完全匹配是視口矩形。

換句話說,如果有必要的話viewBox被拉伸或縮放來完全適應(yīng)整個(gè)視口,不管寬高比。圖形也許會(huì)扭曲。

(注意:如果的值是none,可選的值<meetOrSlice>無效。)

②xMinYMin

  • 強(qiáng)制統(tǒng)一縮放
  • 視口X軸的最小值對齊元素viewBox的<min-x>。
  • 視口Y軸的最小值對齊元素viewBox的<min-y>。
  • 把這個(gè)類比為backrgound-position: 0% 0%;。

③xMinYMid

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的最小值對齊元素viewBox的<min-x>。
  • 視口Y軸的中間值來對齊元素的viewBox的中間值。
  • 把這個(gè)類比為backrgound-position: 0% 50%;。

④xMinYMax

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的最小值對齊元素viewBox的<min-x>。
  • 視口X軸的最大值對齊元素的viewBox的<height>+<min-y>。
  • 把這個(gè)類比為backrgound-position: 0% 100%;。

⑤xMidYMin

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的中間值對齊元素的viewBox的X軸中間值。
  • 視口Y軸的最小值對齊元素的viewBox的最小值 。
  • 把這個(gè)類比為backrgound-position: 50% 0%;。

⑥xMidYMid (默認(rèn)值)

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的中間值對齊元素的viewBox的X軸中間值。
  • 視口Y軸的中間值對齊元素的viewBox的Y軸中間值。
  • 把這個(gè)類比為backrgound-position: 50% 50%;。

⑦xMidYMax

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的中間值對齊元素的viewBox的X軸中間值。
  • 視口Y軸的最大值對齊元素的viewBox的<height>+<min-y>。
  • 把這個(gè)類比為backrgound-position: 50% 100%;。

⑧xMaxYMin

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的最大值對齊元素的viewBox的 <width>+<min-x>。
  • 視口Y軸的最小值對齊元素的viewBox的<min-y>。
  • 把這個(gè)類比為backrgound-position: 100% 0%;。

⑨xMaxYMid

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的最大值對齊元素的viewBox的 <width>+<min-x>。
  • 視口Y軸的中間值對齊元素的viewBox的Y軸中間值。
  • 把這個(gè)類比為backrgound-position: 100% 50%;。

⑩xMaxYMax

  • 強(qiáng)制統(tǒng)一縮放。
  • 視口X軸的最大值對齊元素的viewBox的 <width>+<min-x>。
  • 視口Y軸的最大值對齊元素的viewBox的 <height>+<min-y>。
  • 把這個(gè)類比為backrgound-position: 100% 100%;。

所以,通過使用preserveAspectRatio屬性的align和meetOrSlice值,你可以聲明是否統(tǒng)一縮放viewBox,是否和視口對齊,在視口中是否整個(gè)可見。

有時(shí)候,取決于viewBox的尺寸,一些值可能會(huì)導(dǎo)致相似的結(jié)果,例如在早先viewBox="0 0 200 300"的例子中,一些對齊完全用了不同的align值。這時(shí)候就要設(shè)置meetOrSlice的值為meet來保證viewBox包含在viewport內(nèi)。

The result of aligning the viewBox using different align values. The meetOrSlice value is set to meet.->viewbox-meet-align-same.jpg

如果我們把meetOrSlice的值改成slice,不同的值我們將得到不同的結(jié)果。注意viewBox是如何拉伸來覆蓋整個(gè)視口的。x軸被拉伸到用200單位來覆蓋視口800單位。為了達(dá)到這個(gè)目的,并且保持viewBox的寬高比,y軸在底部被“裁切”,但是你可以想象它在視口中高度上的延伸。

The result of aligning the viewBox using different align values. The meetOrSlice value is set to slice.->viewbox-slice-align-same.jpg

當(dāng)然,不同的viewBox值看起來不同于我們這里用的200*300。為了保持簡潔,我們不再列舉更多的例子,你可以看我創(chuàng)建的一些互動(dòng)演示來幫助你更好地形象化理解viewBox和preserveAspectRatio在不同值下的效果。你可以在一下節(jié)中查看互動(dòng)演示例子的鏈接。

但是在這之前,我想要提醒你注意如果 <min-x>和<min-y> 值改變,那么mid-x, mid-y, max-x, 和 max-y的值也會(huì)發(fā)生改變。你可以在互動(dòng)演示中改變這些值來查看軸以及相關(guān)聯(lián)的viewBox的對齊方式的改變。

下面圖片展示了定位軸的位置為viewBox = "100 0 200 300"時(shí)的效果。和之前用一樣的例子,但是我們把的<min-x>值設(shè)為100而不是之前的0。你可以設(shè)置成任何你想要的值。注意min-x, mid-x, 和 max-x軸是如何變化的。這里使用的preserveAspectRatio值為默認(rèn)的xMinYMin meet,意味著mid-*軸和視口軸的中間對齊。

The effect of changing the value of <min-x> on the position of the x-axes. The translucent blue area shows the area which is considered to be the viewBox area after changing the value of <min-x>.->viewbox-axes-changed-min-x-min-y.jpg

互動(dòng)演示

要理解viewport, viewBox, 以及不同的preserveAspectRatio值是如何工作的最好方法是可視化的演示。

出于這個(gè)目的,我創(chuàng)建了一個(gè)簡單的互動(dòng)演示,你可以改變這些屬性的值來查看新值導(dǎo)致的結(jié)果。

demo1.jpeg

在線案例

我希望這篇文章在幫助你理解SVG viewport, viewBox, 和 preserveAspectRatio 內(nèi)容時(shí)有作用。如果你想要了解更多關(guān)于SVG坐標(biāo)系的內(nèi)容,例如嵌套坐標(biāo)系,建立一個(gè)新的坐標(biāo)系以及SVG中的變換,繼續(xù)閱讀這一系列接下來的部分。感謝你的閱讀!

本文根據(jù)SaraSoueidan的《Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, viewBox, and preserveAspectRatio》一文所譯,整個(gè)譯文帶有我們自己的理解與思想,如果譯得不好或有不對之處還請同行朋友指點(diǎn)。如需轉(zhuǎn)載此譯文,需注明英文出處http://sarasoueidan.com/blog/svg-coordinate-systems/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,555評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內(nèi)容