웹 프론트엔드 JS 튜토리얼 Google Apps Script 및 Leaflet.js를 사용하여 대화형 XY 이미지 플롯 구축

Google Apps Script 및 Leaflet.js를 사용하여 대화형 XY 이미지 플롯 구축

Sep 08, 2024 pm 10:35 PM

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

저장한 다음 배포를 클릭하고 웹 앱으로 게시하세요. 그런 다음 새 배포에 대한 링크를 열면 Leaflet.js가 뉴욕 지도를 표시하는 것을 볼 수 있습니다.

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

그럼 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
}

다음 섹션의 HTML에서 더 쉽게 작업할 수 있도록 핀을 JSON으로 반환합니다.

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

각 핀에는 해당 행의 제목이 포함된 팝업이 있습니다. 이 시점에서 핀을 드래그할 수 있지만 새 위치를 저장하는 기능이 여전히 필요합니다.

드래그 시 마커 위치 저장

새 위치를 저장하려면 클라이언트 측에서 이벤트를 캡처하는 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 < 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

새 포인트 추가

이제 기존 포인트를 이동할 수 있지만 새 포인트를 추가하는 것은 어떨까요? 이번에도 HTML과 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Stock Market GPT

Stock Market GPT

더 현명한 결정을 위한 AI 기반 투자 연구

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

JavaScript에서 데이터 속성으로 요소를 어떻게 선택합니까? JavaScript에서 데이터 속성으로 요소를 어떻게 선택합니까? Aug 30, 2025 am 01:57 AM

CSS 속성 선택기를 통해 JavaScript의 데이터 속성을 사용하여 요소를 선택하고 문서를 사용하여 문서를 사용하여이를 달성하십시오. 1. [data-attribute]를 사용하여 지정된 데이터 속성 (모든 값)이있는 요소를 선택하십시오. 2. [data-attribute = "value"]를 사용하여 속성 값이 정확히 일치하는 요소를 선택하십시오. 3. Data-User-ID가 DataSet.userId에 해당하는 Element.Dataset을 통해 데이터 속성에 액세스하십시오.

Pytest 및 Selenium : 동적 데이터 중심 테스트를위한 구현 전략 Pytest 및 Selenium : 동적 데이터 중심 테스트를위한 구현 전략 Aug 30, 2025 am 06:00 AM

이 기사는 동적 데이터 중심 테스트를 위해 pytest 및 selenium을 사용할 때 런타임에 생성 된 데이터를 직접 처리 할 수없는 @pytest.mark.mark.martrize 데코레이터가 직접 처리 할 수없는 문제를 해결하는 것을 목표로합니다. 우리는 pytest.mark.marketrize의 한계를 탐구하고 Pytest의 pytest_generate_tests 후크 기능을 통해 Selenium 동적 데이터 수집을 기반으로 매개 변수화 된 테스트를 우아하게 구현하는 방법을 자세히 소개하여 테스트 사례의 유연성과 효율성을 보장합니다.

jQuery 팝업 창에서 동적 외부 링크 점프의 이벤트 처리 최적화 jQuery 팝업 창에서 동적 외부 링크 점프의 이벤트 처리 최적화 Sep 01, 2025 am 11:48 AM

이 기사는 JQuery 팝업 창에서 외부 링크 리디렉션 버튼을 리디렉션하는 문제를 해결하는 것을 목표로합니다. 사용자가 여러 외부 링크를 연속적으로 클릭하면 팝업의 점프 버튼이 항상 첫 번째 클릭 링크를 가리킬 수 있습니다. 핵심 솔루션은 OFF ( 'Click') 메소드를 사용하여 새 이벤트의 각 바인딩 전에 이전 이벤트 핸들러를 취소하여 점프 동작이 항상 최신 대상 URL을 가리키므로 정확하고 제어 가능한 링크 리디렉션을 달성하는 것입니다.

근무일 및 근무 시간으로 실행하는 JavaScript 카운터 구축 근무일 및 근무 시간으로 실행하는 JavaScript 카운터 구축 Aug 31, 2025 am 06:30 AM

이 기사는 JavaScript를 사용하여 정확한 타이밍 카운터를 구축하는 방법에 대해 자세히 설명합니다. 카운터는 분에 한 번 증가하지만 사전 설정 근무일 (월요일 ~ 금요일)과 근무 시간 (예 : 오전 6시에서 오후 8시) 이내에 만 운행됩니다. 작동하지 않는 시간에는 증가를 일시 중지 할 수 있지만 현재 값을 표시하고 매월 첫날에 자동으로 재설정하여 계산 로직의 정확성과 유연성을 보장합니다.

JavaScript는 클릭 스루 이미지 전환 효과 : 전문 자습서를 인식합니다 JavaScript는 클릭 스루 이미지 전환 효과 : 전문 자습서를 인식합니다 Sep 18, 2025 pm 01:03 PM

이 기사는 JavaScript를 사용하여 이미지를 클릭하는 효과를 얻는 방법을 소개합니다. 핵심 아이디어는 HTML5의 데이터-* 속성을 사용하여 대체 이미지 경로를 저장하고 JavaScript를 통해 클릭 이벤트를 듣고 SRC 속성을 동적으로 전환하여 이미지 전환을 실현하는 것입니다. 이 기사는 일반적으로 사용되는 대화식 효과를 이해하고 마스터하는 데 도움이되는 자세한 코드 예제 및 설명을 제공합니다.

사전로드 스크립트에서 동적으로 생성 된 DOM 요소에 액세스하고 작동하는 방법 사전로드 스크립트에서 동적으로 생성 된 DOM 요소에 액세스하고 작동하는 방법 Aug 30, 2025 am 11:57 AM

이 기사에서는 JavaScript 스크립트가 웹 개발에서 DOM 요소를 생성하기 전에로드 및 실행될 때 JavaScript 스크립트에 효과적으로 액세스하고 조작 할 수있는 방법을 살펴 봅니다. 우리는 세 가지 핵심 전략을 소개합니다. 기능 반환 값을 통해 요소 참조를 직접 통과시키고, 모듈 간 통신을 달성하기 위해 사용자 정의 이벤트를 사용하고, 돌연변이 관상 서버를 사용하여 DOM 구조 변경을 듣습니다. 이러한 방법을 사용하면 개발자가 JavaScript 실행 타이밍과 동적 컨텐츠로드 사이의 과제를 해결할 수 있도록하여 스크립트가 드래그 가능하게 만드는 등 후속 추가 요소를 올바르게 작동시킬 수 있습니다.

JavaScript의 진화 : ES2023 이상의 모습 JavaScript의 진화 : ES2023 이상의 모습 Aug 29, 2025 am 12:18 AM

ES2023은 JavaScript의 성숙한 진화를 나타내는 여러 가지 실용적인 업데이트를 도입했습니다. 1.array.prototype.findlast () 및 FindlastIndex () 메소드는 배열 끝에서 검색을 지원하여 로그 처리 효율성 또는 구성의 효율성을 향상시킵니다. 2. Hashbang Syntax (#!/usr/bin/envnode)는 JavaScript 파일을 UNIX와 같은 시스템에서 직접 실행할 수 있습니다. 3.Error.cause는 오류 체인을 지원하여 예외 디버깅 기능을 향상시킵니다. 4. 약점 및 세트의 사양은 교차 엔진 일관성을 향상시킨다. 앞으로 데코레이터 (단계 3), 레코드 및 튜플 (

JavaScript에서 객체 속성을 업데이트하는 방법 JavaScript에서 객체 속성을 업데이트하는 방법 Sep 04, 2025 am 04:58 AM

알려진 이름;

See all articles