Ajouter un écouteur d'événements sur un marqueur dans Leaflet

10

J'utilise Leaflet pour rendre une carte. J'ai créé une carte avec des marqueurs et je ne sais pas comment implémenter le Listener d'événements 'onClick' sur chaque marqueur.

Mon code

var stops = JSON.parse(json);
var map = new L.Map('map', {
  zoom: 12,
  minZoom: 12,
  center: L.latLng(41.11714, 16.87187)
});
map.addLayer(L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
  attribution: 'Map data',
  maxZoom: 18,
  id: 'mapbox.streets',
  accessToken: '-----'
}));
var markersLayer = new L.LayerGroup();
map.addLayer(markersLayer);


//populate map from stops
for (var i in stops) {
  L.marker(L.latLng(stops[i].Position.Lat, stops[i].Position.Lon), {
    title: stops[i].Description
  }).addTo(markersLayer).bindPopup("<b>" + stops[i].Description + "</b>").openPopup();
}

Exemple

map.on('click', function(e) {
    alert(e.latlng);
});

La brochure traite des écouteurs d'événements par référence, donc si vous voulez ajouter un écouteur puis le supprimer, définissez-le comme une fonction:

function onClick(e) { ... }

map.on('click', onClick);
map.off('click', onClick);
ilias ioannou
la source
Voir la réponse de @ TimoSperisen à cette question et le violon qu'il a posté Ça marche pour moi
Mawg dit réintégrer Monica

Réponses:

14

Bienvenue sur GIS Stack Exchange!

Il ne devrait pas y avoir de difficulté particulière à attacher un rappel à un événement de clic de marqueur (s). Vous utiliseriez simplement myMarker.on('click', callback)comme vous l'avez fait avec la carte. Vous devrez également le faire pour chaque marqueur auquel vous souhaitez attacher un rappel.

Une autre possibilité serait d'ajouter tous vos marqueurs dans un groupe d'entités (par exemple, instanciez simplement votre markersLayeravec L.featureGroup()au lieu de L.layerGroup()), afin de pouvoir attacher le rappel directement à ce groupe. Il recevra les événements de clic des marqueurs individuels et vous pouvez accéder à la fonction cliquée individuelle à l'aide de event.layer.

var markersLayer = L.featureGroup().addTo(map);

// populate map from stops…

markersLayer.on("click", function (event) {
    var clickedMarker = event.layer;
    // do some stuff…
});

Démo: http://jsfiddle.net/ve2huzxw/74/

Question similaire posée par quelqu'un d'autre sur le forum Leaflet: https://groups.google.com/forum/#!topic/leaflet-js/RDTCHuLvMdw

ghybs
la source
Juste pour ajouter, event.layer.propertiesvous aurez accès au tableau de toutes les propriétés (métadonnées) de vos marqueurs, selon le format GeoJSON. Vous pouvez donc assigner event.layer.properties.description = stops[i].Descriptionpar exemple.
Nikhil VJ
4

Modifiez la boucle de population de votre carte pour attribuer des propriétés à votre marqueur.

//populate map from stops
for (var i in stops) {
  var oneMarker = L.marker(L.latLng(stops[i].Position.Lat, stops[i].Position.Lon), {
    title: stops[i].Description
  }).bindPopup("<b>" + stops[i].Description + "</b>").openPopup();

  oneMarker.properies.name = stops[i].Name;
  oneMarker.properies.description = stops[i].Description;
  oneMarker.properies.othervars = stops[i].othervars;
  oneMarker.addTo(markersLayer);
}

Plus tard, pour accéder à ces propriétés (propriétés de fonction comme on les appelle) dans l'événement onclick,

markersLayer.on("click", markerOnClick);

function markerOnClick(e) {
  var attributes = e.layer.properties;
  console.log(attributes.name, attributes.desctiption, attributes.othervars);
  // do some stuff…
}

L' properties.varapproche a l'avantage supplémentaire de rendre votre marqueur au format GeoJson standard. Le rend compatible si, par exemple, vous devez exporter les données sous forme de fichier de formes, importer des marqueurs à partir de fichiers de formes, etc.

Nikhil VJ
la source
1
J'essaie d'incorporer votre suggestion dans ma propre configuration. Mais l'ajout d'un simple oneMarker.properties me donne un message d'erreur "oneMarker.properties n'est pas défini". J'oublie quelque chose d'évident ?? regards btw: vous avez mal orthographié les propriétés ........ propriétés dans votre exemple de code
alex
1
ah je pense avoir trouvé une solution: j'ai dû ajouter oneMarker.properties = {}; btw: est-il correct d'utiliser var oneMarker ou doit-il s'agir d'un nom dynamique?
alex
@alex bon à savoir sur le piratage des propriétés. Oui, c'est bien à utiliser var oneMarker- c'est une portée locale dans la boucle for, et la ligne layer.addTo () ajoute de la valeur. (comme: a=3; array1.push[a];va ajouter de la valeur 3au tableau, pas une référence à alui-même.)
Nikhil VJ
0

Un moyen assez simple et facile de créer un tableau de marqueurs cliquables dans un objet de carte de dépliant consiste à manipuler la liste des classes du marqueur créé en ajoutant un nom de classe incrémenté personnalisé à chaque marqueur. Il est ensuite facile de créer un écouteur et de savoir quel marqueur a été cliqué. En sautant l'actif ou non, chacun a un événement de clic récupérable avec un ID fiable.

  // creates markers, each with a leaflet supplied class
  if (length === 1) {
    for (i = 0; i < parks.length; ++i) {
      if (parks[i].parksNumber !== parks.parksNumber)
        L.marker([parks[i].latitude, parks[i].longitude], {
          icon: parks[i].iconMarker
        }).addTo(mymap);
    }
  }

  // select all of the leaflet supplied class
  let markers = document.querySelectorAll(".leaflet-marker-icon");

  // loop through those elements and first assign the indexed custom class
  for (i = 0; i < markers.length; ++i) {
    markers[i].classList.add("marker_" + parks[i].parksNumber);

    // then add a click listener to each one
    markers[i].addEventListener("click", e => {

      // pull the class list
      let id = String(e.target.classList);

      // pull your unique ID from the list, be careful cause this list could 
      // change orientation,  if so loop through and find it
      let parksNumber = id.split(" ");
      parksNumber = parksNumber[parksNumber.length - 1].replace("marker_", "");

      // you have your unique identifier to then do what you want with
      search_Number_input.value = parksNumber;
      HandleSearch();
    });
  }
Joel Mason
la source