理解 SVG 中的 Viewport 和 ViewBox - 實做縮放(zoom)和拖曳(drag)效果
本文章同步刊載於 PJCHENder 前端網頁資源站
不同於以往將 SVG 視為一張圖案(ICON 或 LOGO)的概念,在這篇文章中,我們要試著將 SVG 視為一個畫布(Canvas),而我們可以透過滑鼠來直接對這個畫布像 Google Map 一樣進行拖曳和縮放。
要將 SVG 視為一個畫布,並實做出縮放或拖曳的功能,有許多對於 SVG 的基本概念是我們需要先瞭解的,就讓我們一步一步來瞭解。
註 1:在這篇文章中我們會把 SVG 視為一個畫布(Canvas)而不是去探究 SVG 中各個元素(例如,
<rect></rect><circle></circle>
)。 註 2:在這篇文章中我們只考慮 viewport 和 viewBox 為等比例的情況。
最後實做出來的功能會像這樣子:實做 SVG 拖曳與縮放
瞭解 SVG 中的 Viewport 和 ViewBox
在 SVG 的世界中,空間的概念可以分成 Viewport 和 ViewBox 兩個部分。在這篇文章中,我會把它 Viewport 比喻作相框,ViewBox 比喻作相片。
Viewport 相對上比較好理解,就是相框的大小,也就是你的眼睛看得到的範圍,不管你的相片多大,你能看到的實際範圍就是相框的大小。在網頁中我們可以透過設定 viewport 來調整我們相框的大小。
ViewBox 則可以想成是這張照片的大小,如果相片的大小和相框(viewport)一樣大的時候,自然不會有什麼問題,你可以從相框中看一樣大的相片。可是,如果相片(viewbox)比起相框來得大或來得小時,這時候就會比較麻煩些,你會需要多去控制說這張相片應該要如何的排置在相框上,才能夠呈現出你想要呈現的東西,因此 ViewBox 中除了能夠控制的相片的大小之外,還能夠控制相片要如何擺放在相框中。
讓我們來瞭解一下 viewport 和 viewbox 的概念:
當 viewBox 等於 viewport 的情況(初始化的情況)
首先,我們可以直接在 SVG 元素上定義 viewport 的寬高,或者你也可以用 CSS 定義,基本上這個 DOM 元素的寬高就是 viewport 的寬高,也就是你相框的寬高。接著我們可以在 SVG 中定義我們的圖案內容,在這裡先用一隻鳥當作示範。
<svg id="svgElement" width="800" height="400">
<g><!-- 鳥的圖形 --></g>
</svg>
這時候便會得到如下的一個 viewport:
再來我們可以設定 viewBox
, viewBox 的設定可以寫在 SVG 的標籤上,設定屬性包含 <min-x>
<min-y>
<width>
<height>
這四個屬性,也就是 viewBox = '<min-x> <min-y> <width> <height>'
。
我們剛剛有提到,ViewBox 中除了能夠控制的相片的大小之外,還能夠控制相片要如何擺放在相框中,其中 <min-x>
和 <min-y>
就是在控制相片要如何擺放在相框中,而 <width>
和 <height>
則是相片的大小。
預設的情況下(沒有特別去設定 viewBox 的情況下)viewBox 的尺寸大小會和 viewport 一樣,因此當我們把鳥的相片放入 svg 後,他會自動填滿整個相框,兩個的大小會是一樣的,程式碼會像這樣:
<svg id="svgElement" width="800" height="400" viewBox="0 0 800 400">
<g><!-- 鳥的圖形 --></g>
</svg>
相片會很完整的融入在相框當中
viewBox 初始化時尺寸大小會和 viewport 一樣
當 viewbox 小於 viewport 時:圖案會被放大
透過 viewBox 的設定,我們可以進一步放大或縮小我們的相片,這裡有一個原則是,viewBox 會自動盡可能去填滿成 viewport 的大小*,說起來很抽象,假設一開始我的 viewport 為 800 x 400 ,現在我們可以透過 viewBox 的設定,使得我們 viewBox 的大小變成 400 x 200,當我們的相片大小設定的比相框還小時,它會在原本的相片上裁切一小塊區域(在這裡是 400 x 200),接著把它調整到填滿整個 viewport 的大小(800 x 400)。
分解過程像是這樣(綠色是 viewport,藍色是 viewBox)
- 設定比 viewport 還要小的 viewBox:
- 裁切: