實作口罩地圖後記與心得,開發口罩地圖並沒有想像中的簡單
武漢肺炎日漸嚴重,台灣也出現了搶口罩的風潮(不是已經很久了嗎),而自從政府開始實施口罩配給後,哪個藥局還有庫存成了眾人最關心的議題。所以,為了測試自己的程度,加入了製作口罩地圖的行列中!
在此也要特別感謝 kiang 江明宗先生將藥局資料以及即時的口罩庫存做成 geoJSON 檔案提供,省去了不少處理資料的麻煩。
資料修正
不過政府對某些藥局的經緯度資料上有誤差,所以我自己也做了不少的修正。以下提供我重新在 Google Map 上查詢到的經緯度修正,若你在使用地圖時有遇到藥局座標錯誤,歡迎在下方留言板告訴我喔!
醫事機構代碼 | 醫事機構名稱 | 經度 , 緯度 |
---|---|---|
5931033130 | 永利藥局 | 121.517612 , 25.006090 |
5931033176 | 緣來藥師藥局 | 121.518552 , 25.007578 |
5931101455 | 日揚藥局 | 121.461145 , 25.136232 |
5931100092 | 上全藥局 | 121.461358 , 25.136273 |
這次採用 Leaflet 的 JavaScript 程式庫來顯示地圖,也因為是第一次使用 Leaflet,開發時 也遇到許多阻礙呢。使用前因為沒有把 Leaflet 的文件完全看完,我也不知道 Leaflet 有提供 geoJSON function 可用,所以我傻傻的寫了個迴圈來逐一加點,而且事後才發現原來有 geoJSON 可以用。
Marker 顏色辨別
不過現在想想也沒關係,因為是自己用迴圈來拆解資料並逐一加入 marker,所以對於每筆資料的條件判斷靈活性更高,可以達成逐一判別該 marker 應該用什麼樣子的 icon 來顯示。這也是為什麼在我的口罩地圖中可以用顏色來分辨該藥局的口罩存量比例有多少。
在選擇顏色的時候我採用好想工作室的顏色分類,我想他們的顏色分類是最能分辨庫存數量的。
Marker Cluster
原本以為這樣做就 OK 了,結果沒想到 Leaflet 的 marker 是利用一個 DOM element 進行繪製的,意味著全台可供購買的藥局一共有 6583 間,所以就有快六千個 DOM element,而這六千個瀏覽器都要進行繪製,對於瀏覽器的負荷太高了,連電腦的瀏覽器都有效能上的問題更何況手機的瀏覽器。
為了解決這個問題我採用 Leaflet 一個 plugin 叫做 marker cluster。marker cluster 可以有效的將附近的 marker 組合成一個 marker,其中間的數字是用來表示該群組有幾個 marker,而原先有將這個數字顯示出來,不過後來考慮到會跟口罩的數量起衝突(讓使用者以為有多少口罩在那裡)所以將他取消了。
Marker Cluster 開發時為了讓你能快速分辨該 Cluster 的口罩庫存狀況,採用了收納 Marker 時順便抓取庫存狀態最高的作為該 Cluster 的顏色顯示。最後利用不透明度來將庫存高的 Cluster 強調出來(實際上是將存量低的不透明度設低)。
每 30 秒自動更新
每 30 秒自動更新也是頭痛的部分之一,因為每個 marker 的 popup 內容並不是以 DOM element 方式儲存的,而是儲存在變數內,當使用者點擊 marker 時才會將內容加入頁面中。所以自動更新時也花了不少的時間在了解 Leaflet Marker Cluster 儲存資料的方式,慶幸的是,取用 popup 內容時是以資料型態為 DOM 的格式儲存,所以可以用 JavaScript 原生的方式存取該資料。
距離
不知道有沒有人注意到每個藥局名稱旁都有顯示與目前位置的距離。開發時,尋找距離公式時簡單,可是當將其寫成程式碼時又有遇到單位上的問題,所幸最後一一排除做出了理想的結果。
一鍵切換成人、兒童口罩
因為有了自動更新取得儲存資料的經驗後,做切換 marker icon 的時候就順多了。直接取得 popup 內容裡成人口罩、兒童口罩的數量並且依照比例算出落在哪個區間,再用 Leaflet 的 setIcon
轉換 icon 就達成目的了。
不過,偶然間看到資料更新時藥局資料內的背景、marker 有正確轉換,而 marker cluster 卻沒有跟著轉換。此時才意識到忘記於更新資料的程式碼裡加入 markers.refreshClusters()
,與此同時才意識到測試沒做完全。
更多功能
若你覺得口罩地圖還可以加入甚麼功能,歡迎下方留言板告訴我喔!
- 搜尋功能我目前有在考慮該不該做。