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

快速了解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
html5的div一行可以放两个吗html5的div一行可以放两个吗Apr 25, 2022 pm 05:32 PM

html5的div元素默认一行不可以放两个。div是一个块级元素,一个元素会独占一行,两个div默认无法在同一行显示;但可以通过给div元素添加“display:inline;”样式,将其转为行内元素,就可以实现多个div在同一行显示了。

html5中列表和表格的区别是什么html5中列表和表格的区别是什么Apr 28, 2022 pm 01:58 PM

html5中列表和表格的区别:1、表格主要是用于显示数据的,而列表主要是用于给数据进行布局;2、表格是使用table标签配合tr、td、th等标签进行定义的,列表是利用li标签配合ol、ul等标签进行定义的。

html5怎么让头和尾固定不动html5怎么让头和尾固定不动Apr 25, 2022 pm 02:30 PM

固定方法:1、使用header标签定义文档头部内容,并添加“position:fixed;top:0;”样式让其固定不动;2、使用footer标签定义尾部内容,并添加“position: fixed;bottom: 0;”样式让其固定不动。

html5中不支持的标签有哪些html5中不支持的标签有哪些Mar 17, 2022 pm 05:43 PM

html5中不支持的标签有:1、acronym,用于定义首字母缩写,可用abbr替代;2、basefont,可利用css样式替代;3、applet,可用object替代;4、dir,定义目录列表,可用ul替代;5、big,定义大号文本等等。

HTML5中画布标签是什么HTML5中画布标签是什么May 18, 2022 pm 04:55 PM

HTML5中画布标签是“<canvas>”。canvas标签用于图形的绘制,它只是一个矩形的图形容器,绘制图形必须通过脚本(通常是JavaScript)来完成;开发者可利用多种js方法来在canvas中绘制路径、盒、圆、字符以及添加图像等。

html5废弃了哪个列表标签html5废弃了哪个列表标签Jun 01, 2022 pm 06:32 PM

html5废弃了dir列表标签。dir标签被用来定义目录列表,一般和li标签配合使用,在dir标签对中通过li标签来设置列表项,语法“<dir><li>列表项值</li>...</dir>”。HTML5已经不支持dir,可使用ul标签取代。

Html5怎么取消td边框Html5怎么取消td边框May 18, 2022 pm 06:57 PM

3种取消方法:1、给td元素添加“border:none”无边框样式即可,语法“td{border:none}”。2、给td元素添加“border:0”样式,语法“td{border:0;}”,将td边框的宽度设置为0即可。3、给td元素添加“border:transparent”样式,语法“td{border:transparent;}”,将td边框的颜色设置为透明即可。

html5为什么只需要写doctypehtml5为什么只需要写doctypeJun 07, 2022 pm 05:15 PM

因为html5不基于SGML(标准通用置标语言),不需要对DTD进行引用,但是需要doctype来规范浏览器的行为,也即按照正常的方式来运行,因此html5只需要写doctype即可。“!DOCTYPE”是一种标准通用标记语言的文档类型声明,用于告诉浏览器编写页面所用的标记的版本。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版