Google Maps API - 顯示 GeoJSON 資料

透過 Google Maps API 在地圖上繪製圖形不困難,但「取得地圖上的資料」卻令人頭痛,幸好隨著科技的進步,我們可以透過 GeoJSON 這種專門處理地理資訊結構的格式,更方便的在地圖上顯示各種資訊,這篇就來簡單介紹一下 GeoJSON,並在 Google 地圖上顯示對應的樣貌。

GeoJSON 簡介

GeoJSON 是一種對地理資訊結構進行編碼的格式,基於 JavaScript 物件標記的地理空間資訊資料交換格式 ( 所以才會是 Geo + json ),GeoJSON 支援像是點、線、多邊形、多點、多線、多個多邊形的幾何形狀,當中也包含了特徵或特徵的集合資訊。

舉例來說,一個 GeoJSON 最外層包含一個 type 為 FeatureCollection 的屬性,接著 features 的屬性包含了許多 type 為 Feature 的物件,這些 Feature 物件裡包含 properties 的屬性,可以設定區域的顏色、邊框...等樣式,也包含了 geometry 的屬性,定義地圖上形狀的面貌,以下面這段 GeoJSON 來說,就是在台北 101 旁的松壽路上,畫「一段粗細 10px,透明度 0.5 的紅色直線」。

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stroke": "#ff0000",
        "stroke-width": 10,
        "stroke-opacity": 0.5
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            121.56351685523987,
            25.03585799721269
          ],
          [
            121.56548023223877,
            25.0358093932627
          ]
        ]
      }
    }
  ]
}

上面的例子中,type 設定為 LineString 呈現的是直線,如果要呈現多邊形,就要將 type 設為 Polygon,下面的 GeoJSON 呈現的是台北 101 被一個「黑色實線、紅色半透明填滿的正方形」圍住。

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stroke": "#000000",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#ff2600",
        "fill-opacity": 0.5
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              121.56345248222352,
              25.03295144714567
            ],
            [
              121.5654158592224,
              25.03295144714567
            ],
            [
              121.5654158592224,
              25.03476926411677
            ],
            [
              121.56345248222352,
              25.03476926411677
            ],
            [
              121.56345248222352,
              25.03295144714567
            ]
          ]
        ]
      }
    }
  ]
}

產生 GeoJSON

雖然說已經知道了 GeoJSON 的格式,但要產生 GeoJSON 最麻煩的仍然是那些小數點好多位數的「座標」,這時候就要透過 geojson.io 這個線上服務,來幫我們產生標準又漂亮的 GeoJSON。

參考連結:http://geojson.io/

打開網頁後,映入眼簾的是左右兩個視窗,左邊的視窗是地圖,右上角有繪圖的工具,右邊的視窗會根據所繪製的圖案,自動產生 GroJSON。

用「多邊形」工具把台北 101 旁邊的台北世界貿易中心框起來,就會看到對應的 GeoJSON 自動產生出來。

用滑鼠點擊畫好的多邊形,就可以修改多邊形的屬性,修改後在 GeoJSON 裡的 properties 也會自動產生,下圖就是把繪製的多邊形,改成黑色外框紅色填滿的屬性。

透過 geojson.io 這個方便好用的網站,要產生 GeoJSON 已經不再那麼困難,接著就來實作如何用 Google 地圖顯示 GeoJSON 資料。

Google 地圖顯示 GeoJSON 資料

匯入 GeoJSON 資料其實很簡單,每個 Google 地圖都有一個 map.data 物件,做為任意地理空間資料(包括 GeoJSON)的資料圖層,只要呼叫 data 物件的loadGeoJSON()方法就可以,用法如下:

map.data.loadGeoJson('GeoJSON.json');

舉例來說,下面這段程式碼,就會在地圖上載入上面我們所畫好的台北世貿中心。

範例:Google 地圖顯示 GeoJSON 資料

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 17,
    center: {lat: 25.034010, lng:121.562428}
  });

  map.data.loadGeoJson('geojson.demo.json');
}

不過很神奇的,載入之後我們原本設定的樣式反而不見了,這時候就得使用Data.setStyle()方法來指定資料外觀,以剛剛的例子來說,只要改寫成下面這樣,就能讓原本的形狀多了些色彩。

範例:Google 地圖顯示 GeoJSON 資料 - 改變樣式 1

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 17,
    center: {lat: 25.034010, lng:121.562428}
  });

  map.data.loadGeoJson('geojson.demo.json');

  map.data.setStyle({
    strokeWeight: 20,
    strokeOpacity: .5,
    strokeColor: '#f00',
    fillColor: '#0c0',
    fillOpacity: .35
  });
}

如果還是想使用我們自定義的 GeoJSON 樣式該怎麼做呢?這時就得用到map.data.setStyle(function(feature)){}來取的每筆資料的屬性,下面的例子將會把我們自定義的 properties 的樣式取出,套用到 Google 地圖上。

範例:Google 地圖顯示 GeoJSON 資料 - 改變樣式 2

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 17,
    center: {lat: 25.034010, lng:121.562428}
  });

  map.data.loadGeoJson('geojson.demo.json');

  map.data.setStyle(function(feature){
    return {
      strokeWeight: feature.getProperty('stroke-width'),
      strokeOpacity: feature.getProperty('stroke-opacity'),
      strokeColor: feature.getProperty('stroke'),
      fillColor: feature.getProperty('fill'),
      fillOpacity: feature.getProperty('fill-opacity')
    }
  });
}

同樣道理,如果我們手動在 properties 內定義一個名為 name 的屬性,就可以在「多個形狀」的資料下,指定每筆資料產生的形狀樣式,以下面的例子來說,透過 name 的屬性,就能指定紅色和綠色的區塊按照 GeoJSON 的配置顯示色彩,而另外一個區塊就用預設的 Google 形狀來顯示。

範例:Google 地圖顯示 GeoJSON 資料 - 多個形狀

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 17,
    center: {lat: 25.034010, lng:121.562428}
  });

  map.data.loadGeoJson('geojson.demo2.json');

  map.data.setStyle(function(feature){
    if(feature.getProperty('name')=='red' || feature.getProperty('name')=='green'){
      return {
        strokeWeight: feature.getProperty('stroke-width'),
        strokeOpacity: feature.getProperty('stroke-opacity'),
        strokeColor: feature.getProperty('stroke'),
        fillColor: feature.getProperty('fill'),
        fillOpacity: feature.getProperty('fill-opacity')
      }
    }
  });
}

小結

基本上透過 Google 地圖來顯示 GeoJSON 資料沒有太大的難度,比較難的是讀取資料後要怎麼用視覺化呈現,讓使用者可以一目瞭然,接下來會再嘗試讀取資料後再做一些變化,敬請期待囉~ ^_^

參考

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