Clicky

屋台マップを作ろう!Leaflet × Googleスプレッドシート × GASで作るオープンデータWeb地図

GAS(GoogleAppsScript)
GAS(GoogleAppsScript)
この記事は約9分で読めます。

※記事中に広告情報を含みます。

スキルを手に入れた時、人は強くなれる。
Youtubeでスキルアップを始める 電子書籍でスキルアップを始める
\ワードプレスのスキルアップはこちら!/ WordPress入門読本

中洲屋台など、地域の屋台情報を地図上でまとめて見たい。そんな思いから、Googleスプレッドシートをデータベースとして、Leafletで表示する屋台マップを作ってみます。この記事では、無料の構成で実現する方法をまとめます。


使用技術

  • Leaflet.js:オープンソースの地図ライブラリ(軽量・商用利用可)
  • Google Apps Script(GAS):スプレッドシートをWeb API化
  • Googleスプレッドシート:屋台データの管理用データベース
  • OpenStreetMap:背景地図タイル(無料で利用可)

システム構成図

Google Spreadsheet
     ↓ (getYataiList)
Google Apps Script (Web App)
     ↓
Leaflet + OpenStreetMap (index.html)

スプレッドシート構成

シート名:屋台リスト(例)

屋台ID名称緯度経度カテゴリー利用可能曜日
1博多屋台ラーメン一番33.5903,130.4018ラーメン月〜土
2焼き鳥だるま33.5899,130.4024焼き鳥水〜日
3餃子ひかり33.5905,130.4007餃子金・土

緯度経度は「カンマ区切り」で入力(例:33.5903,130.4018)。Googleマップなどで座標を取得できます。


Google Apps Script (Code.gs)

スプレッドシートから屋台データを取得して返すAPIを作ります。

/**
 * 屋台マップ用 Webアプリ
 */
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile("index")
    .setTitle("屋台マップ")
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

/**
 * スプレッドシートから屋台データを取得
 */
function getYataiList() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("屋台リスト");
  const data = sheet.getDataRange().getValues();
  const headers = data[0];

  const idIndex = headers.indexOf("屋台ID");
  const nameIndex = headers.indexOf("名称");
  const latlonIndex = headers.indexOf("緯度経度");
  const categoryIndex = headers.indexOf("カテゴリー");
  const daysIndex = headers.indexOf("利用可能曜日");

  const result = [];

  for (let i = 1; i < data.length; i++) {
    const row = data[i];
    const latlon = row[latlonIndex];
    if (!latlon || !String(latlon).includes(",")) continue;

    const [lat, lon] = latlon.split(",").map((x) => parseFloat(x.trim()));
    if (isNaN(lat) || isNaN(lon)) continue;

    result.push({
      id: row[idIndex] || "",
      name: row[nameIndex] || "名称未設定",
      category: row[categoryIndex] || "",
      days: row[daysIndex] || "",
      lat,
      lon,
    });
  }

  return result;
}

index.html(Leafletによる地図表示)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>屋台マップ</title>

  <!-- Leaflet -->
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

  <style>
    html, body { height: 100%; margin: 0; padding: 0; }
    body {
      font-family: "Noto Sans JP", sans-serif;
      display: flex;
      flex-direction: column;
      background-color: #fafafa;
    }
    header {
      background: #c62828;
      color: #fff;
      text-align: center;
      padding: 8px 0;
      font-size: 18px;
      letter-spacing: 0.05em;
    }
    #map { flex-grow: 1; width: 100%; height: 100%; }
    .popup-name { font-weight: bold; font-size: 15px; color: #b71c1c; }
    .popup-category { font-size: 13px; color: #444; }
    .popup-days { font-size: 12px; color: #1b5e20; margin-top: 2px; }
  </style>
</head>

<body>
  <header>屋台マップ</header>
  <div id="map"></div>

  <script>
    // 初期位置(福岡・中洲付近)
    const map = L.map("map").setView([33.5898, 130.4021], 16);

    // OpenStreetMap タイル
    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
      attribution: "地図データ © OpenStreetMap contributors",
    }).addTo(map);

    // 屋台アイコン
    const yataiIcon = L.icon({
      iconUrl: "https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png",
      shadowUrl: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png",
      iconSize: [25, 41],
      iconAnchor: [12, 41],
      popupAnchor: [1, -34],
      shadowSize: [41, 41],
    });

    // GASから屋台データ取得
    google.script.run.withSuccessHandler(displayYatai).getYataiList();

    // ピンを描画
    function displayYatai(list) {
      list.forEach((y) => {
        if (isNaN(y.lat) || isNaN(y.lon)) return;

        const popupHtml = `
          <div class="popup-content">
            <div class="popup-name">${y.name}</div>
            <div class="popup-category">カテゴリー:${y.category}</div>
            <div class="popup-days">営業日:${y.days}</div>
          </div>
        `;

        L.marker([y.lat, y.lon], { icon: yataiIcon })
          .addTo(map)
          .bindPopup(popupHtml);
      });
    }
  </script>
</body>
</html>

デプロイ手順

  1. Googleスプレッドシートを用意し、「屋台リスト」シートを作成
  2. Apps Script を開き
    Code.gsindex.html を追加
  3. メニューから
    [デプロイ] → [新しいデプロイ] → [ウェブアプリ]
  4. アクセス権限を「全員(匿名含む)」に設定して公開
  5. 発行されたURLを開くと、屋台マップが表示されます!

応用・拡張アイデア

機能内容
曜日フィルター今日営業中の屋台だけを表示
カテゴリー別アイコンラーメン=赤、焼き鳥=黄、餃子=緑など色分け
検索フォーム屋台名またはジャンル検索
現在地表示スマホのGPSと連携して近い屋台をピン表示
GeoJSON拡張地区ポリゴンデータを重ねてエリア分析も可能

Leaflet活用のポイント

Leafletは軽量かつシンプルで、以下の特長があります。

  • オープンソースで商用利用も無料
  • モバイル対応のインタラクティブ地図
  • プラグインが豊富(検索・クラスタ・フルスクリーンなど)
  • GeoJSON, CSV, APIなど柔軟なデータ連携が可能

国土地理院の地図タイルやGeoJSONデータを組み合わせると、
より本格的なWebGISとしても活用できます。


まとめ

今回は、スプレッドシートのデータをそのままWebマップに反映できる「屋台マップ」を構築しました。Leafletの扱いに慣れると、地域イベント・不動産・観光など、さまざまな場面で応用できます。無料で動く「地域マップ」基盤としてもおすすめです。