動手實作 D3.js 練習-運動場

Jacy Chu
6 min readJul 28, 2021

--

運用 D3.js 手把手繪製台灣地圖 & 標示資料

📋 目錄

  1. 實作練習介紹
  2. [實作] 繪製台灣地圖
  3. [實作] 標記運動場館資料
  4. 小結

實作練習介紹

🏆 2021年7月23日 — 8月8日適逢東京奧運
培訓好的運動員需要良好的場地!
目標:製作台灣地圖,並標上全國運動場館資料 🏊

此練習需具備基礎 D3.js 概念,若不清楚建議先看這篇:
🚪 D3.js 資料視覺化工具(上)
另外,也將運用 SVG 工具製圖,若不清楚建議先看這篇:
🚪 D3.js 資料視覺化工具(中)
匯入及處理資料集部分,若不清楚建議先看這篇:
🚪 D3.js 資料視覺化工具(下)

使用 D3.js 搭配台灣地圖資料,根據經緯度繪製到畫布上,再結合全國運動場館的資訊,標上運動場館的位置。提供 zoom 縮放功能,hover 在點上會出現客製 tooltip!

請先準備好一個 index.html 檔案,以及在資料夾同一層加入一個空的 index.js 檔案。 index.html 檔案完整程式碼如下:

準備好了,就開始實作吧 🚀

[實作] 繪製台灣地圖

準備台灣地圖資料,從政府資料開放平台取得台灣經緯度資料 🔍

下載 SHP 檔案,藉由地圖編輯器 Mapshaper 將檔案輸出 GeoJSON 檔案。檔名為:COUNTY_MOI_1090820.json (檔名請依真實情況調整),將檔案放入資料夾中。詳細步驟可以參考 ShawnL 撰寫的這篇文章 (感謝 ShawnL 🙌 )

開始繪製地圖,程式碼如下:

首先先選定 svg,綁定 g 以便於後續操作。d3.geoMercator() 表示用橫麥卡托的方式投影。d3 官方提供許多投影方式,可以參考這邊.center() 指定為台灣的座標,.scale() 設定放大的倍率。下方引入剛剛準備好的 json 檔案,將 data 印出來看一下:

data

看起來要的資料已經取到了!接著使用 topojson.feature() 是 topoJSON 去創造 GeoJSON object 的方法。查看一下取到的 geometries:

geometries
🔖 補充說明
1.GeoJSON:是一種對各種地理數據結構進行編碼的格式。GeoJSON支持下面幾何類型:點、線、面、多點、多線、多面和幾何集合。
2.TopoJSON:以 GeoJSON 為基礎,以拓樸學的科學基礎編碼而成的格式。原先描述地理訊息的邊緣,會以共同邊所表示,並且消除掉一些較為冗贅的地理資訊後而產生。
🔦 附上xcatliu(作者)撰寫的 GeoJSON 和TopoJSON 文章

接著把取到的資料繪製上去,程式碼如下:

其中加上county class,還有加上簡易版本的 tooltip,希望 hover 時可以出現相對應的縣市名稱。

在 index.html 加上 style 樣式,程式碼如下:

此時,開啟瀏覽器,畫面如下:

看起來很不錯呢!👏

[實作] 標記運動場館資料

準備台灣運動場館資料,先從全國運動場館資訊網取得場館資訊 🔍

下載 ODS 檔案,請自行轉為 CSV 檔案。檔名為:全國運動場館資訊.csv,將檔案放入資料夾中。(筆者撰寫時間取得最新資訊為 民國 110年 4月的資訊)

開始繪製地圖前,先講上方設定的 .county:hover style 以及縣市的tooltip 註解掉,因為標記場館不會用到。在原始 index.js 檔案加入以下程式碼:

此非完整 index.js 檔案

查看一下 data 資訊如下:

data

此時,全國運動場館資訊已經標記上去。由於數量不少,幾個縣市的點很密集,希望可以增加畫布放大的功能。在 index.js 檔案最上面加上 d3.zoom 功能。

此非完整 index.js 檔案

此時,畫布可以隨著使用者操作有放大縮小的功能!接下來希望在原點上標示出場館名稱。使用跟剛剛一樣的作法:

此非完整 index.js 檔案

畫面可以看到已經有標示出場館的名稱 🎈
如果想要客製化自己的 tooltip,像是制定樣式、放更多資訊等等。可以藉由下方作法:

新增 tooltip id,下方加上 mouse 控制,藉由 opacity 控制出現或消失。另外 index.html 檔案 style 部分加上 custom_tooltop 樣式設定。

此非完整 index.html 檔案

看起來非常完整!台灣地圖結合標示運動場館已完成 🎉

不過多 reload 幾次頁面,其實會發現有時候會先繪製地圖檔案,有時候會先繪製運動場檔案。面對這樣的情況,可以利用 async 及 await 實現非同步程式。修改後完整的程式碼如下:

修改之後,每一次 reload 都會先繪製地圖,再標示場館 🙆
🌟 大功告成了!

小結

具備 D3.js 基礎後,練習處理、介接不同型態的資料,搭配不同工具完成此地圖標記運動館實作。附上此練習的 GitHub 檔案連結 🔗 ,專案資料夾名稱:d3-practice-GYM。分享筆者很喜歡的一句名言:

有任何指點或建議都可以在下方留言~🙏

🍡 Thanks for reading!

--

--