Rumah  >  Artikel  >  hujung hadapan web  >  Membina Plot Imej XY Interaktif dengan Skrip Google Apps dan Leaflet.js

Membina Plot Imej XY Interaktif dengan Skrip Google Apps dan Leaflet.js

WBOY
WBOYasal
2024-09-08 22:35:08894semak imbas

Google 지도에는 지도에 지점을 표시하는 다양한 기능이 있지만 이미지에 지점을 표시하려면 어떻게 해야 할까요? 이러한 XY 이미지 플롯 맵은 평면도, 작업 현장 검사, 심지어 게임에도 일반적으로 사용됩니다.

이 가이드에서는 Leaflet.js 및 Google Apps Script를 사용하여 드래그 가능한 지점이 있는 대화형 지도를 만드는 방법을 보여 드리겠습니다. 지도 설정부터 Google Sheets의 데이터 통합, 웹 앱 배포까지 모든 과정을 다룹니다.

이 가이드에서는 다음 내용을 다룹니다.

  • Google Apps Script HTML 서비스에서 Leaflet.js 설정

  • Google 스프레드시트의 데이터를 사용하여 마커 표시

  • 마커 이동 시 시트 행 업데이트

  • 지도에서 새 마커를 만들고 시트에 저장

  • 웹 앱에서 마커 삭제

Google Apps Script HTML 서비스에서 Leaflet.js 설정

Leaflet.js는 가장 인기 있는 오픈 소스 매핑 라이브러리 중 하나입니다. 가볍고 사용하기 쉬우며 훌륭한 문서가 포함되어 있습니다. 배경 이미지를 제공할 수 있는 "CRS.Simple" 또는 좌표 참조 시스템을 포함하여 다양한 지도 유형을 지원합니다.

Google 스프레드시트 설정

다음 구조를 사용하여 map_pin이라는 시트를 생성하여 시작합니다.

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

Kemudian buka Skrip Aplikasi daripada menu Sambungan.

Mencipta Fail HTML

Mula-mula, kita akan mulakan dengan contoh asas daripada dokumen Risalah, hanya untuk membolehkan perpustakaan berfungsi. Anda boleh melihat contoh penuh dalam panduan permulaan pantas mereka, di sini.

Tambahkan Fail HTML baharu bernama Index, dan tetapkan kandungannya kepada:

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

Kemudian kemas kini fail Code.gs dengan:

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

Simpan, kemudian klik Gunakan, dan terbitkan sebagai apl web. Kemudian buka pautan untuk penempatan baharu dan anda akan melihat Leaflet.js memaparkan peta di New York.

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

Ok, itu contoh peta biasa menggunakan Risalah. Sekarang beralih kepada jenis peta CRS.Simple, yang membolehkan membekalkan imej latar belakang.

Kemas kini HTML dengan contoh ini daripada Tutorial Risalah.

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

Di sini kami membekalkan imej 1000 x 1000 piksel, kemudian menetapkan penanda tengah pada 500, 500.

Klik Simpan, kemudian Gunakan>Ujian Penggunaan, untuk melihat jenis peta baharu. Anda kini sepatutnya mempunyai peta dengan imej latar belakang dan penanda diplot di tengah.

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

Memulakan Peta dengan Data daripada Helaian Google

Seterusnya, kami akan menggunakan data daripada helaian untuk mengisi set penanda pada peta.

Mula-mula, tambahkan fungsi pada fail Code.gs untuk mendapatkan lokasi penanda:

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
}

Di sini saya mengembalikan pin sebagai JSON supaya lebih mudah digunakan dalam HTML di bahagian seterusnya.

Sekarang tambahkan fungsi pada HTML untuk menggelungkan JSON ini dan mencipta pin peta selepas peta dimuatkan.

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

Simpan, dan kemudian buka penggunaan ujian. Anda kini sepatutnya mempunyai penanda yang dijana daripada data helaian anda!

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

Setiap pin mempunyai pop timbul dengan tajuk daripada baris itu. Pin boleh diseret pada ketika ini, tetapi kami masih memerlukan fungsi untuk menyimpan kedudukan baharu.

Menyimpan Kedudukan Penanda Apabila Diseret

Untuk menyimpan kedudukan baharu, kami memerlukan dua fungsi: satu dalam HTML untuk menangkap acara pada bahagian klien dan satu untuk menyimpan kedudukan baharu pada bahagian pelayan, dalam fail Code.gs.

Kemas kini HTML dengan:

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

Dan kemudian tambahkan fungsi pada fail Code.gs untuk menyimpan lokasi:

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

Simpan dan muat semula penggunaan ujian. Anda kini sepatutnya melihat kemas kini helaian apabila penanda diseret!

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

Menambah Mata Baharu

Kami kini boleh mengalihkan mata sedia ada, tetapi bagaimana pula dengan menambah yang baharu? Sekali lagi, kami memerlukan dua fungsi, satu dalam HTML dan satu dalam fail Code.gs.

Mula-mula, tambahkan fungsi pada HTML untuk membuka gesaan apabila pengguna mengklik tempat kosong pada peta dan menghantar nilai kepada fungsi pelayan.

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

Kemudian tambahkan fungsi pada Code.gs untuk menyimpan baris baharu.

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

Simpan sekali lagi dan muat semula penggunaan ujian. Kini apabila anda mengklik tempat kosong, anda boleh memasukkan tajuk dan menyimpan penanda baharu!

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

Memadam Penanda

Akhir sekali, kami harus menambah cara untuk memadamkan penanda, memberikan kami apl CRUD penuh dalam paparan peta.

Kemas kini fungsi penanda tambah untuk memberi pop timbul butang padam:

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

Dan kemudian tambah fungsi untuk memadam dari sisi klien:

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

Kemudian tambahkan fungsi padanan pada fail 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;
    }
  }
}

Apa Seterusnya?

Ada banyak lagi yang boleh anda lakukan dari sini, seperti menambahkan titik data lain pada setiap penanda, imej latar belakang dinamik atau interaksi klik dan seret yang lain. Anda juga boleh membuat permainan! Ada idea untuk use case? Tinggalkan komen di bawah!

Atas ialah kandungan terperinci Membina Plot Imej XY Interaktif dengan Skrip Google Apps dan Leaflet.js. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn