Rumah > Artikel > hujung hadapan web > Membina Plot Imej XY Interaktif dengan Skrip Google Apps dan Leaflet.js
Google 지도에는 지도에 지점을 표시하는 다양한 기능이 있지만 이미지에 지점을 표시하려면 어떻게 해야 할까요? 이러한 XY 이미지 플롯 맵은 평면도, 작업 현장 검사, 심지어 게임에도 일반적으로 사용됩니다.
이 가이드에서는 Leaflet.js 및 Google Apps Script를 사용하여 드래그 가능한 지점이 있는 대화형 지도를 만드는 방법을 보여 드리겠습니다. 지도 설정부터 Google Sheets의 데이터 통합, 웹 앱 배포까지 모든 과정을 다룹니다.
이 가이드에서는 다음 내용을 다룹니다.
Google Apps Script HTML 서비스에서 Leaflet.js 설정
Google 스프레드시트의 데이터를 사용하여 마커 표시
마커 이동 시 시트 행 업데이트
지도에서 새 마커를 만들고 시트에 저장
웹 앱에서 마커 삭제
Leaflet.js는 가장 인기 있는 오픈 소스 매핑 라이브러리 중 하나입니다. 가볍고 사용하기 쉬우며 훌륭한 문서가 포함되어 있습니다. 배경 이미지를 제공할 수 있는 "CRS.Simple" 또는 좌표 참조 시스템을 포함하여 다양한 지도 유형을 지원합니다.
다음 구조를 사용하여 map_pin이라는 시트를 생성하여 시작합니다.
id | title | x | y |
---|---|---|---|
1 | test1 | 10 | 30 |
2 | test2 | 50 | 80 |
Kemudian buka Skrip Aplikasi daripada menu Sambungan.
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.
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.
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!
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.
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!
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!
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; } } }
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!