LoginSignup
8
14

More than 1 year has passed since last update.

【Google MAP】Googleスプレッドシート API連携 + 絞込み

Last updated at Posted at 2020-09-05

はじめに

・以前、外部サービス(Sheetson)を利用してGoogleスプレッドシートAPI連携をしました。
(Qiita:【Google MAP】スプレッドシートAPI連携による日本世界遺産の表示

・外部サービスを利用せずに、Google SpreadSheet APIの利用について実施されている方からリンクいただき、外部サービスを利用しない方法を知りましたので、同じことをやってみようと思いました。
(参考サイト Qiita:Googleスプレッドシートを利用した、たぶん史上最も簡単にデータを更新できるマップツール

使用技術/前提条件

  • JavaScript
  • Google Map API
  • Google SpreadSheet API
  • Google Map API keyの取得

内容

・地図にマーカー表示するのは、Googleスプレッドシートに用意したMyLIST。(現時点では300くらい)
001.png

<補足>緯度経度の情報は、名称からPythonにて取得。
 (参考 Qiita:Pythonでジオコーディング(Geocoder/Googlemaps)

・タグ情報ごとにマーカーピンの色を変える。

・タグの絞り込み機能をつけ、それぞれのマーカーピンのみを表示できるようにする。

作成サイト

デモサイト

002.png

コード

  • スプレッドシートURL指定の部分
function.js
      // Function:地図データの取得
      function getMapdata(){

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

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

        request.onload = function () {
          const data = this.response;     // 取得できた値を格納
          // 後続処理を記載
        };

        request.send();

      }
  • 全体のコード
全体のコード
mylist.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>Google Maps My List</title>
    <meta charset="utf-8">
    <style>
      #header {
        font-family: Meriyo UI;
        font-size: 14px;
    	  color: white;
        font-weight: bold;
    	  background-color: darkblue;
    	  padding: 3px;
				width: 1750px;
        border: 1px outset gray;
      }
      #target {
        border: 1px outset gray;
        width: 1400px;
        height: 900px;
      }
      #sidebar {
        border: 1px solid #666;
        padding: 6px;
        background-color: white;
        font-family: Meriyo UI;
        font-size: 12px;
        overflow: auto;
        width: 337px;
        height: 888px;
      }
      #tag {
        font-size: 16px;
        height: 30px;
      }
      #getTag {
        font-size: 16px;
        width: 200px;
        color: #fff;
        background: green;
        border-radius: 5px;
        height: 30px;
      }
    </style>
  </head>

  <body>
    <div id="header">Google Maps - 日本いろいろMY LIST</div>
    <br>
    <div>
      <select id="tag">
        <option value="0">0.ALL</option>
        <option value="1">1.世界遺産</option>
        <option value="2">2.日本三大:七不思議</option>
        <option value="3">3.滝</option>
        <option value="4">4.城</option>
        <option value="5">5.山</option>
        <option value="6">6.温泉</option>
        <option value="7">7.xxx</option>
      </select>
      <button id="getTag">タグの絞込み</button>
    </div>

    <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=APIキーを設定&callback=initMap" async defer></script>

    <script>
      let marker = [];
      let infoWindow = [];
      let markerData = [];

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

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

        map = new google.maps.Map(target, {
          center: centerp,
          zoom: 5,
        });

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

      }

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

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

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

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

        request.send();

      }

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

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

        // 初期化
        let sidebar_html = "";
        marker = [];

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

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

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

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

          // 吹き出しへのデータセット
          const done = markerData[i]['done'];
          const tag = markerData[i]['tag'];
          const name = markerData[i]['name'];
          const img = markerData[i]['img'];

          let setHtml;
          if (done === 'y'){
            setHtml = tag + '<br><br>' + name + '<br><img src=' + img + ' width="200" height="150"><br>';
          } else {
            setHtml = tag + '<br><br>' + name + '<br><br>';
          }

          // 吹き出しのセット
          infoWindow[i] = new google.maps.InfoWindow({
            content: setHtml
          });

          // サイドバーのデータセット
          sidebar_html += '<a href="javascript:myclick(' + i + ')">' + tag + ' : ' + name + '(' + done + ')' + '</a><br>';

          // Function:マーカーにクリックイベントを追加
          markerEvent(i);
        }

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

      }

      // Function:マーカーにクリックイベントを追加
      function markerEvent(i) {
        marker[i].addListener('click', function() {
          myclick(i);     // Function: 吹き出しのオープン・クローズ
        });
      }

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

      // 絞り込みボタンが押下されたとき
      const tagBtn = document.getElementById('getTag');
      tagBtn.addEventListener('click', function(){
        const tag = document.getElementById('tag').value;

        const tagmarkerData = [];
        let j = 0;
        for (let i = 0; i < markerData.length; i++) {
          if (tag === markerData[i]['tag'].charAt(0)) {
            tagmarkerData[j] = markerData[i];
            j++;
          }
          if (tag === '0') {
            tagmarkerData[i] = markerData[i];
          }
        }

        // 地図の初期表示
        const target = document.getElementById('target');
        const centerp = {lat: 37.67229496806523, lng: 137.88838989062504};

        map = new google.maps.Map(target, {
          center: centerp,
          zoom: 5,
        });

        // Function:位置とマーカーをセット(タグを絞り込みしたデータ)
        setData(tagmarkerData);

      });

    </script>

  </body>
</html>

まとめ

  • 外部サービスに頼らずとも、Google Mapと Googleスプレッドシートを連携させることができました。
  • 表形式のGoogleスプレッドシートを更新すれば、地図にすぐに反映できる手軽さはやはりとても便利です。
8
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
14