Maison interface Web js tutoriel Création d'un tracé d'image XY interactif avec Google Apps Script et Leaflet.js

Création d'un tracé d'image XY interactif avec Google Apps Script et Leaflet.js

Sep 08, 2024 pm 10:35 PM

Google Maps propose de nombreuses fonctionnalités permettant de tracer des points sur une carte, mais que se passe-t-il si vous souhaitez tracer des points sur une image ? Ces cartes de tracé d'images XY sont couramment utilisées pour les plans d'étage, les inspections de chantier et même les jeux.

Dans ce guide, je vais vous montrer comment créer une carte interactive avec des points déplaçables à l'aide de Leaflet.js et de Google Apps Script. Nous couvrirons tout, de la configuration de la carte à l'intégration des données de Google Sheets et à son déploiement en tant qu'application Web.

Ce guide couvrira :

  • Configuration de Leaflet.js dans un service HTML Google Apps Script

  • Affichage des marqueurs à l'aide des données de Google Sheets

  • Mise à jour de la ligne des feuilles lorsqu'un marqueur est déplacé

  • Création de nouveaux marqueurs à partir de la carte et enregistrement dans Sheets

  • Supprimer un marqueur de l'application web

Configuration de Leaflet.js dans un service HTML de script Google Apps

Leaflet.js est l'une des bibliothèques de cartographie open source les plus populaires. Il est léger, facile à utiliser et dispose d'une excellente documentation. Ils prennent en charge une tonne de types de cartes différents, y compris "CRS.Simple" ou Coordonnées de référence, qui vous permet de fournir une image d'arrière-plan.

Configuration de Google Sheets

Commencez par créer une feuille nommée map_pin avec la structure suivante :

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

Then open Apps Script from the Extensions menu.

Creating HTML File

First, we'll start with the basic example from the Leaflet docs, just to get the library working. You can see the full example in their quick start guide, here.

Add a new HTML File named Index, and set the content to:

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

Then update the Code.gs file with:

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

Save, and then click Deploy, and publish as a web app. Then open the link for the new deployment and you should see Leaflet.js displaying a map on New York.

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

Ok, that's the regular map example using Leaflet. Now on to the CRS.Simple map type, which allows supplying a background image.

Update the HTML with this example from the Leaflet Tutorials.

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

Here we are supplying an image of 1000 x 1000 pixels, then setting the center marker at 500, 500.

Click Save, then Deploy>Test Deployments, to see the new map type. You should now have a map with a background image and a marker plotted in the center.

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

Initializing a Map with Data from Google Sheets

Next, we'll use data from the sheet to populate a set of markers on the map.

First, add a function to the Code.gs file to get the marker locations:

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
}

Here I'm returning the pins as JSON so they're easier to work with in the HTML in the next section.

Now add a function to the HTML to loop over this JSON and create the map pins after the map has loaded.

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

Save, and then open the test deployment. You should now have markers generated from your sheet data!

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

Each pin has a popup with the title from that row. The pins are draggable at this point, but we still need a function to save the new position.

Saving Marker Position When Dragged

To save the new position, we need two functions: one in the HTML to capture the event on the client side, and one to save the new position on the server side, in the Code.gs file.

Update the HTML with:

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

And then add a function to the Code.gs file to save the location:

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

Save, and refresh the test deployment. You should now see the sheet update when a marker is dragged!

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

Adding New Points

We can now move the existing points, but what about adding new ones? Again, we'll need two functions, one in the HTML, and one in the Code.gs file.

First, add a function to the HTML to open a prompt when the user clicks an empty spot on the map, and pass the value to a server function.

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

Then add the function to the Code.gs to save the new row.

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

Save once more and refresh the test deployment. Now when you click an empty spot, you can enter a title and save a new marker!

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

Deleting A Marker

Lastly, we should add a way to delete markers, giving us a full CRUD app in map view.

Update the add marker function to give the popup a delete button:

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

And then add a function for deleting from the client side:

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

Then add the matching function to the Code.gs file:

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

What's Next?

There's a ton more you could do from here, like adding other data points to each marker, dynamic background images, or other click and drag interactions. You could even make a game! Got an idea for a use case? Drop a comment below!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Stock Market GPT

Stock Market GPT

Recherche d'investissement basée sur l'IA pour des décisions plus intelligentes

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment sélectionnez-vous les éléments par un attribut de données dans JavaScript? Comment sélectionnez-vous les éléments par un attribut de données dans JavaScript? Aug 30, 2025 am 01:57 AM

Vous pouvez sélectionner des éléments avec des attributs de données dans JavaScript via le sélecteur d'attribut CSS et utiliser la méthode document.QuerySelector () ou document.QuerySelectorAll () pour y parvenir. 1. Utiliser [Data-Attribute] pour sélectionner un élément avec l'attribut de données spécifié (n'importe quelle valeur); 2. Utilisez [data-attribut = "Value"] pour sélectionner un élément dont la valeur d'attribut correspond exactement; 3. Accédez à l'attribut de données via Element.Dataset, où Data-User-ID correspond à DataSet.Userid (Remplacer

Pytest et sélénium: stratégies de mise en œuvre pour les tests dynamiques basés sur les données Pytest et sélénium: stratégies de mise en œuvre pour les tests dynamiques basés sur les données Aug 30, 2025 am 06:00 AM

Cet article vise à résoudre le problème selon lequel le décorateur de @ pytest.mark.Marametrise ne peut pas gérer directement les données générées lors de l'exécution lors de l'utilisation de PyTest et du sélénium pour des tests dynamiques basés sur les données. Nous explorerons les limites de pytest.mark.Parametrize en profondeur et introduirons en détail comment implémenter gracieusement les tests paramétrés en fonction de l'acquisition de données dynamiques de sélénium via la fonction de crochet Pytest_GenEReate_tests de Pytest pour assurer la flexibilité et l'efficacité des cas de test.

Optimiser la gestion des événements des sauts de liaison externe dynamique dans la fenêtre contextuelle jQuery Optimiser la gestion des événements des sauts de liaison externe dynamique dans la fenêtre contextuelle jQuery Sep 01, 2025 am 11:48 AM

Cet article vise à résoudre le problème de la redirection du bouton de redirection de liaison externe dans la fenêtre pop-up jQuery provoquant des erreurs de saut. Lorsqu'un utilisateur clique sur plusieurs liens externes successivement, le bouton Jump dans la fenêtre contextuelle peut toujours pointer vers le premier lien cliqué. La solution principale consiste à utiliser la méthode OFF ('Click') pour annuler l'ancien gestionnaire d'événements avant chaque liaison d'un nouvel événement, garantissant que le comportement de saut pointe toujours vers l'URL cible, réalisant ainsi une redirection de liens précise et contrôlable.

Créer des compteurs JavaScript en cours d'exécution par les jours ouvrables et les heures de travail Créer des compteurs JavaScript en cours d'exécution par les jours ouvrables et les heures de travail Aug 31, 2025 am 06:30 AM

Cet article détaille comment créer un compteur de synchronisation précis à l'aide de JavaScript. Le comptoir est incrémenté une fois par minute, mais ne se déroule que dans les jours ouvrables prédéfinis (du lundi au vendredi) et les heures de travail (comme 6 h à 20 h). Il peut interrompre les incréments pendant les heures de travail, mais afficher la valeur actuelle et réinitialiser automatiquement le premier jour de chaque mois, assurant la précision et la flexibilité de la logique de comptage.

JavaScript réalise l'effet de commutation d'image click-through: tutoriel professionnel JavaScript réalise l'effet de commutation d'image click-through: tutoriel professionnel Sep 18, 2025 pm 01:03 PM

Cet article présentera comment utiliser JavaScript pour réaliser l'effet de cliquer sur les images. L'idée principale est d'utiliser l'attribut Data- * de HTML5 pour stocker le chemin d'image alternatif et écouter des événements de clic via JavaScript, changez dynamiquement les attributs SRC, réalisant ainsi la commutation d'image. Cet article fournira des exemples de code et des explications détaillés pour vous aider à comprendre et à maîtriser cet effet interactif couramment utilisé.

Comment les éléments DOM créés dynamiquement sont accessibles et exploités par des scripts préchargés Comment les éléments DOM créés dynamiquement sont accessibles et exploités par des scripts préchargés Aug 30, 2025 am 11:57 AM

Cet article explore comment les scripts JavaScript peuvent être effectivement accessibles et manipulés lorsqu'ils sont chargés et exécutés avant la création d'éléments DOM dans le développement Web. Nous présenterons trois stratégies de base: passer directement les références d'élément via des valeurs de retour de fonction, en utilisant des événements personnalisés pour réaliser une communication intermodule et en utilisant MutationObserver pour écouter les changements de structure DOM. Ces méthodes peuvent aider les développeurs à résoudre les défis entre le synchronisation de l'exécution JavaScript et le chargement dynamique du contenu, garantissant que le script peut fonctionner correctement des éléments ajoutés par la suite, tels que les rendre glisserables.

L'évolution de JavaScript: un regard sur ES2023 et au-delà L'évolution de JavaScript: un regard sur ES2023 et au-delà Aug 29, 2025 am 12:18 AM

ES2023 a introduit un certain nombre de mises à jour pratiques, marquant l'évolution mature de JavaScript. 1.Array.prototype.Findlast () et FindLasTindex () Les méthodes prennent en charge la recherche à partir de la fin du tableau, améliorant l'efficacité des journaux ou configurations de traitement; 2.Hashbang Syntax (#! / Usr / bin / envNode) permet d'exécuter les fichiers JavaScript directement dans des systèmes de type Unix; 3.Error.Cause prend en charge les chaînes d'erreur, améliorant les capacités de débogage des exceptions; 4. Les spécifications des faibles et des ensembles améliorent la cohérence des moteurs transversales; À l'avenir, les décorateurs (stade3), les disques et les tuples (

Comment mettre à jour les propriétés des objets en javascript Comment mettre à jour les propriétés des objets en javascript Sep 04, 2025 am 04:58 AM

UsedotNotationToupDateProperties dans les noms de connaissances; 2.UsebracketnotationfordynAmicorSpecialCharacterPropertyNames; 3.UseObject.assign () ToupdateMultiplepropertiesormergeObjects, notedingitMutatestheoriginalSanempyObjectisSusedArfirStargUment; 4.usethesppyples

See all articles