Google Mapをクリックした地点の人口データの属性を持つ町丁目ポリゴンを取得し、表示する

## 概要説明
今回は、Google Mapをクリックしたときにサーバーと連携し、クリックした地点の人口データの属性を持つ町丁目ポリゴンを取得して表示させてみました。また、表示させた町丁目ポリゴンの削除についてもご紹介します。
この記事は[Maps JavaScript APIを使ってGoogle Mapに町丁目ポリゴンを表示してみる](https://qiita.com/yan_x/items/c069c8fb7c5d2648fe50)を拡張した内容になります。

## 使用したもの
- Google Map
- Maps JavaScript API

https://developers.google.com/maps/documentation/javascript?hl=ja
- JavaScript
- PHP
- 町丁目ポリゴン、令和2年国勢調査（2020年国勢調査）/人口総数
今回使用した町丁目ポリゴンおよび人口総数データは、TerraMap API からレスポンスされたものです。

https://www.mapmarketing.co.jp/terramap-api?grid=qiita&utm_source=qiita.com&utm_medium=referral&utm_campaign=qiita_gmap-click-point-polygon_23f7aceaac367cb2f874_01

## 完成イメージ
全体の完成イメージは、以下の動画のようになります。今回は TerraMap API から町丁目ポリゴンや人口データを取得するために、サーバーへのリクエストも必要になります。
**Google Mapをクリックして座標情報を取得　→　サーバーへのリクエスト　
　→　町丁目ポリゴンと人口データの取得・表示　→　町丁目ポリゴンの削除**
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/03f2374c-fa5c-9a1d-e326-351431dae03d.gif)

## Google Mapをクリックした地点の座標情報を取得する
最初に以下のようにHTMLファイルとJavaScriptファイルを作成し、Google Mapをクリックしたときにクリック地点の座標情報を取得するようにします。
```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <title>
      Google Mapをクリックした地点の人口データの属性を持つ町丁目ポリゴンを表示する
    </title>

    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <!--The div element for the map -->
    <div id="map" style="width: 100%; height: 600px"></div>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_MAP_KEY&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>
```
```javascript:index.js
function initMap() {
  // 中心位置
  const centerLocation = { lat: 35.6727, lng: 139.662 };

  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 15,
    center: centerLocation,
  });

  map.addListener("click", (event) => {
    const { latLng } = event;
    const coordinate = [latLng.lng(), latLng.lat()];
    console.log(coordinate);
  });
}
window.initMap = initMap;
```
> 参考情報
> [クリックイベントから緯度/経度を取得する](https://developers.google.com/maps/documentation/javascript/examples/event-click-latlng)

## サーバーへリクエストして町丁目ポリゴンと人口データを取得し表示する
次に、クリックイベントで取得したGoogle Mapの座標情報をサーバーへPOST送信させるようにします。レスポンスされた町丁目ポリゴンのGeoJSONは、指定されたスタイルで地図に表示させ、人口データはMaps JavaScript APIのInfoWindowクラスを利用し表示させるようにします。
先ほど作成したJavaScriptファイルを以下のように変更します。
```javascript:index.js
function initMap() {
  // 中心位置
  const centerLocation = { lat: 35.6727, lng: 139.662 };
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 15,
    center: centerLocation,
  });
  const infowindow = new google.maps.InfoWindow();

  map.addListener("click", (event) => {
    const { latLng } = event;
    const coordinate = [latLng.lng(), latLng.lat()];
    const requestBody = {
      // 渡したいパラメータをJSON形式で書く
      coordinate,
    };

    // サーバーサイドプログラムからTerraMap APIへのリクエスト例はページ下部に説明があります
    fetch(`https://YOUR_SERVER_DOMAIN`, {
      method: "POST",
      body: JSON.stringify(requestBody),
    })
      .then((response) => response.json())
      .then((data) => {
        map.data.addGeoJson(data);
        const html =
          `住所：${data.features[0].properties.points}` +
          "<br>" +
          `人口：${data.features[0].properties.data[0].value}`;

        infowindow.setContent(html);
        infowindow.setPosition(latLng);
        infowindow.open(map);
      })
      .catch((error) => {
        console.log(error);
      });
  });

  const polygonStyleOptions = {
    strokeColor: "#810FCB",
    strokeOpacity: 1.0,
    strokeWeight: 2.0,
    fillColor: "#810FCB",
    fillOpacity: 0.5,
  };

  map.data.setStyle((feature) => {
    if (feature.getGeometry().getType() === "MultiPolygon") {
      return polygonStyleOptions;
    }
    return null;
  });
}
window.initMap = initMap;
```
> 参考情報
> [情報ウィンドウ](https://developers.google.com/maps/documentation/javascript/infowindows)
> [Googleマップでマーカーに情報ウィンドウを表示させる](https://gimmicklog.com/javascript/384/)

## サーバーサイド（PHP）の作成
PHPでの実装例を挙げておきます。
サーバーサイドでは、フロントサイドで取得した座標情報から、住所と令和2年国勢調査（2020年国勢調査）の人口総数の属性を持つ町丁目ポリゴンを取得してレスポンスを返すようにします。
```PHP:index.php
<?php
header('Content-Type: application/json');

// URLとapiキーはダミーです
$url = 'https://tmapi.example.jp/api/area';
$apiKey = 'YOUR_TERRAMAP_API_KEY';

// リクエストパラメータからのINPUT
$json = file_get_contents("php://input");
$requestParams = json_decode($json, true);

// パラメータをJSON形式でセット
$params = json_encode([
    "layer_id" => "00104", // レイヤーは町丁目を指定
    "area_type" => "coordinate", // エリアタイプは座標を指定
    "coordinates"=> array($requestParams["coordinate"]),
    "output" => "polygon,point,data", // ポリゴン、住所、データを出力する
    "stats" => [
        array(
            "stat_id" => "001012000",       // 令和2年国勢調査（2020年国勢調査）を指定
            "stat_item_id" => [15776]       // 人口総数を指定
        )
    ],
]);

$ch = curl_init();
// Content-TypeとAPIキーをセット
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'X-API-KEY: ' . $apiKey]);
// POSTメソッドを指定
curl_setopt($ch, CURLOPT_POST, true);
// パラメータをセット
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
// URLをセット
curl_setopt($ch, CURLOPT_URL, $url);

// レスポンスをブラウザに渡す
curl_exec($ch);

curl_close($ch);
```

## 町丁目ポリゴンの削除
最後にinitMap() 内に以下のコードを追加し、クリック地点の町丁目ポリゴンを削除できるようにします。同時に人口データも非表示にしておきます。
```JavaScript:index.js
map.data.addListener("click", (event) => {
    map.data.remove(event.feature);
    infowindow.close();
});
```
円やある程度の範囲を指定してざっくりとしたエリアを決めた後に不要なエリアを削除する使い方もあります。
チラシを配布するエリアの選定や店舗の商圏を設定する際にも活用できます。 
円やある程度の範囲を指定する方法は以下をご参照ください。
[地図(Google Map)の任意地点に円を描き、人口データの属性を持つ町丁目ポリゴンを取得し、表示する](https://qiita.com/yan_x/items/0cf06675739ddcfa3576)
[Google Mapに多角形を描き、人口データの属性を持つ町丁目ポリゴンを取得し、表示する](https://qiita.com/y-mto/items/5c9e1a18b9442d434375)

> 参考情報
> [Google マップ データ レイヤーからデータを削除するには？](https://stackoverflow.com/questions/23071775/how-to-remove-data-from-a-google-maps-data-layer)

## おわりに
今回はGoogle Mapをクリックした地点の人口データの属性を持つ町丁目ポリゴンを取得し、表示する方法と表示した町丁目ポリゴンを削除する方法をご紹介しました。
TerraMap APIを利用することによって町丁目ポリゴンと人口データを簡単に表示することができます。
TerraMap APIは人口総数以外にも様々な統計データを取得することができ、地図を使った統計データの見える化やエリアマーケティングに特化した分析が実現できます。

https://www.mapmarketing.co.jp/terramap-api?grid=qiita&utm_source=qiita.com&utm_medium=referral&utm_campaign=qiita_gmap-click-point-polygon_23f7aceaac367cb2f874_02