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 事件,在點擊行政區時會抓取滑鼠的經緯度座標,接著把這個座標丟給資訊視窗,讓資訊視窗在這個座標開啟,同時顯示對應的行政區域名稱,此外也可以使用 mouseovermouseout 事件,在滑鼠移到行政區上方會改變顏色,移出行政區又會恢復顏色。

範例:點擊台灣行政區域,出現資訊視窗

// 為每個多邊形加上滑鼠點擊事件
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 的用法,其實只要了解資料格式,就能夠很簡單的在地圖上做出想要的效果,之後應該還會再找篇幅,應用更多不同的資料在地圖上呈現。。

參考

有興趣瞧瞧其他新文章嗎?