【Google MAP】スプレッドシートAPI連携による日本世界遺産の表示

## はじめに：やりたいこと
 - Mapにピンを打ったり、その場所を表示するには、緯度・経度情報が必要になります。
 - 以前、[こちらの記事(Qiita)](https://qiita.com/yoshi_yast/items/e68970e20527ff3d9b15)にて、DBから読み込み方法を試しました。
 - 最近、[観測史上最速！GoogleスプレッドシートだけでAPIが作れる「Sheetson」](https://entry.anypicks.jp/product-sheetson/)
というのを拝見して、これで日本の世界遺産リストを表示してみようと思いました。

## 前提条件
 - Google Map API keyの取得

## 使用技術
 - JavaScript
 - Google Map API
 - Sheetson (GoogleスプレッドシートでAPIをつくる)

## 作成サイトイメージ
・日本の世界遺産リストを表示する
（自分が訪れたところがあるところとないところをピンで色分け）

[デモサイト](https://anotherskyjp.site/japantravel/20_japan_heritage/japan_heritage_map.html)
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/3fe90d67-718d-94e1-7616-0945cb93e93a.png)

## Google スプレッドシートの作成

・[観測史上最速！GoogleスプレッドシートだけでAPIが作れる「Sheetson」](https://entry.anypicks.jp/product-sheetson/)をみて、Googleスプレッドシートを作成する。

①スプレッドシートを作成する
②共有する　sheetson@project-id-9647564749903618942.iam.gserviceaccount.com
③URLをたたけば、アクセスできる
（例）https://api.sheetson.com/v1/sheets/シート名?spreadsheetId=スプレッドシートID

・スプレッドシートには、名称、緯度、経度、サイトURL、区分、写真パスなどの情報を保持
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/462cc0db-6652-bb5d-1e6c-49a6ec1d67e2.png)

## コード（JavaScript）

・JavaScriptでAPIを呼び出す方法

~~~JavaScript
// XMLHttpRequestオブジェクトの作成
var request = new XMLHttpRequest();

// URLを開く
request.open('GET', URL, true);

// レスポンスが返ってきた時の処理を記述 
request.onload = function () {
  // レスポンスが返ってきた時の処理
}

// リクエストをURLに送信
request.send();
~~~


・全体のコード

~~~HTML
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Google Maps World Heritage(Japan)</title>
    <style>
      // 省略
    </style>
  </head>
  <body>
    <div id="header">Google Maps - World Heritage(Japan) - 日本の世界遺産</div>
    <div id="target"></div>
    <td><div id="sidebar"></div></td>

    <!-- Google MAP API呼出 -->
    <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=「APIキーを設定する」&callback=initMap" async defer></script>

    <script>
      var map;
      var marker = [];
      var infoWindow = [];

      function initMap() {

        var target = document.getElementById('target');
        var centerp = {lat: 37.67229496806523, lng: 137.88838989062504};

        //マップ表示
        map = new google.maps.Map(target, {
          center: centerp,
          zoom: 5,
        });

        //APIにてデータを取得して、位置とマーカーをセットするfunctionを呼び出す
        var request = new XMLHttpRequest();
        request.open('GET', 'https://api.sheetson.com/v1/sheets/「シート名」?spreadsheetId=「スプレッドシートID」', true);
        request.responseType = 'json';

        request.onload = function () {
          var markerData = this.response;
          // console.log(markerData);
          setData(markerData);
        };

        request.send();

      }

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

        var sidebar_html = "";
        var icon;

        for (var i = 0; i < markerData.results.length; i++) {
          // マーカー位置セット
          var markerLatLng = new google.maps.LatLng({
            lat: Number(markerData.results[i]['lat']),
            lng: Number(markerData.results[i]['lng'])
          });
          // マーカーアイコンのセット
          if (markerData.results[i]['pic'] === 'on'){
            icon = new google.maps.MarkerImage('./icon_blue/numbericon_blue_' + [i + 1] + '.png');
          } else {
            icon = new google.maps.MarkerImage('./icon_pink/numbericon_pink_' + [i + 1] + '.png');
          }
          // マーカーのセット
          marker[i] = new google.maps.Marker({
            position: markerLatLng,          // マーカーを立てる位置を指定
            map: map,                        // マーカーを立てる地図を指定
            icon: icon                       // アイコン指定
          });
          // 吹き出しの追加
          var name = markerData.results[i]['name'];
          var url = markerData.results[i]['url'];
          var tag = markerData.results[i]['tag'];
          var img = markerData.results[i]['img'];

          if (markerData.results[i]['pic'] === 'on'){
            var setHtml = '<a href=' + url + ' target="right">' + name + '</a><br><br>' + tag + '<br><img src=' + img + ' width="200" height="150"><br>'
          } else {
            var setHtml = '<a href=' + url + ' target="right">' + name + '</a><br><br>' + tag + '<br><br>'
          }

          infoWindow[i] = new google.maps.InfoWindow({
            content: setHtml           // 吹き出しに表示する内容
          });
          // サイドバー
          sidebar_html += '<a href="javascript:myclick(' + i + ')">' + name + '<\/a><br />';
          // マーカーにクリックイベントを追加
          markerEvent(i);
        }

        // サイドバー
        document.getElementById("sidebar").innerHTML = '<日本の世界遺産List><br><br>' + sidebar_html;

      }

      var openWindow;

      // クリックイベント
      function markerEvent(i) {
        marker[i].addListener('click', function() {
          myclick(i);
        });
      }

      // 吹き出しのオープン・クローズ
      function myclick(i) {
        if(openWindow){
          openWindow.close();
        }
        infoWindow[i].open(map, marker[i]);
        openWindow = infoWindow[i];
      }

    </script>

  </body>
</html>
~~~


## まとめ
- いままでプログラム中に緯度・経度を直接コードの中に記載していたものを、DBよりもさらに手軽に、外だしすることができました。
- 例えば、Google Apps ScriptなどでGoogleスプレッドシートを自動更新すると、APIにより取得できる情報が変わるので、静的な情報ばかりなく、いろいろな用途が考えるような気がします。