使用 Google Apps Script 和 Leaflet.js 构建交互式 XY 图像图

随笔2个月前发布 葛存
34 0 0

Google 地图有大量在地图上绘制点的功能,但是如果您想在图像上绘制点怎么办?这些 XY 图像绘制地图通常用于楼层地图、工地检查,甚至游戏。

在本指南中,我将向您展示如何使用 Leaflet.js 和 Google Apps Script 创建带有可拖动点的交互式地图。我们将介绍从设置地图到集成 Google 表格中的数据以及将其部署为 Web 应用的所有内容。

本指南将涵盖:

在 Google Apps Script HTML 服务中设置 Leaflet.js

使用 Google 表格中的数据显示标记

移动标记时更新表格行

从地图创建新标记并保存到表格

从 Web 应用程序中删除标记

在 Google Apps Script HTML 服务中设置 Leaflet.js

Leaflet.js是最流行的开源地图库之一。它轻量、易用,并且文档丰富。它们支持大量不同的地图类型,包括“ CRS.Simple ”或坐标参考系统,允许您提供背景图像。

Google 表格设置

冷库厂家 www.cqzlsb.com

首先创建一张map_pin具有以下结构的工作表:

ID 标题
1 测试1 10 三十
2 测试2 50 80

然后从扩展菜单打开 Apps 脚本。

创建 HTML 文件

首先,我们将从 Leaflet 文档中的基本示例开始,以使该库正常运行。您可以在他们的快速入门指南中看到完整的示例,点击此处。

添加一个新的 HTML 文件,命名为 Index,并将内容设置为:

复制

复制

<!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 显示纽约的地图。

使用 Google Apps Script 和 Leaflet.js 构建交互式 XY 图像图

好的,这是使用 Leaflet 的常规地图示例。现在介绍 CRS.Simple 地图类型,它允许提供背景图像。

使用 Leaflet 教程中的示例更新 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

点击“保存”,然后点击“部署”>“测试部署”,查看新的地图类型。现在您应该有一张带有背景图像且在中心绘制有标记的地图。

使用 Google Apps Script 和 Leaflet.js 构建交互式 XY 图像图

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

保存,然后打开测试部署。现在您应该已经从工作表数据生成了标记!

使用 Google Apps Script 和 Leaflet.js 构建交互式 XY 图像图

每个图钉都有一个弹出窗口,其中包含该行的标题。此时图钉是可拖动的,但我们仍需要一个函数来保存新位置。

拖动时保存标记位置

为了保存新位置,我们需要两个函数:一个在 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; } } } 

保存并刷新测试部署。现在,当标记被拖动时,您应该会看到工作表更新!

使用 Google Apps Script 和 Leaflet.js 构建交互式 XY 图像图

添加新点

我们现在可以移动现有的点,但如何添加新的点呢?同样,我们需要两个函数,一个在 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; } 

再次保存并刷新测试部署。现在,当您单击空白处时,您可以输入标题并保存新标记!

使用 Google Apps Script 和 Leaflet.js 构建交互式 XY 图像图

删除标记

最后,我们应该添加一种删除标记的方法,以便在地图视图中为我们提供完整的 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; } } } 

下一步是什么?

您还可以在这里做很多事情,例如向每个标记添加其他数据点、动态背景图像或其他点击和拖动交互。您甚至可以制作游戏!有用例的想法吗?在下面发表评论!

10

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...