從範例學習 mini map 之 zoom, brush 功能
📋 目錄
範例介紹
在撰寫 動手實作 D3.js 練習-運動場 這篇,發現一個很好的 brush & zoom 範例!( 由 Seemant Kulleen 撰寫 ✒️ )
此篇文章將基於原著的程式碼,細節部分加以說明,並進行部分客製化。
目標:製作阿爾罕布拉宮 🏰 main map & mini map,並提供 brush & zoom 功能。
若尚未具備基礎 D3.js 概念,建議先閱讀這幾篇:
🚪 D3.js 資料視覺化工具(上)
🚪 D3.js 資料視覺化工具(中)
🚪 D3.js 資料視覺化工具(下)
準備好就開始吧 🚀
[實作] 繪製 main map & mini map
先準備好 index.html,程式碼如下:
頁面上有兩個獨立的 SVG 元素: main
mini
其中主要的 SVG 會嵌套在 aperture 的 SVG 中,是為了提供放大鏡功能。
檔案佈局為:
(小圖) div.vis -> div#mini -> svg
(大圖) div.vis -> div#main -> svg.aperture -> svg#largemap
上方的 viewBox(min-x, min-y, width, height)
,搭配 preserveAspectRatio = "xMinYMin meet"
,SVG 內部的元素就會自動填滿容器的寬。
有關 viewBox 以及 preserveAspectRatio 可以參考這篇 📃
也可以參考這支影片說明 🎥
在開始實作 main
mini
功能之前,先加入要放大檢視的圖片。
至 Unsplash 網站下載 圖片素材,將圖片放入資料夾中,並將其重新命名為view.jpg
本實作使用下方阿爾罕布拉宮這張
index.js 檔案加入下方程式碼:
接著,index.html 檔案中的 style 區塊加入下方程式碼:
使用 Flexbox 處理排版,並將 main map 設定為 mini map 的四倍大 🔍
若不清楚 Flexbox 使用方式,可以參考這支教學影片 (Learn Flexbox in 15 Minutes)
目前畫面如上所示, 👈 左方為 mini map ,右方為 main map 👉
[實作] 新增 brush & zoom 功能
有了 mini map 與 main map,要來新增 brush & zoom 功能。
step 1 取參數,並將對應方法加到 SVG 上
index.js 加上程式碼如下方:
首先,將最初設定的 viewBox 存起來。
brush.extent() 函數用於將可刷範圍設置為指定的點數組[[ x0 , y0 ], [ x1 , y1 ]],其中 [ x0 , y0 ] 是左上角[ x1 , y1 ] 是右下角並返回畫筆。
.scaleExtent([]):縮放最大值與最小值,預設為(1, 無限大)
最後把功能加到對應的 SVG 上 🎯
step 2 加上 brushed function
index.js 加上程式碼如下方:
一開始若發現呼叫的是 zoom 動作,即忽略 brushed function
取 d3.event.selection
以抓移動 brush 的值
接著算出要 scale 的 縮放因子 k
在內部,元素的變換存為 element.__zoom
不使用 zoom 提供的回呼函式,而是直接手動取修改 __zoom
step 3 加上 zoomed function
若是在小圖上進行縮放,反映到大圖上做縮放動作
若發現觸發的是 brush 動作,即忽略 zoomed function
接著取 d3.event.transform
取回是一個 object ,其中包含 x
y
以及 k
(縮放因子)
縮放動作完成要更新原本的 viewBox 並反映到小圖上
完成了 🎉 🎉 🎉
小結
具備 D3.js 基礎後,藉由網路資源找尋不錯的範例,抽絲剝繭做學習,過程中更認識進階的 zoom & brush 功能。將原始的 SVG 圖檔置換成不同檔案型式(jpg),部分客製化為喜歡的作品。附上此練習的 GitHub 檔案連結 🔗 ,專案資料夾名稱:d3-minimap-Alhambra
。有任何指點或建議都可以在下方留言~🙏
🏰 Thanks for reading!