search
HomeWeb Front-endJS TutorialBuilding an Interactive XY Image Plot with Google Apps Script and Leaflet.js

Google Maps has a ton of features for plotting points on a map, but what if you want to plot points on an image? These XY Image Plot maps are commonly used for floor maps, job site inspections, and even games.

In this guide, I'll show you how to create an interactive map with draggable points using Leaflet.js and Google Apps Script. We'll cover everything from setting up the map to integrating data from Google Sheets, and deploying it as a web app.

This guide will cover:

  • Setting up Leaflet.js in a Google Apps Script HTML Service

  • Displaying Markers using data from Google Sheets

  • Updating Sheets row when a Marker is moved

  • Creating new Markers from the map and saving to Sheets

  • Deleting a marker from the web app

Setting up Leaflet.js in a Google Apps Script HTML Service

Leaflet.js is one of the most popular open-source mapping libraries. It's light-weight, easy to use, and had great documentation. They support a ton of different map types, including "CRS.Simple", or Coordinate Reference System, which allows you to supply a background image.

Google Sheets Set Up

Start out by creating a sheet named map_pin with the following structure:

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

然後從「擴充功能」選單開啟 Apps 腳本。

建立 HTML 文件

首先,我們將從 Leaflet 文件中的基本範例開始,以使程式庫正常運作。您可以在此處查看其快速入門指南中的完整範例。

新增一個新的HTML文件,命名為Index,並將內容設為:



  <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>


  <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>


然後使用以下內容更新 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

好的,這就是使用 Leaflet 的常規地圖範例。現在介紹 CRS.Simple 地圖類型,它允許提供背景圖片。

使用傳單教學中的範例更新 HTML。



  <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>


  <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>


這裡我們提供一張 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 中使用它們。

現在為 HTML 添加一個函數以循環此 JSON 並在地圖載入後建立地圖圖釘。

// 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}`);
        });
      });
    }
</b>

儲存,然後開啟測試部署。現在您應該已經從工作表資料產生了標記!

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

每個圖釘都有一個彈出窗口,其中包含該行的標題。此時圖釘可以拖曳,但我們仍然需要一個函數來儲存新位置。

拖曳時儲存標記位置

要保存新位置,我們需要兩個函數:一個在 HTML 中用於捕獲客戶端的事件,另一個用於在伺服器端的 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 



<p>儲存並重新整理測試部署。現在,當拖曳標記時,您應該會看到工作表更新! </p>

<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/172580614176490.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Building an Interactive XY Image Plot with Google Apps Script and Leaflet.js"></p>

<h2>
  
  
  新增點
</h2>

<p>我們現在可以移動現有的點,但是增加新的點怎麼樣?同樣,我們需要兩個函數,一個在 HTML 中,一個在 Code.gs 檔案中。 </p>

<p>首先,在 HTML 中新增一個函數,以便在使用者點擊地圖上的空白點時開啟提示,並將值傳遞給伺服器函數。 <br>
</p>

<pre class="brush:php;toolbar:false">    // 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 



<h2>
  
  
  接下來是什麼?
</h2>

<p>您也可以從這裡做很多事情,例如向每個標記添加其他資料點、動態背景圖像或其他點擊和拖曳互動。你甚至可以製作遊戲!有用例的想法嗎?在下面發表評論! </p>


          

            
        

The above is the detailed content of Building an Interactive XY Image Plot with Google Apps Script and Leaflet.js. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Python vs. JavaScript: A Comparative Analysis for DevelopersPython vs. JavaScript: A Comparative Analysis for DevelopersMay 09, 2025 am 12:22 AM

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Python vs. JavaScript: Choosing the Right Tool for the JobPython vs. JavaScript: Choosing the Right Tool for the JobMay 08, 2025 am 12:10 AM

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript: Understanding the Strengths of EachPython and JavaScript: Understanding the Strengths of EachMay 06, 2025 am 12:15 AM

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScript's Core: Is It Built on C or C  ?JavaScript's Core: Is It Built on C or C ?May 05, 2025 am 12:07 AM

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

JavaScript Frameworks: Powering Modern Web DevelopmentJavaScript Frameworks: Powering Modern Web DevelopmentMay 02, 2025 am 12:04 AM

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

The Relationship Between JavaScript, C  , and BrowsersThe Relationship Between JavaScript, C , and BrowsersMay 01, 2025 am 12:06 AM

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Atom editor mac version download

Atom editor mac version download

The most popular open source editor