一、Google 處理掉很多事了
原本以為畫熱圖(Heat map)很難,後來看了 Google Maps API 的文件,Google 已經處理掉大部份的工作了,我們只要丟座標,加上每個座標的權重,剩下的事情 Google 都會幫你搞定。
如果會了系列第一篇的 放多個標記,跟第二篇的 畫圓形,其實 Heat Map 也就會了。
Heat Map 是把數據視覺化在地圖上的一種,這種數據視覺化的地圖,照文件上給的範例有二:
1 圓圈圖(Circle Map):用不同大小的圓圈當代表,像文件上示範的是地震狀況圖,每個圓圈大小就代表著不同的地震級數。Google Map Demo
2 熱圖(Heat Map):就是本篇要實作的,會配合地理因素跟權重大小,生成出很像是熱感應圖的東西。Google Map Demo
Circle Map 比較簡單,就是在放多個標記時,icon 用客製,都用成畫圓圈的 function 就行。
這篇來拿第二個 Heat Map 來實作,畫一個台灣 12 小時累積雨量的分佈圖。
二、取得氣象局雨量資料
在「接氣象局 API、跨網域 AJAX 資料」這篇中有寫怎麼拿氣象局 API 的授權碼,以及拿到 API 的 URL。
這邊寫另一個取得 URL 的方式。主要是最近氣象局一直在推他們的新版官網,搜尋「氣象局 api」,第一名的結果就是:氣象資料開放平台。
找觀測雨量的資料,就會找到這頁:自動雨量站-雨量觀測資料。
登入會員後,如果有取得授權碼,在「JSON」的連結,就可以當 AJAX 的 URL。不過加了想要限定回傳資料的參數,好像跟原有的 opendata API 不太一樣,至少只想回傳 12 小時內的就沒用。
附上 GET 回來後,每個主欄位的中文說明:
要注意的是,雖然文件中說雨量值是 -998.00 時,代表連著 6 小時內的值都是 0,但實作時遇到的情況是,除了會出現 -998.00,也會遇到 -999.00。為了避免權重上的影響,這 2 個值出現時都要換成 0。
以下是 AJAX 回來後的資料 Demo:
各觀測站的資料都在 cwbopendata.location 裡,總共有 798 個觀測站,再打開來會看到每個站的資料:
lat
是緯度、lon
是經度,合起來就是座標。
elemenetName
代表的意思,前面附上的 PDF 就有說明了。這邊用的是 12 小時累積雨量,所以是抓陣列裡的第 5 個。
三、資料整理成 Heat Map 要的
Heat Map 預設是只要一個資料就行,就是座標。
但只有座標,看不出影響的程度,再加上權重(Weight)會更清楚。
這邊拿雨量當作權重,整理的資料是這樣:
let rainData = { location: new google.maps.LatLng(經度, 緯度), weight: 雨量 };
用 forEach
把每個觀測站的雨量資料處理成上面的物件,再 push
進一個陣列裡,接著就可以拿這個資料陣列去畫Heat Map。
四、畫熱圖 Heat Map
畫 Heat Map 的 code 如下:
let heatmap = new google.maps.visualization.HeatmapLayer({ data: heatmapData, dissipating: false, radius: 20, // 半徑 gradient: [], // 顏色 map: map });
dissipating
dissipating 這個比較特別,是指地圖放大縮小時,熱點圖是否要跟著加強。false
就是會,true
就是不會。
之所以會說特別,是因為不知道是不是共有 798 個點,當設成 false
讓每個點跟著強加的結果,就會讓整個台灣像被 AT 力場包起來一樣,像這樣:
改成 true
以後才正常。
有可能是對這個參數的理解錯了,也有可能是其他原因,如果有知道的高手請不吝賜教。
gradient
這個也是很容易踩雷的參數。
他的值是一個陣列,原本以為是給一個色碼,程式就會自動用權重去加上深淺的分別,結果完全不是這麼一回事。
之所以用陣列,就是要填入很多不同的色碼,假設權重是 1–10,又希望這 10 個權重反應出的顏色都不一樣,就要照著 1–10 的順序填入不同的色碼。像這樣:
[ '#000', // 給權重0的色碼 '#111', // 給權重1的色碼 '#222', // 給權重2的色碼 '#333', // 給權重3的色碼 ... ]
色碼,可以寫 white、black 等顏色名字,也可以寫 Hex 的六碼,或是寫 rgba。
可以寫 rgba 很重要,因為實作發現,第一個值會給權重 0,就是熱圖上其他沒有值的狀況,如果第一個值寫了紅色,那整張表都會加上一層紅色。
因此陣列第一個值給權重 0 的色碼,建議是填 rgba(255, 255, 255, 0),讓透明度為 0,才不會整張地圖都染上顏色。
這邊因為是要顯示雨量分佈,就直接用 Material Design 的色表。
method 執行完後,雨量分佈的 Heat map 就完成了:
五、原始碼
本篇的原始碼整理如下,替換氣象局跟 Google Maps API 的 key 就行了。
lat是緯度, long是經度哦, 你寫反了~
不過你的分享很棒! 獲益良多, 謝謝哦~
已修正,感謝你~