Google Maps API - 點擊區域,出現資訊視窗
透過 Google Maps API 我們已經可以順利載入 GeoJSON,不過說穿了格式其實就是 json,所以也可以使用 jQuery 來載入,這篇除了會在地圖上顯示台灣的縣市區域,更會嘗試用滑鼠點擊區域,並開啟資訊視窗 infowindow 顯示對應資訊。
初始化地圖並載入 GeoJSON
網頁載入後先宣告地圖,然後在地圖裡放入資訊視窗,接著使用 jQuery 的getJSON
來載入 GeoJSON 檔案,不過因為並非使用 Google 地圖的 data 載入,在資料的處理就得自己動手來做,所以這裡就先用一個變數 features 來裝載特徵值的陣列。
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: {
lat: 23.858987,
lng: 120.917631
}
});
// 在地圖上放入資訊視窗
var infowindow = new google.maps.InfoWindow();
$.getJSON('taiwanCities.geojson.json', function(e) {
var features = e.features;
// 載入資料後要做的事情.....
});
}
載入後要做的事:繪製行政區域圖
一開始先新增三個陣列,taiwan 陣列會裝載待會的行政區域多邊形的特徵值,name 會裝載各個行政區域的名稱,polygonPath 則是代表在地圖上繪製出的多邊形陣列。
var taiwan = []; // 行政區域多邊形特徵值的陣列
var name = []; // 行政區域名稱的陣列
var polygonPath = []; // 繪製後的多邊形陣列
再來就是透過forEach
依序把 GeoJSON 中的特徵值一一取出,如果仔細觀察資料結構,可以看到資料中有以下 三種 形狀:
- 第一種:單獨一塊:一組陣列,例如南投縣、高雄市、台南市...等。
- 第二種:兩塊以上:一組陣列中有兩組以上的子陣列,例如台東縣、金門縣...等。
- 第三種:三塊以上:一組陣列中有另外一個子陣列,同時子陣列中又包含一個以上的孫陣列,例如嘉義縣包著嘉義市 ( 嘉義市屬於第一種 )、新北市包著台北市...等。
面對這三種資料,就得分別用邏輯判斷將其獨立出來,特別是第三種,回想在 Google Maps (11) - 形狀 ( 多邊形 Polygon ) 這篇文章有介紹,多邊形如果是有 A 包著 B 的狀況,會由其座標點繪製的順時針或逆時針方向,取決其交集或聯集的呈現結果,幸好 GeoJSON 原始資料已經有處理,只要正常載入就不會有問題 ( 像是嘉義縣,如果只載入外框,那麼最後產生的形狀,就會和嘉義市互相重疊 ),完成後就可以透過new google.maps.Polygon
依序在地圖上畫出行政區域形狀。
features.forEach(function(i, index) {
name.push(i.properties.name); // 將各個行政區的名字記錄到 name 陣列中
if (i.geometry.coordinates.length == 1) {
// 如果行政區域只有一塊,例如南投縣
var arr = [];
i.geometry.coordinates[0].forEach(function(j) {
arr.push({
lat: j[1],
lng: j[0]
});
});
taiwan.push(arr);
} else {
// 如果行政區域不只一塊,例如台東縣包含綠島和蘭嶼,就是個多邊形集合
var arr = [];
for (var k = 0; k < i.geometry.coordinates.length; k++) {
var arrContent = [];
if (i.geometry.coordinates[k].length == 1) {
//如果行政區域沒有包含其他的行政區域,例如台東縣
i.geometry.coordinates[k][0].forEach(function(j) {
arrContent.push({
lat: j[1],
lng: j[0]
});
});
} else {
//如果行政區域包含了其他的行政區域,例如嘉義縣包覆著嘉義市
i.geometry.coordinates[k].forEach(function(j) {
arrContent.push({
lat: j[1],
lng: j[0]
});
});
}
arr.push(arrContent);
}
taiwan.push(arr);
}
// 依序在地圖上畫出對應的多邊形
polygonPath[index] = new google.maps.Polygon({
paths: arr,
strokeColor: '#000',
strokeOpacity: .7,
strokeWeight: 1,
strokePosition: google.maps.StrokePosition.CENTER,
fillColor: '#f00',
fillOpacity: 0.35,
map: map
});
//畫完行政區域後要做的事情.....
});
畫完行政區域要做的事:加入滑鼠事件、打開資訊視窗
畫完行政區後要做的事情就簡單了,就是為每個行政區的多邊形,加入滑鼠 click 事件,在點擊行政區時會抓取滑鼠的經緯度座標,接著把這個座標丟給資訊視窗,讓資訊視窗在這個座標開啟,同時顯示對應的行政區域名稱,此外也可以使用 mouseover 和 mouseout 事件,在滑鼠移到行政區上方會改變顏色,移出行政區又會恢復顏色。
// 為每個多邊形加上滑鼠點擊事件
polygonPath[index].addListener('click', function(e) {
// 點擊時獲取滑鼠的經緯度座標
var coordinate = {lat: e.latLng.lat(), lng: e.latLng.lng()};
// 將資訊視窗的位置,設定為滑鼠的座標
infowindow.setPosition(coordinate);
// 設定資訊視窗的內容為行政區名稱
infowindow.setContent('<h2>'+name[index]+'</h2>');
// 將資訊視窗打開在地圖上
infowindow.open(map);
});
// 設定滑鼠移到多邊形上,多邊形會變成半透明黑色
polygonPath[index].addListener('mouseover', function(e) {
this.setOptions({
fillColor: '#000'
})
});
// 設定滑鼠移出多邊形,多邊形會恢復半透明紅色
polygonPath[index].addListener('mouseout', function(e) {
this.setOptions({
fillColor: '#f00'
})
});
小結
如果已經熟悉多邊形 Polygon 和資訊視窗 infowindow 的用法,其實只要了解資料格式,就能夠很簡單的在地圖上做出想要的效果,之後應該還會再找篇幅,應用更多不同的資料在地圖上呈現。。