Google Map　GeoJSONファイルを読み込み、人口での色分けを行ってみる

## はじめに
今回は、Google Map上にGeoJSON形式の町丁目ポリゴンを表示し、人口総数によって色分けを行い、色分けの凡例も作成したいと思います。

### 前提条件
Google Mapを表示するには、Google Maps Platform用のAPIキーが必要となります。この記事では「[Google Cloudプロジェクトをセットアップする](https://developers.google.com/maps/documentation/javascript/cloud-setup?hl=ja)」や「[APIキーを使用する](https://developers.google.com/maps/documentation/javascript/get-api-key?hl=ja)」等の手順は割愛させていただきます。

## 町丁目ポリゴン（GeoJSON）
人口総数を属性に持つ町丁目ポリゴンについては、[TerraMap API](https://www.mapmarketing.co.jp/terramap-api?grid=qiita&utm_source=qiita.com&utm_medium=referral&utm_campaign=qiita_googlemap_chomoku_population_colors_816f1bc92f8d7f835074_01)から取得できるものを利用しました。

一部省略しておりますが、以下のようなGeoJSONファイルになります。
`features[0].properties.data[0].value` が人口総数の値になっています。
```ChoPolygon.geojson
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "area": {
          "area": 0.23232962656232412
        },
        "data": [
          {
            "is_authorized": true,
            "stat_item_id": 15776,
            "stat_id": "001012000",
            "value": "1301"
          }
        ],
        "point_coordinates": [
          139.67882,
          35.662
        ],
        "geocode": "13110000104",
        "points": [
          [
            "東京都",
            "目黒区",
            "駒場４丁目"
          ]
        ]
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [
                139.674866628,
                35.664159828
              ],
              [
                139.675069068,
                35.664075835
              ],
              
              // .... 座標を省略しています
              
            ]
          ]
        ]
      }
    },

    // .... featureを省略しています
  ]
}
```
## 地図と単色ポリゴンの表示まで
### HTML
HTMLファイルは以下のようになりました。`"YOUR_GOOGLE_MAP_API_KEY"` の部分にはAPIキーの入力が必要になります。
```index.html
<!DOCTYPE html>
<html>
  <head>
    <title>
      Google Map上に町丁目ポリゴンを表示し、人口総数での色分けを行ってみる
    </title>
    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map" style="width: 100%; height: 95vh"></div>

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "YOUR_GOOGLE_MAP_API_KEY", v: "weekly"});</script>
  </body>
</html>
```

### JavaScript
JavaScriptのコードは以下のようになります。GeoJSONファイルを読み込み、ポリゴンを単色で表示させています。
```index.js
let map;

async function initMap() {
  const { Map } = await google.maps.importLibrary("maps");
  // 中心位置
  const centerLocation = { lat: 35.6727, lng: 139.662 };

  map = new Map(document.getElementById("map"), {
    center: centerLocation,
    zoom: 13,
  });

  // GeoJsonをロード
  map.data.loadGeoJson("ChoPolygon.geojson");

  // ポリゴンのスタイル設定
  const polygonStyleOptions = {
    strokeColor: "#810FCB",
    strokeOpacity: 1.0,
    strokeWeight: 0.5,
    fillColor: "#810FCB",
    fillOpacity: 0.5,
  };

  map.data.setStyle((feature) => {
    if (feature.getGeometry().getType() === "MultiPolygon") {
      return polygonStyleOptions;
    }
    return null;
  });
}

initMap();
```
### 表示結果
![ChomokuPolygonOnGoogleMap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893989/146cb332-6f3f-6f0e-a3ae-62f851aa071c.png)

参考情報
[Simple Map | Maps JavaScript API | Google for Developers](https://developers.google.com/maps/documentation/javascript/examples/map-simple)
[データレイヤ | Maps JavaScript API | Google for Developers](https://developers.google.com/maps/documentation/javascript/datalayer?hl=ja)

## 人口総数での色分け
続いて、人口総数の値によって色分けを行いたいと思います。
index.jsにおいて、以下の２つの関数を `let map;` の後に宣言します。
```js
// 人口総数による配色
function getColor(d) {
  return d > 7000
    ? "#8b0000"
    : d > 6000
    ? "#d7352b"
    : d > 5000
    ? "#ffa746"
    : d > 4000
    ? "#ffd976"
    : d > 3000
    ? "#c9d0bb"
    : d > 2000
    ? "#92c7ff"
    : d > 1000
    ? "#5b97ee"
    : "#0855c4";
}

// フィーチャの人口総数に応じたスタイル設定を取得
function getPolygonStyleOptions(feature) {
  return {
    strokeColor: "black",
    strokeOpacity: 1.0,
    strokeWeight: 0.5,
    fillColor: getColor(feature.getProperty("data")[0].value),
    fillOpacity: 0.5,
  };
}
```
`map.data.setStyle`で使用するのは、関数の`getPolygonStyleOptions`に切り替えます。
```js
  map.data.setStyle((feature) => {
    if (feature.getGeometry().getType() === "MultiPolygon") {
      return getPolygonStyleOptions(feature);   //関数を利用
    }
    return null;
  });
```
### 表示結果
![ChomokuPolygonOnGoogleMap2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893989/4c0a45fd-9133-f250-932d-d5791afa2a2b.png)

## カスタム凡例の表示
最後は色分けに対してのカスタム凡例を加えて、完成になります。
[カスタム凡例のチュートリアル](https://developers.google.com/maps/documentation/javascript/adding-a-legend?hl=ja) を参考にして作成しました。
### HTML
index.htmlにカスタム凡例用の `<div id="legend"></div>` を追加します。
```html
    <div id="map" style="width: 100%; height: 95vh"></div>
    <div id="legend"></div>
```
### JavaScript
index.js の `map.data.setStyle` 処理の後に、以下のコードを加えます。
チュートリアルとは異なり、`<span>`タグでアレンジしてみました。

```js
  const legend = document.getElementById("legend");
  const grades = [0, 1000, 2000, 3000, 4000, 5000, 6000, 7000];

  for (let i = 0; i < grades.length; i += 1) {
    const from = grades[i];
    const to = grades[i + 1];

    const div = document.createElement("div");
    div.className = "info";
    div.innerHTML = `<span style="background:${getColor(from + 1)}"></span> ${from}${
      to ? `&ndash;${to}` : "+"
    }`;
    legend.appendChild(div);
  }

  map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(legend);
```
### CSS
以下のCSSファイルも加えます。
```style.css
#legend {
  font: 12px Arial, Helvetica, sans-serif;
  background: rgba(255, 255, 255, 0.8);
  padding: 10px;
  margin: 10px;
  box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
  border-radius: 5px;
}

#legend span {
  width: 15px;
  height: 15px;
  float: left;
  margin-right: 8px;
  opacity: 0.7;
}

#legend .info {
  width: 90px;
  height: 15px;
}
```
### 表示結果
全体が上手くいくと、以下のような表示結果となります。
![ChomokuPolygonOnGoogleMap3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2893989/4f1125d0-1d9f-28e2-7506-6e927b69d299.png)

記事は以上になります。ありがとうございました。