ホームページ ウェブフロントエンド jsチュートリアル Google Apps Script と Leaflet.js を使用したインタラクティブな XY 画像プロットの構築

Google Apps Script と Leaflet.js を使用したインタラクティブな XY 画像プロットの構築

Sep 08, 2024 pm 10:35 PM

Google マップには地図上に点をプロットするための機能がたくさんありますが、画像上に点をプロットしたい場合はどうすればよいでしょうか?これらの XY 画像プロット マップは、フロア マップ、現場検査、さらにはゲームにもよく使用されます。

このガイドでは、Leaflet.js と Google Apps Script を使用して、ドラッグ可能なポイントを含むインタラクティブなマップを作成する方法を説明します。地図の設定から Google スプレッドシートのデータの統合、ウェブ アプリとしての展開まで、すべてを説明します。

このガイドの内容は次のとおりです:

  • Google Apps Script HTML サービスでの Leaflet.js のセットアップ

  • Google スプレッドシートのデータを使用してマーカーを表示する

  • マーカーが移動されたときにシート行を更新する

  • 地図から新しいマーカーを作成し、スプレッドシートに保存します

  • Web アプリからマーカーを削除する

Google Apps Script HTML サービスで Leaflet.js をセットアップする

Leaflet.js は、最も人気のあるオープンソース マッピング ライブラリの 1 つです。軽量で使いやすく、ドキュメントも充実しています。これらは、背景画像を提供できる「CRS.Simple」または座標参照システムを含む、さまざまなマップ タイプをサポートしています。

Google スプレッドシートのセットアップ

まず、次の構造を持つ、map_pin という名前のシートを作成します。

id title x y
1 test1 10 30
2 test2 50 80

次に、[拡張機能] メニューから Apps Script を開きます。

HTMLファイルの作成

まず、ライブラリを動作させるために、Leaflet ドキュメントの基本的な例から始めます。完全な例は、こちらのクイック スタート ガイドでご覧いただけます。

Index という名前の新しい HTML ファイルを追加し、コンテンツを次のように設定します。

<!DOCTYPE html>
<html>
<head>
  <title>Quick Start - Leaflet</title>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" />
  <style>
    #map {
      height: 400px;
    }
  </style>
</head>
<body>
  <div id="map"></div>

  <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
  <script>
    var map = L.map('map').setView([40.73, -73.99], 13);

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 19,
      attribution: '© OpenStreetMap'
    }).addTo(map);

    var marker = L.marker([40.73, -73.99]).addTo(map)
      .bindPopup('Test Popup Message')
      .openPopup();
  </script>
</body>
</html>

次に、Code.gs ファイルを次のように更新します。

function doGet() {
  const html = HtmlService.createHtmlOutputFromFile('Index')
    .setTitle('Map with Draggable Points')
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
  return html;
}

保存し、[デプロイ] をクリックして、Web アプリとして公開します。次に、新しいデプロイメントのリンクを開くと、Leaflet.js がニューヨークの地図を表示しているのが表示されます。

Building an Interactive XY Image Plot with Google Apps Script and Leaflet.js

OK、これは Leaflet を使用した通常の地図の例です。次に、背景画像を提供できる CRS.Simple マップ タイプに移ります。

リーフレット チュートリアルのこの例を使用して HTML を更新します。

<!DOCTYPE html>
<html>
<head>
  <title>CRS Simple Example - Leaflet</title>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" />
  <style>
    #map {
      height: 400px;
      width: 600px;
    }
    body {
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>
  <div id="map"></div>

  <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"></script>
  <script>
    // Set up the map with a simple CRS (no geographic projection)
    var map = L.map('map', {
      crs: L.CRS.Simple,
      minZoom: -1,
      maxZoom: 4
    });

    // Define the dimensions of the image
    var bounds = [[0, 0], [1000, 1000]];
    var image = L.imageOverlay('https://leafletjs.com/examples/crs-simple/uqm_map_full.png', bounds).addTo(map);

    // Set the initial view of the map to show the whole image
    map.fitBounds(bounds);

    // Optional: Add a marker or other elements to the map
    var marker = L.marker([500, 500]).addTo(map)
      .bindPopup('Center of the image')
      .openPopup();
  </script>
</body>
</html>

ここでは 1000 x 1000 ピクセルの画像を指定し、中心マーカーを 500、500 に設定します。

保存をクリックし、次に展開>展開のテストをクリックして、新しいマップ タイプを確認します。これで、背景画像と中央にマーカーがプロットされた地図が完成したはずです。

Building an Interactive XY Image Plot with Google Apps Script and Leaflet.js

Google スプレッドシートのデータを使用して地図を初期化する

次に、シートのデータを使用して、マップ上に一連のマーカーを設定します。

まず、マーカーの位置を取得する関数を Code.gs ファイルに追加します。

function getPinData(){
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheetByName('map_pin');
  const data = sh.getDataRange().getValues();
  const json = arrayToJSON(data);
  //Logger.log(json);
  return json
}

function arrayToJSON(data=getPinData()){
  const headers = data[0];
  const rows = data.slice(1);
  let jsonData = [];
  for(row of rows){
    const obj = {};
    headers.forEach((h,i)=>obj[h] = row[i]);
    jsonData.push(obj)
  }
  //Logger.log(jsonData)
  return jsonData
}

ここではピンを JSON として返しているので、次のセクションの HTML での作業が簡単になります。

次に、この JSON をループする関数を HTML に追加し、マップが読み込まれた後にマップ ピンを作成します。

// Add map pins from sheet data
    google.script.run.withSuccessHandler(addMarkers).getPinData();

    function addMarkers(mapPinData) {
      mapPinData.forEach(pin => {
        const marker = L.marker([pin.x, pin.y], {
          draggable: true
        }).addTo(map);

        marker.bindPopup(`<b>${pin.title}`).openPopup();

        marker.on('dragend', function(e) {
          const latLng = e.target.getLatLng();
          console.log(`Marker ${pin.title} moved to: ${latLng.lat}, ${latLng.lng}`);
        });
      });
    }

保存して、テスト展開を開きます。これで、シート データからマーカーが生成されたはずです!

Building an Interactive XY Image Plot with Google Apps Script and Leaflet.js

各ピンには、その行のタイトルを含むポップアップがあります。この時点でピンはドラッグ可能ですが、新しい位置を保存する関数がまだ必要です。

ドラッグ時のマーカー位置の保存

新しい位置を保存するには、2 つの関数が必要です。1 つはクライアント側でイベントをキャプチャする HTML 内の関数で、もう 1 つはサーバー側の Code.gs ファイルに新しい位置を保存する関数です。

次のコマンドを使用して HTML を更新します。

    function addMarkers(mapPinData) {
      mapPinData.forEach(pin => {
        const { id, title, x, y } = pin;
        const marker = L.marker([x, y], {
          draggable: true
        }).addTo(map);

        marker.bindPopup(`<b>${title}</b>`).openPopup();

        marker.on('dragend', function(e) {
          const latLng = e.target.getLatLng();
          console.log(`Marker ${title} moved to: ${latLng.lat}, ${latLng.lng}`);
          saveMarkerPosition({ id, title, lat: latLng.lat, lng: latLng.lng });
        });
      });
    }

    function saveMarkerPosition({ id, title, lat, lng }) {
      google.script.run.saveMarkerPosition({ id, title, lat, lng });
    }

次に、関数を Code.gs ファイルに追加して、場所を保存します。

function saveMarkerPosition({ id, lat, lng }) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheetByName('map_pin');
  const data = sh.getDataRange().getValues();

  for (let i = 1; i < data.length; i++) {
    if (data[i][0] === id) {  // ID column (index 0)
      sh.getRange(i + 1, 3).setValue(lat);  // latitude column
      sh.getRange(i + 1, 4).setValue(lng);  // longitude column
      break;
    }
  }
}

テスト展開を保存し、更新します。マーカーをドラッグするとシートが更新されるのが確認できるはずです!

Building an Interactive XY Image Plot with Google Apps Script and Leaflet.js

新しいポイントを追加する

既存のポイントを移動できるようになりましたが、新しいポイントを追加する場合はどうすればよいでしょうか?繰り返しますが、2 つの関数が必要になります。1 つは HTML に、もう 1 つは Code.gs ファイルにあります。

まず、ユーザーが地図上の空いている場所をクリックしたときにプロンプ​​トを開く関数を HTML に追加し、その値をサーバー関数に渡します。

    // Function to add a new pin
    map.on('click', function(e) {
      const latLng = e.latlng;
      const title = prompt('Enter a title for the new pin:');
      if (title) {
        google.script.run.withSuccessHandler(function(id) {
          addNewMarker({ id, title, lat: latLng.lat, lng: latLng.lng });
        }).addNewPin({ title, lat: latLng.lat, lng: latLng.lng });
      }
    });

    function addNewMarker({ id, title, lat, lng }) {
      const marker = L.marker([lat, lng], {
        draggable: true
      }).addTo(map);

      marker.bindPopup(`<b>${title}</b>`).openPopup();

      marker.on('dragend', function(e) {
        const latLng = e.target.getLatLng();
        saveMarkerPosition({ id, title, lat: latLng.lat, lng: latLng.lng });
      });
    }

次に、関数を Code.gs に追加して新しい行を保存します。

function addNewPin({ title, lat, lng }) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheetByName('map_pin');

  // Check if there are any rows present, if not initialize ID
  const lastRow = sh.getLastRow();
  let newId = 1;

  if (lastRow > 0) {
    const lastId = sh.getRange(lastRow, 1).getValue();
    newId = lastId + 1;
  }

  sh.appendRow([newId, title, lat, lng]);

  return newId;
}

もう一度保存して、テスト展開を更新します。空の場所をクリックすると、タイトルを入力して新しいマーカーを保存できるようになりました!

Building an Interactive XY Image Plot with Google Apps Script and Leaflet.js

マーカーの削除

最後に、マーカーを削除する方法を追加して、マップ ビューで完全な CRUD アプリを提供する必要があります。

マーカーの追加関数を更新して、ポップアップに削除ボタンを追加します:

      const popupContent = `<b>${title}</b><br><button onclick="deleteMarker(${id})">Delete Marker</button>`;
      marker.bindPopup(popupContent).openPopup();

次に、クライアント側から削除するための関数を追加します。

// Function to delete a marker
  function deleteMarker(id) {
    const confirmed = confirm('Are you sure you want to delete this marker?');
    if (confirmed) {
      google.script.run.withSuccessHandler(() => {
        // Refresh the markers after deletion
        google.script.run.withSuccessHandler(addMarkers).getPinData();
      }).deleteMarker(id);
    }
  }

次に、一致する関数を Code.gs ファイルに追加します。

function deleteMarker(id) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheetByName('map_pin');
  const data = sh.getDataRange().getValues();

  for (let i = 1; i < data.length; i++) {
    if (data[i][0] === id) {  // ID column (index 0)
      sh.deleteRow(i + 1);  // Delete the row
      break;
    }
  }
}

次は何ですか?

各マーカーへの他のデータ ポイントの追加、動的な背景画像、その他のクリック アンド ドラッグ インタラクションなど、ここからできることはたくさんあります。ゲームも作れるかも!使用例についてのアイデアはありますか?以下にコメントを書き込んでください!

以上がGoogle Apps Script と Leaflet.js を使用したインタラクティブな XY 画像プロットの構築の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

node.jsでHTTPリクエストを作成する方法は? node.jsでHTTPリクエストを作成する方法は? Jul 13, 2025 am 02:18 AM

node.jsでHTTPリクエストを開始するには、組み込みモジュール、axios、およびnode-fetchを使用する3つの一般的な方法があります。 1.依存関係のない内蔵http/httpsモジュールを使用します。これは基本的なシナリオに適していますが、https.get()を使用してデータを取得したり、.write()を介してPOSTリクエストを送信するなど、データステッチとエラーモニタリングの手動処理が必要です。 2.Axiosは、約束に基づいたサードパーティライブラリです。簡潔な構文と強力な機能を備えており、非同期/待ち声、自動JSON変換、インターセプターなどをサポートします。非同期リクエスト操作を簡素化することをお勧めします。 3.Node-Fetchは、約束と単純な構文に基づいて、ブラウザフェッチに似たスタイルを提供します

JavaScriptデータ型:プリミティブ対参照 JavaScriptデータ型:プリミティブ対参照 Jul 13, 2025 am 02:43 AM

JavaScriptデータ型は、プリミティブタイプと参照タイプに分割されます。プリミティブタイプには、文字列、数字、ブール、ヌル、未定義、シンボルが含まれます。値は不変であり、コピーは値を割り当てるときにコピーされるため、互いに影響を与えません。オブジェクト、配列、関数などの参照タイプはメモリアドレスを保存し、同じオブジェクトを指す変数は互いに影響します。 TypeofとInstanceOFを使用してタイプを決定できますが、TypeOfNullの歴史的な問題に注意してください。これらの2種類の違いを理解することは、より安定した信頼性の高いコードを書くのに役立ちます。

JavaScriptでオブジェクトの配列をフィルタリングします JavaScriptでオブジェクトの配列をフィルタリングします Jul 12, 2025 am 03:14 AM

JavaScriptのフィルター()メソッドは、すべての合格テスト要素を含む新しい配列を作成するために使用されます。 1.Filter()は元の配列を変更しませんが、条件付き要素を満たす新しい配列を返します。 2。基本的な構文はarray.filter((element)=> {returnCondition;})です。 3.オブジェクト配列は、30歳以上のユーザーをフィルタリングするなど、属性値でフィルタリングできます。 4.年齢と名前の長さの条件を同時に満たすなど、マルチコンディショナルフィルタリングをサポートします。 5。動的条件を処理し、フィルターパラメーターを関数にパスして、柔軟なフィルタリングを実現できます。 6.それを使用する場合は、空のアレイの返品を避けるためにブール値を返すように注意し、他の方法を組み合わせて文字列マッチングなどの複雑なロジックを実現してください。

配列にJavaScriptに値が含まれているかどうかを確認する方法 配列にJavaScriptに値が含まれているかどうかを確認する方法 Jul 13, 2025 am 02:16 AM

JavaScriptでは、配列に特定の値が含まれているかどうかを確認します。最も一般的な方法は、boolean値を返す()を含む()であり、構文はarray.includes(valuetofind)です。古い環境と互換性がある必要がある場合は、numbers.indexof(20)!== -1などのindexof()を使用します。オブジェクトまたは複雑なデータの場合、ユーザー(user => user.id === 1)などの綿密な比較には、いくつかの()メソッドを使用する必要があります。

async/async/await javascript関数でのエラー処理 async/async/await javascript関数でのエラー処理 Jul 12, 2025 am 03:17 AM

非同期関数のエラーを処理するには、トライ/キャッチを使用し、コールチェーンでそれらを処理し、.catch()メソッドを使用して、unhandledRejectionイベントをリッスンします。 1.トライ/キャッチに使用するためにエラーをキャッチすることは、明確な構造を備えた推奨方法であり、待ち望みの例外を処理できます。 2。コールチェーンの取り扱いエラーは、マルチステッププロセスに適した集中ロジックにすることができます。 3. .catch()を使用して、Async関数を呼び出した後にエラーをキャッチします。これは、Promiseの組み合わせシナリオに適しています。 4.未処理のイベントに耳を傾けて、未処理の拒否を最後の防衛線として記録します。上記の方法は、非同期エラーが正しくキャプチャおよび処理されることを共同で保証します。

JavaScriptのタイムゾーンを処理する方法は? JavaScriptのタイムゾーンを処理する方法は? Jul 11, 2025 am 02:41 AM

JavaScriptタイムゾーンの問題に対処するための鍵は、適切な方法を選択することです。 1.ネイティブの日付オブジェクトを使用する場合は、UTC時間に保存および転送し、表示時にユーザーのローカルタイムゾーンに変換することをお勧めします。 2。複雑なタイムゾーン操作の場合、IANAタイムゾーンデータベースをサポートし、便利なフォーマットおよび変換機能を提供するモーメントタイムゾーンを使用できます。 3.表示時間をローカライズする必要があり、サードパーティライブラリを導入したくない場合は、intl.dateTimeformatを使用できます。 4.最新の軽量ソリューションDay.JSおよびTimeZoneおよびUTCプラグインに推奨されます。

JavaScriptのコンテキストで説明されている仮想DOMの概念 JavaScriptのコンテキストで説明されている仮想DOMの概念 Jul 12, 2025 am 03:09 AM

Virtual Domは、実際のDOM更新を最適化するプログラミングコンセプトです。メモリ内の実際のDOMに対応するツリー構造を作成することにより、実際のDOMの頻繁かつ直接的な動作を避けます。その中心的な原則は次のとおりです。1。データが変更されたときに新しい仮想DOMを生成します。 2。新しい仮想ドームと古い仮想ドームの最小の違いを見つけます。 3.再配置と再描画のオーバーヘッドを減らすための実際のDOMのバッチアップデート。さらに、ユニークな安定したキーを使用すると、リストの比較効率を改善できますが、最新のフレームワークでは他のテクノロジーを採用して仮想DOMを置き換えます。

機能プログラミングとは何ですか?コアコンセプトのJSラウンドアップ 機能プログラミングとは何ですか?コアコンセプトのJSラウンドアップ Jul 11, 2025 am 03:13 AM

functionprogramminginjavascriptemphasizes clean、predictablecodethroghcoreconcepts.1.purefunctionsconsconsientlyturturturturturtputputtitputitedside effects、改善可能性と予測可能性

See all articles