资讯专栏INFORMATION COLUMN

[技術分享] 理解 SVG 中的 Viewport 和 ViewBox-拖曳與縮放功能實做(上)

Leo_chen / 2695人阅读

摘要:註在這篇文章中我們只考慮和為等比例的情況。最後實做出來的功能會像這樣子實做拖曳與縮放瞭解中的和在的世界中,空間的概念可以分成和兩個部分。實際感受的效果在她所撰寫文章中提供了非常好的實做案例。這個座標系統是相對固定的。

理解 SVG 中的 Viewport 和 ViewBox - 實做縮放(zoom)和拖曳(drag)效果

本文章同步刊載於 PJCHENder 前端網頁資源站

不同於以往將 SVG 視為一張圖案(ICON 或 LOGO)的概念,在這篇文章中,我們要試著將 SVG 視為一個畫布(Canvas),而我們可以透過滑鼠來直接對這個畫布像 Google Map 一樣進行拖曳和縮放。

要將 SVG 視為一個畫布,並實做出縮放或拖曳的功能,有許多對於 SVG 的基本概念是我們需要先瞭解的,就讓我們一步一步來瞭解。

註1:在這篇文章中我們會把 SVG 視為一個畫布(Canvas)而不是去探究 SVG 中各個元素(例如,)。
註2:在這篇文章中我們只考慮 viewport 和 viewBox 為等比例的情況。

最後實做出來的功能會像這樣子:實做 SVG 拖曳與縮放

瞭解 SVG 中的 Viewport 和 ViewBox

在 SVG 的世界中,空間的概念可以分成 Viewport 和 ViewBox 兩個部分。在這篇文章中,我會把它 Viewport 比喻作相框,ViewBox 比喻作相片。

Viewport 相對上比較好理解,就是相框的大小,也就是你的眼睛看得到的範圍,不管你的相片多大,你能看到的實際範圍就是相框的大小。在網頁中我們可以透過設定 viewport 來調整我們相框的大小。

ViweBox 則可以想成是這張照片的大小,如果相片的大小和相框(viewport)一樣大的時候,自然不會有什麼問題,你可以從相框中看一樣大的相片。可是,如果相片(viewbox)比起相框來得大或來得小時,這時候就會比較麻煩些,你會需要多去控制說這張相片應該要如何的排置在相框上,才能夠呈現出你想要呈現的東西,因此 ViewBox 中除了能夠控制的相片的大小之外,還能夠控制相片要如何擺放在相框中

讓我們來瞭解一下 viewport 和 viewbox 的概念:

當 viewBox 等於 viewport 的情況(初始化的情況)

首先,我們可以直接在 SVG 元素上定義 viewport 的寬高,或者你也可以用 CSS 定義,基本上這個 DOM 元素的寬高就是 viewport 的寬高,也就是你相框的寬高。接著我們可以在 SVG 中定義我們的圖案內容,在這裡先用一隻鳥當作示範。


    

這時候便會得到如下的一個 viewport:

再來我們可以設定 viewBox , viewBox 的設定可以寫在 SVG 的標籤上,設定屬性包含 這四個屬性,也就是 viewBox = " "

我們剛剛有提到,ViewBox 中除了能夠控制的相片的大小之外,還能夠控制相片要如何擺放在相框中,其中 就是在控制相片要如何擺放在相框中,而 則是相片的大小。

預設的情況下(沒有特別去設定 viewBox 的情況下)viewBox 的尺寸大小會和 viewport 一樣,因此當我們把鳥的相片放入 svg 後,他會自動填滿整個相框,兩個的大小會是一樣的,程式碼會像這樣:


    

相片會很完整的融入在相框當中

當 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:

裁切:

![SVG viewport and viewBox](https://2.bp.blogspot.com/-j8... "這時候因為我們設定的尺寸比相片原本的大小還要小,所以相片會被裁切。
")

填滿 viewport

文字範本mdimg

這時候就會產生一個很神奇的現象,雖然我的相因為設定的尺寸片(viewBox)比原本的尺寸來的小,但是因為它會自動去填滿整個 viewport 的緣故,所以實際上相片被放大了。

程式碼寫起來像是這樣,設定為 viewBox="0 0 400 200"


    
當 viewbox 大於 viewport 時:圖案會被縮小

類似的道理,當我們設定的 viewBox 大於 viewPort 時,它會先把這張照片的底圖放大(先放大成 1600 x 800),然後在盡可能的塞入 viewport 當中(這裡是 800 x 400):

所以,雖然 viewBox 的設定(1600 x 800)大於原始 viewBox 的大小(800 x 400),但是實際上,照片在實際顯示上卻會被縮小。程式碼寫起來會像這樣子,viewBox="0 0 1600 800"


    
瞭解 SVG ViewBox 位置的設定

在 viewBox 的設定中,包含了四個屬性值 viewBox = " ",除了上面我們所說的可以設定照片的大小外,也可以裡用 這兩個屬性來設定相片的位置。

例如說當我設定 viewBox 的 min-x 為 150 時( viewBox = "150 0 800 400" ),viewBox 會向左移動 150 單位 :

我們也可以同時設定 min-x 和 min-y ,例如(viewBox = "-400 -200 800 400"),會得到這樣的效果:

最後實際上可以看到的樣子:

viewBox 設定造成的影響

在 viewBox 的設定的四個屬性值中 viewBox = "min-x min-y width height",我們可以簡單理解成前兩項 min-xmin-y 控制的是位移(translate),可以達到左右移動的效果;後兩項 widthheight 控制的則是縮放(scale)。

但是因為 viewBox 實際上影響的是 SVG 當中的座標系統(後面會說明 SVG 座標系統),所以會和你的直覺有寫相反,例如,##當你設定 min-x 和 min-y 越大時,實際上看到的畫面會往左上方移動##;同樣地,##當你設定width 和 height 越大時,實際上看到的畫面會往縮小##。

這個部分需要你花一些時間實際感受一下,非常建議利用下段中由 Sara Soueidan 所提供的實做案例感受。

實際感受 SVG 的效果

Sara Soueidan 在她所撰寫文章中 Understanding SVG Coordinate Systems and Transformations (Part 1) — The viewport, viewBox, and preserveAspectRatio 提供了非常好的實做案例。

左上角的地方你可以去以用拖拉的方式去設定 viewBox 的值,以此感受 viewBox 的改變對於視覺上顯示的效果,另外,由於它的 viewport 是 (800 x 600) 所以建議你可以先把 viewBox 的長寬設為 800 x 600(也就是初始化時預設 viewport = viewBox 的狀況),接這再來實際操作看看 viewBox 的改變會有什麼樣的效果。

當 viewport 和 viewBox 的尺寸並不是等比例時:preserveAspectRatio

我們提到,當 viewBox 和 viewport 的尺寸大小不一樣時, viewBox 會盡可能的去填滿整個 viewport ,可是在上面文章的例子中,我們都把 viewBox 的尺寸大小設定的和 viewPort 是等比例的情況,如果是不同比例的話,又要用什麼樣的方式來對齊和填滿呢?

這時候我們就會需要用到 preserveAspectRatio 這個屬性了。在這個屬性當中可以設定對齊的方式(align)還有要用什麼樣的方式填滿(meet or slice)。在這篇文章中,我只打算探討 viewBox 和 viewport 為等比例的情況,我認為要瞭解 viewport 和 viewBox 的概念時,先以等比例的情況當作實例來練習是比較容易瞭解的,因為在等比例的情況下,preserveAspectRation 的值對於畫面的呈現是沒有任何影響的,如果對於 preserveAspectRatio 的屬性想要有更多的瞭解,可以參考這篇文章([譯] 理解 SVG 座標系統與 Transformations @ Andyyou),或進一步參考文章中最後面所列的參考文章。

深入瞭解 SVG 座標系

從上面我們可以看出當我們為 SVG 元素設定 viewBox 時,SVG 會有很多特別的效果,我們可以視整個 SVG 元素為一個畫布,對它進行縮放和移動,而實際上在 SVG 的世界中,我們要瞭解viewport 和 viewBox 實際上是處在兩個不同的座標系統中

在 viewport 中,是我們過去所熟悉的,以瀏覽器中 DOM 為主的座標系統,通常把它稱作 viewport 座標系統(viewport coordinate system)canvas 座標系統(但是不要把它和 HTML 中的 Canva 標籤搞混)。一般來說,在這個座標系統中,1px 就是 1px 大,這個座標系統是相對固定的。這個座標系統是相對固定的。在後面的文章中,我會使用 viewport 座標系統這個詞。

在 viewBox 的座標系統中,就不是我們所習慣的情況了,我們一般把在 viewBox 的座標系統吃做作 SVG 座標系統(SVG coordinate system)用戶座標系統(user coordinate system)(或 the current coordinate systemuser space in use
。在後面的文章中,我會使用 SVG 座標系統這個詞。

在這個座標系統中,值是不一定要有單位的,如果我們沒有給它單位時,預設它會以 viewport 的單位為單位(例如,px),然而,恐怖的特別的地方在於,當我們在設定 viewBox 時,如果對於這當圖片有縮放時,那麼它的 1 單位大小將不會再是 1px 。

認識不同的座標名稱

為了幫助我們更進一步的探討 SVG 座標系統和 viewport 座標系統,我們要來認識三種不同的座標名稱,分別是 offsetclientSVG Point

其中 offset 和 client 所取得的值都是屬於 viewport 座標系統中的座標值(也就是 1px 就是真實的 1px),兩者的差別在於 offset 是相對於 container 左上角的點,也就是以 container 左上角為(0, 0);而 client 則是相對於 window 左上角(瀏覽器視窗左上角)的點,以 window 左上角為(0, 0),越右 X 值越大,越下 Y 值越大。

SVG 座標系統就比較特別一點了,它有專屬的座標點,可以透過 viewport 座標系的 client 座標加以轉換。

我們會在下一篇文章中說明如何取得這三個座標值,但目前你需要知道有這三種不同的座標名稱。

viewBox 等同於 viewport 時

我們用 Sara Soueidan 在所提供的互動案例來做更多說明,一開始的時候,我先把 viewBox 設成和 viewport 一樣大,在這種情況下 SVG 座標系統中的 1 單位大小會和 viewport 的一樣大,也就是 1px。留意藍色的尺標是 SVG 座標系統、灰色的尺標則是 viewport 座標系統:

同時我們標下鳥右下角的這個點,讓我們後面能夠更清楚 SVG 座標系統的變化。在一開始的時候,因為 viewport 等同於 viewBox 的緣故,所以 SVG 座標系統中這個點,和 viewport 座標系統中的 offset 座標點,都會是(200, 300):

當 viewBox 為 viewport 尺寸的一半時

接著,我們可以看到,當我把 viewBox 設為 viewport 的一半(viewBox = "0 0 400 300"),也就是讓鳥看起來變 2 倍大時,這時候 SVG 座標系統中的 1 單位,會變成 viewport 的 2 單位(這裡就是 2px)。

但要留意的是,雖然圖案被放大了兩倍,但是鳥右下角這點在藍色尺標的 SVG 座標系統中一樣是(200, 300),可是灰色尺標的 viewport 座標系統中的 offset 座標點會變成兩倍,也就是(400, 600)。

當 viewBox 為 viewport 尺寸的兩倍大時

同樣的道理,當我把 viewBox 設為 viewport 的 2 倍大(viewBox = "0 0 1600 800"),也就是讓鳥看起來變 2 倍大時,這時候 SVG 座標系統中的 1 單位,會變成 viewport 的 1/2 單位(這裡就是 0.5px)。

這時候你會看到,雖然藍色尺標的 SVG 座標系統中,右下角座標仍然是(200, 300),但是 viewport 座標系統中的 offset 座標點則變成了(100, 150)。

重點總結

在這篇文章中有幾個你應該留意的重點:

知道有 viewport 和 SVG 這兩種不同的座標系統

知道有 offset, client, SVGPoint 這三種不同的座標點

知道有 offset 和 client 屬於 viewport 座標系統;SVGPoint 屬於 SVG 座標系統

知道透過 viewBox 的設定可以達到縮放和移動的效果

參考資料

Understanding SVG Coordinate Systems and Transformations

[中譯]理解 SVG 座標系統和 Transformation @ Andyyou

SVG 研究之路 (23) - 理解 viewport 與 viewbox @ OXXO

首頁圖片來源 @ TeamTreehouse

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82156.html

相关文章

  • [技術分享] 理解 SVG 中的 Viewport ViewBox拖曳縮放功能實做

    摘要:註在這篇文章中我們只考慮和為等比例的情況。最後實做出來的功能會像這樣子實做拖曳與縮放瞭解中的和在的世界中,空間的概念可以分成和兩個部分。實際感受的效果在她所撰寫文章中提供了非常好的實做案例。這個座標系統是相對固定的。 理解 SVG 中的 Viewport 和 ViewBox - 實做縮放(zoom)和拖曳(drag)效果 本文章同步刊載於 PJCHENder 前端網頁資源站 不同於以往...

    AJie 评论0 收藏0
  • svg的坐标系统

    摘要:发现目前浏览器支持的挺强大的,但是本身有很多背景知识和元素属性以及库等,如何系统地掌握这一强大工具呢视窗和视野这两个词的翻译还是比较好的你站在屋子里通过窗户来看外面的世界。的坐标和的最左边的坐标对齐 最近做一个流程图绘制项目,所以研究了一下svg。发现svg目前浏览器支持的挺强大的,但是svg本身有很多背景知识和元素属性以及js库等,如何系统地掌握这一强大工具呢? viewPort(视...

    spademan 评论0 收藏0
  • SVG精髓》笔记(一)

    摘要:本文是基于精髓一书的简单总结,文中的均为该书提供,目的是方便大家使用时快速查阅。允许指定一个给定的一组图形伸展以适应特定的容器元素。该属性的模型为指定轴和位置,由一个对齐方式和一个对齐方式组合而成。 本文是基于《SVG精髓》一书的简单总结,文中的demo均为该书提供,目的是方便大家使用时快速查阅。 1. 坐标系统 视口(viewport):文档使用的画布区域,表示SVG可见区域的大...

    warkiz 评论0 收藏0
  • SVG

    摘要:目前只提供了一些基础功能。中与的区别开发者第一次接触手写那种,虽然很多情况都有设计师使用来完成这项工作,但还是不排除需要利用到的每个元素。轻量级,具备灵活的来自团队,全球非常出名的可视化团队。于是笔者尝试着把移植到中。 使用SVG + CSS实现动态霓虹灯文字效果 早上无意间进入一个网站,看到他们的LOGO效果略屌,如图: 刚开始以为是gif动画之类的,审查元素发现居然是用SVG + ...

    104828720 评论0 收藏0
  • SVG图标跑到哪里了?

    摘要:先上图,这是我们想要实现的图标效果为了方便看出图标的轮廓,我们将背景上色。也就是说划定了应该显示的图像区域的起点位置以左上角为图像起点和大小,所以它包含四个数字类型参数,分别代表盒子左上角的坐标和它的宽度和高度。 先上图,这是我们想要实现的图标效果: showImg(https://segmentfault.com/img/bVblPou);(为了方便看出svg图标的轮廓,我们将背景上...

    huashiou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<