首頁 >web前端 >H5教程 >深入解析HTML5使用SVG映像時的viewBox屬性用法_html5教學技巧

深入解析HTML5使用SVG映像時的viewBox屬性用法_html5教學技巧

WBOY
WBOY原創
2016-05-16 15:46:292247瀏覽

快速了解viewBox的參數

viewBox屬性是用來指定使用者SVG影像的座標系統的原點以及尺寸的。所有在SVG內繪製的內容都是相對於這個座標系統完成的。因為SVG畫佈在所有方向都是無限延長的,你甚至可以在這個座標系統的邊界之外的地方繪製圖形;但是這些相對於SVG視窗定位的圖形,也可以由使用者座標系的位置來控制。

viewBox屬性使用四個參數來指定座標係原點的位置以及它的尺寸:x y width height。初始情況下,這個座標係等同於初始化的視窗座標系(由SVG影像的width和height決定),而且它的原點是在(0, 0)-即SVG的左上角。

藉由改變x和y這兩個參數的值,可以調整原點的位置。改變width和height的值,可以改變座標系統的尺寸。只使用viewBox屬性,就可以幫你擴充或裁切SVG畫布。跟著範例一起閱讀。

重要提示:在本文章中,我不會改變viewBox在SVG視窗內的預設行為(比例和位置)。因為,根據屬性的預設行為,viewBox的內容會被盡可能地完全包含在視窗內,然後放置在中心位置。不過,使用preserveAspectratio屬性可以讓你自由地改變viewBox的尺寸和位置,但是在這篇文章中,這不是必需的技術,所以我們也不會在這裡深入講解。
使用viewBox裁切SVG,即使用viewBox屬性製作Art Direction的SVG

前陣子,我的一個客戶要求把他網站的SVG頭像按照不同的屏幕尺寸設置成不同的大小,從而使得它只有一小部分是在小屏幕上可見的,在中等的屏幕尺寸上可以看到再大一點的部分,然後在大螢幕上可以看到完整的內容。當時我腦中首先出現的想法是,他的要求其實是使用viewBox屬性來裁剪SVG圖像,然後根據不同的螢幕尺寸,顯示他想要看到的圖像的某一部分。

透過改變SVG座標系統的尺寸和原點位置,我們可以把SVG進行裁剪,並顯示我們希望在視窗中顯示的那部分內容。

我們來看看如何實現。

假設我們有以下這張完整的SVG圖像,然後我們想要把它裁剪成小螢幕的尺寸。這張圖是Freepik設計的可免費使用的房屋向量圖,該圖片有Creative Commons Attribution 3.0 Unported協議的許可授權。為了簡單起見,我們先假設圖像只是要裁剪成在中小螢幕上顯示的內容,以及大螢幕上顯示的完整的內容,如下所示。

左邊的圖的是我們將要使用viewBox屬性裁切的完整的圖片,右邊的圖是我們希望在小螢幕上顯示的區域。

現在,透過改變viewBox屬性的值來裁切SVG。有一些需要考慮的內容,我們等會談到。但首先,我們要改變座標系統,讓它符合上面的圖片中虛框矩形區域的內容。 ,透過調整系統的原點以及width和height的值,我們可以改變它初始的0 0 800 800參數值。

但是我們要如何獲知新座標和新尺寸呢?重點是不要經過大量重複的實驗和錯誤。

有幾種方式。因為我們已經在圖形編輯器中(我的範例使用的是AI),我們可以使用編輯器的面板來取得元素的位置和尺寸。

我畫這個虛線的矩形框,除了用來表示我想要在小螢幕上顯示的內容,還有一個原因就是:我們可以取得這個矩形的位置和尺寸,然後把它們當作viewBox的值來使用。使用AI的變換面板(如下圖),我們取得了我們需要的這些值。透過選擇矩形,並點擊右上角的變換鏈接,我們得到瞭如下圖所示的面板,包括我們所需要的x, y, width和height值。

這個AI中的變換面板可以用來取得選取矩形的位置和尺寸的值

你可能注意到了,上面的數值並不是整數,所以我們需要手動修改。根據上面的訊息,我們把viewBox的值改成 0 200 512 512。

因為新的viewBox的寬高比和SVG視窗的寬高比是一樣的(都是正方形),viewBox內的內容將會擴大,並且只有被選中的區域會在視窗中顯示。改變viewBox的值之後,結果如圖:

新裁剪的SVG。只有我們指定使用viewBox屬性的位置在視窗中是可見的。藍色邊框表示SVG的視窗。

在這一點上,有一個問題需要解決:

如果被裁切區域(即viewBox)的寬高比 != SVG視窗的寬高比?

在這種情況下,將會有明顯的溢出。明顯的溢出,我指的不是超出SVG視窗邊界的延伸,而是viewBox定義的相對於新使用者座標系統的溢出。下圖作了對應的說明。

如果viewBox的寬高比和視窗的寬高比不同,SVG中的內容會溢出使用者座標系統,結果可能會是這樣。

黑色邊框代表新的使用者座標系,藍色邊框是SVG視窗。

上邊右圖中的黑色邊框是viewBox定義的區域。根據viewBox在視窗內的預設行為,它會被居中並儘可能放大,來確保自身內容盡可能地包含在視窗(藍色邊框)中。

因為SVG畫布從概念上來說,在所有方向都是無限延伸的,你可以在使用者座標系統邊界之外繪製圖形,內容會直接溢出移動,如上圖所示。

如果你改變了SVG視窗的寬高比(SVG的width和height),來讓它們適應viewBox的寬高比,你就不會看到溢出了,因為viewBox的縮放是適應視窗的,和前面的範例一樣。

但是,在某些情況下,你可能不能或根本不想改變SVG的寬高比。比如說,如果你是使用SVG sprite作為一組圖片來顯示頁面上圖片的。在大多數情況下,影像都有一個固定的寬高比——而且你不想改變改變影像的尺寸,就為了適應它裡面的某一張小圖的內容。或者可能你嵌入了一個圖示系統,並希望所有的圖示在同一時間都保持相同的尺寸。

為了剪掉多餘的東西(比如說,sprite上的部分其它圖標,在視窗中顯示),你可以使用來把多餘的部分裁剪掉。裁切路徑可以是一個覆蓋了整個viewBox區域的元素,然後將該元素套用到root SVG。

但是,還有一點要記住:確保的x和y屬性和viewBox的保持一致,除非rect將被相對定位於原來的/初始化的系統的原點,那麼SVG最終被裁剪的內容也是不確定的。

CSS Code複製內容到剪貼簿
  1. "http://w3.org/2000/svg"  height" clip-path="url(#clipper)" "url(#clipper)" =".." height=".."=".."
  2. ".."
  3. "..""..""..""..""..""..""..
  4. >   
  5.             "clipper">            "vx" y="vy" y="vy"" y="vy"" y=
  6. "vy""
  7.  y="vy""
  8.  y=
  9. "vy"
  10. =
"100%"
 height=height=height=height=height=height=height=height 🎜>>              

當然,裁剪多餘的部分也意味著你仍然在使用不同的寬高比,還是需要解決內容兩邊多出的空白。如果SVG是一個連續的場景,像我們前面的那個例子,那就沒必要了,因為你還需要調整視窗的寬高比。如果SVG是一組圖標,而你只是在不同的視窗中使用一次,這可能就不是問題了。

這裡有一點重要的東西要記住,viewBox的寬高比最好還是和視窗的寬高比保持一致;另外,你需要設定固定來避免SVG中任何不確定的多餘的空白出現。

所以,viewBox可以用來裁切SVG,並依需求只展示SVG的某部分內容。但是它要如何應用在實例呢?

在響應式設計中的Art Directing SVG

這部分沒有什麼需要補充的內容,除了實際過程的程式碼。所以,假設你有如上所示的SVG,並且想要把它作為頭像,比如說,在中小尺寸的屏幕上你只想顯示裁剪下來的那部分內容,然後在大屏幕上顯示完整的頭像。

改變SVG視窗的width和height值,我們可以使用CSS。但是改變viewBox的值,目前我們需要使用JavaScript。

並非所有的SVG屬性,CSS屬性都可以等同使用;只有一組具有和CSS屬性相同效果的屬性才可以在CSS中設定。你可以在這個表格中查看這組可以作為CSS屬性的SVG屬性的概述。在SVG2中,許多屬性(如x, y, cx, cy, r等等)都可以被加到這個清單中;但是這些都是我們現在可以使用的屬性。

為了展示SVG的不同部分,需要基於不同媒體查詢改變viewBox的值,你可以使用Modernizr,找出媒體查詢條件,然後在JavaScript中對應更改viewBox的值。例如下:

CSS Code複製內容到剪貼簿
  1. // 取得root 的引用   
  2. var svgRoot = ...; // 取決於你如何嵌入並引用SVG   
  3. // 定義viewBox的參數值   
  4. var vbValue = '0 200 512 512';   
  5. // 使用Modernizr的媒體查詢擷取來改變viewBox的值   
  6. if (Modernizr.mq('(max-width: 700px)')) {   
  7. )) {       svgRoot.setAttribute('viewBox'
  8. , vbValue);   
  9. }   
// 其它的尺寸狀況  

這是可以運作的,但是如果我們可以使用CSS來完成這個效果豈不更讚?

使用CSS的viewBox屬性來裁切SVG

免責聲明:在寫這篇文章的時候,並沒有CSSviewBox屬性。這只是一個用來解釋為什麼這個屬性有用,以及我想像的它如何被使用的範例。
理想情況下,我們可以這樣使用它: CSS Code
複製內容到剪貼簿
  

這些樣式會被放進(或取出)SVG中,然後SVG將會根據視窗的尺寸調整其viewBox值。讓它成為頁面視窗(內聯)的情況),或透過其它任何引用SVG的元素的尺寸確定的視窗(這可以給我們一些近乎相同的元素查詢)。

不過,這在目前是不可能實現的,因為CSS中還沒有viewBox屬性。

前陣子,我就這個問題詢問了一個SVG規範的編輯,他說我可以根據實際使用情況和實例,向SVGWG提建議。後來在Twitter上進行了一些討論,我才發現在幾年前已經有一個相似的SVGWG proposal thread。當初的提議今天仍然存在,所以我希望,能夠透過一些實際使用範例,推進這個提議,並在不久的將來可以實現。如果你也想要在CSS中看到viewBox屬性,請幫助實現這一目標,推動這個提議的轉發和評論。

使用viewBox完成SVG Art-Direction的時候,需要記住的東西

在做我的客戶的專案的時候,我花了一分鐘不到的時間來按照對方的要求對頭像進行art-direct。但是,這最終分出了三個獨立的SVG,而不是不同螢幕尺寸上的相同SVG不同viewBox。

我們選擇三個SVG的原因是,完整SVG的尺寸太大,在行動端達到了100kb以上的大小。最初的SVG是200kb左右的,我可以透過優化SVG來把檔案壓縮到接近一半的大小,但對於行動裝置來說,圖片還是太大了,所以最後我們只能使用三張不同大小的圖片。 art-directing SVG的時候,需要記住的就是:效能問題。如果你的SVG太大了,不要用viewBox來art-direct。

現在,如果你選擇使用三個不同的SVG映像,也有多種可能的方式可以完成——這取決於你嵌入SVG的方法,也取決於你想要完成什麼、不想完成什麼。

使用元素來完成不同SVG映像是最理想的方式。它不僅能夠根據瀏覽器為我們提供不同的可供選擇的SVG,而且還不需要使用JavaScript,還可以讓我們對不支援它的瀏覽器(IE8及以下)提供多種優化的降級圖像。 對於使用SVG是非常有用的,你可以在這篇文章中閱讀所有SVG fallback的內容。

但如前面所說,如果你想要有動畫或互動效果的SVG,不是最佳選擇。就像使用深入解析HTML5使用SVG映像時的viewBox屬性用法_html5教學技巧嵌入SVG,SVG不能被添加樣式和動畫,除非樣式和動畫是在文件中定義的,SVG不能添加腳本(出於安全考慮),也不能有任何交互(CSS或JS)-比如說,懸停,不會有互動效果。

所以,我總是說:SVG為我們提供了很多選項,可以讓我們完成幾乎所有的事情;你需要做一個權衡、要主次分明、有時甚至需要作出妥協,基於此作出最佳的選擇。但對於性能,永不妥協才有利於發展!

在我們結束之前,因為我們提到了使用viewBox屬性改變SVG畫布尺寸的問題,我們來看看另一個例子,我們可以藉助這個屬性來幫我們在處理SVG時節省一些時間和精力。

使用viewBox擴充SVG畫布

正如viewBox屬性可以用來縮放SVG,它也可以用來擴充SVG畫布。

幾週前我創建了一個可以產生SVG圓形選單的工具。我建立了幾個例子來示範如何使用JavaScript讓產生的選單動起來。 demo使用元素嵌入到應用程式頁面上。 的邊界定義了SVG視窗的邊界,任何在這些邊界之外的內容都是溢出,而且預設為隱藏。

需要注意的是「邊界之外」指的是在SVG中的內容,它還是在無窮大的SVG畫布上的,但是超過了由視窗定義的無窮大的矩形

譯者註:關於SVG畫布、視窗的內容可閱讀w3cplus上的相關文章。
建立的選單,SVG的尺寸是剛好可以將選單包含進去,而沒有再大一些。避免了菜單周圍任何多餘的空白。

我給某個選單套用了一個彈跳動畫,作為選單動畫的範例。這個彈跳效果「拉長了」各菜單項,也導致了菜單項目在它們彈跳的時候會單獨切出來(即溢出)。

起初,由於SVG視窗是由元素定義的,所以視窗和選單本身是一樣大的,選單項目上的彈跳效果導致了這些選單項目在彈跳的時候溢出。

這些可愛的彈跳動畫應用於那些使用彈跳時間函數從0開始放大到100%的項目(即該項目最初是不可見的,縮小狀態),這個效果就是如果項目彈跳到超過了100%的大小,那就把它縮回100%。這個效果會導致物品在彈跳超過SVG邊界的時候溢出。

下圖展示了縮放選單項目在放大到超過的邊界(灰色邊框)的時候的效果,其中,用於嵌入這個縮放選單項目。

上方的示意圖展示了選單項目放大到溢出SVG視窗邊界時的效果。灰色邊框表示SVG視窗的邊框(即元素)。

設定overflow: visible也不能解決問題,因為

為了延長SVG畫布,只需簡單增加它的尺寸。因此,我們使用的是700 x 500px的尺寸,而不是500 x 250這個SVG選單的原始尺寸。這也會讓畫佈在視窗中顯示的高度增加100px,而視窗中的畫布寬度會增加200px。我根據這些選單項目在彈跳效果需要放大的空間來決定這些值。根據您的SVG以及您要完成的具體內容,這些值並不要求一致。

現在,為了確保選單是放置在視窗的中心的,我們需要把座標系統的位置往負方向分別移動100px(即向上和向左)。把這個移動應用到座標系統的原點上,和把一個平移轉換應用到系統中的選單上是一樣的。結果是菜單會在視窗中保持居中。

在該圖中,藍色邊框表示SVG視窗邊界(即元素),灰色邊框表示使用者座標系統的初始尺寸。藍色數字和箭頭表示視窗中的座標系統的擴展。

在延長使用者座標系統尺寸的同時,你也增加了畫佈在視窗中可見區域的面積。這樣做的結果是畫布的內容會顯得略小——這根據你把畫布放大了多少而定。但是對於菜單來說,這樣的結果是可以接受的。

下面的螢幕記錄顯示了擴展SVG畫布的結果,以及在SVG邊界內的選單動畫效果。

一旦SVG畫布被擴展,選單項目就有足夠的空間來進行縮放,在應用彈跳效果的時候也不會再因為溢出被剪切。

透過改變viewBox屬性的四個參數值來延伸SVG畫布,這樣所有問題以及選單項目被剪切的問題都可以解決。 viewBox確實非常棒~~

結束語

viewBox屬性非常棒,它就是一個SVG的加強版工具。透過使用這個屬性,在使用SVG進行工作時就可以節省很多時間,無需借助圖形編輯器即可快速解決SVG的問題。總而言之,這對於編輯SVG真的方便了很多。

我強烈建議你全面學習這個屬性,然後讓它在你的工作中發光發熱。如果你想要使用它來做art-direct SVG,不要忘了效能才是重點。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn