【Google MAP】地図移動後の緯度経度の再取得方法

# はじめに

- 以前、Googleスプレッドシートにある場所リストを利用して、GoogleMAPにマーカー表示＋場所リスト表示をしました。

https://qiita.com/yoshi_yast/items/44ef9da9bc136e455950

- MAPの横にあるサイドバーの場所リストについて、**地図を移動した際に、移動後に表示される地図におけるリストに更新**したいと思いました。言い換えると、複数の場所情報がある場合、GoogleMapの表示範囲のみの地点にて、マーカー＆リストを表示する、ということになります。

# 用意したいサンプルデータ(Googleスプレッドシート)
- Googleスプレッドシートから場所リストを読み込みする方法は、上記リンクを参照。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/0de7a2d4-ef57-0e56-5be6-5b6e6e93ffa5.png)

# サンプルプログラム
- 初期に表示される場所は6カ所。ドラックや拡大などにより地図を移動させると、移動後に表示された地図の位置情報を元に、マーカーとサイドバーの場所リストを更新します。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/cfea9b3a-84d2-c8ec-2848-9e7c774698a5.png)
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/984e1a99-59ac-9bde-91c2-1cb368b11e67.png)

# コード(ポイント)
- 地図の移動が行われ、地図の表示領域が変更されたらイベントが発生するようにする。「idle」は、地図がアイドル状態になったタイミングで発火することを意味します。

```sample.html
<script>
  google.maps.event.addListener(map, 'idle', function(){
    //後続処理を記述
  });
</script>
```

- 移動後の地図の緯度経度を取得する。
```sample.html
<script>
  var bounds = map.getBounds();
  mapNE_lat = bounds.getNorthEast().lat();
  mapSW_lat = bounds.getSouthWest().lat();
  mapNE_lng = bounds.getNorthEast().lng();
  mapSW_lng = bounds.getSouthWest().lng();
</script>
```

# 全体のコード
- 地図の位置情報をもとに、リストを更新して、マーカー表示とサイドバーにある地点リストを更新する形となります。

<details><summary>全体のコード</summary>
<div>

```googlemap_sample.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>Google Maps My List</title>
    <meta charset="utf-8">
    <style>
       /* 省略 */
    </style>
  </head>

  <body>
    <div id="header">Google Maps - 表示されているマーカーのリストを更新する</div>
    <br>

    <table>
      <tr>
        <td><div id="target"></div></td>
        <td><div id="sidebar"></div></td>
      </tr>
    </table>

    <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=GOOGLEAPIキーを設定する&callback=initMap" async defer></script>

    <script>
      var markerData = [];

      // 地図初期表示
      function initMap() {

        var target = document.getElementById('target');

        // 地図の中心設定
        var centerp = {lat: 34.67545304515069, lng: 135.54830200000004};

        // Google Mapの表示
        map = new google.maps.Map(target, {
          center: centerp,
          zoom: 8,
        });

        // Function:地図データの取得
        getMapdata();

        // 地図が移動された場合、マーカーとリストをセットし直す
        google.maps.event.addListener(map, 'idle', function(){
          setSideList();
        });

      }

      // Function:地図データの取得
      function getMapdata(){

        //APIにてデータを取得して、位置とマーカーをセットするfunctionを呼び出す
        var request = new XMLHttpRequest();
        var bookid = 'BOOKIDを設定';
        var sheetname = 'シート名を設定';
        var googleapi = 'APIキーを設定';
        var url = 'https://sheets.googleapis.com/v4/spreadsheets/' + bookid + '/values/' + sheetname + '?key=' + googleapi;

        request.open('GET', url, true);
        request.responseType = 'json';

        request.onload = function () {
          var data = this.response;       // 取得できた値を格納
          markerData = parseData(data);   // Function:データ変換
          setData(markerData);            // Function:位置とマーカーをセット
        };

        request.send();

      }

      // Function:データ変換
      function parseData(data) {
        var keys = data.values[0];
        var parsemarkerData = [];
        data.values.forEach(function(value, i) {
          if (i > 0) {
            var hash = {};
            value.forEach(function(d, j) {
              hash[keys[j]] = d;
            });
            parsemarkerData.push(hash);
          }
        });
        return parsemarkerData;
      }

      // Function:位置とマーカーをセット
      function setData(markerData){

        var sidebar_html = "";
        var marker = [];

        for (var i = 0; i < markerData.length; i++) {

          // マーカー位置のセット
          var markerLatLng = new google.maps.LatLng({
            lat: Number(markerData[i]['lat']),
            lng: Number(markerData[i]['lng'])
          });

          var name = markerData[i]['name'];

          // マーカーアイコンのセット
          var tagno = markerData[i]['tag'].charAt(0)
          iconcolor = './icon_tag/tag' + tagno + '.png'
          var icon = new google.maps.MarkerImage(iconcolor);

          // マーカーのセット
          marker[i] = new google.maps.Marker({
            position: markerLatLng,          // マーカーを立てる位置を指定
            map: map,                        // マーカーを立てる地図を指定
            icon: icon                       // アイコン指定
          });

          // サイドバーのデータセット
          sidebar_html += name + '<br>';

        }

        // サイドバーへの書き出し
        document.getElementById("sidebar").innerHTML = 'Googleスプレッドシートデータ<br><br>' + sidebar_html;

      }

      function setSideList(){

        var mapMarkerData = [];

        //地図の範囲内を取得
        var bounds = map.getBounds();
        mapNE_lat = bounds.getNorthEast().lat();
        mapSW_lat = bounds.getSouthWest().lat();
        mapNE_lng = bounds.getNorthEast().lng();
        mapSW_lng = bounds.getSouthWest().lng();

        // console.log(mapNE_lat);
        // console.log(mapSW_lat);
        // console.log(mapNE_lng);
        // console.log(mapSW_lng);

        // 緯度経度をもってリストを作成
        var j = 0;
        for (var i = 0; i < markerData.length; i++) {
          if (mapNE_lat >= markerData[i]['lat'] && markerData[i]['lat'] >= mapSW_lat) {
            if (mapNE_lng >= markerData[i]['lng'] && markerData[i]['lng'] >= mapSW_lng) {
              mapMarkerData[j] = markerData[i];
              j++;
            }
          }
        }

        // Function:位置とマーカーをセット（緯度経度にて絞り込みしたデータ）
        setData(mapMarkerData);

      }
    </script>

  </body>
</html>
```

</div></details>

# まとめ
- google.maps.event.addListenerにて、地図移動を捉えて、移動後の緯度経度を取得し、再度、マーカーや場所リストの更新する方法が確認できました。

# 参考にさせていただいたサイト
- http://mspec.jp/blog/archives/109
- https://www.terastella.com/addlistener.html
- https://lab.syncer.jp/Web/API/Google_Maps/JavaScript/Map/idle/