Evento de folleto: cómo propagar a capas superpuestas

3 minutos de lectura

avatar de usuario
kaveh

Digamos que tengo algunas capas superpuestas y cada capa tiene un evento de clic. Cuando hago clic en el mapa, me gustaría saber en qué capas se hace clic, aunque el evento de clic se detiene después de la primera capa y no se propaga a sus capas subyacentes. ¿Cómo puedo conseguir esto?

Aquí hay un violín de muestra y su código: https://jsfiddle.net/r0r0xLoc/

<div id="mapid" style="width: 600px; height: 400px;"></div>

<script>
  var mymap = L.map('mapid').setView([51.505, -0.09], 13);

  L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
    maxZoom: 18,
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
      '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
      'Imagery © <a href="http://mapbox.com">Mapbox</a>',
    id: 'mapbox.streets'
  }).addTo(mymap);

  L.polygon([
    [51.509, -0.08],
    [51.503, -0.06],
    [51.51, -0.047]
  ]).addTo(mymap).on('click', function() {
    console.log('clicked on 1st polygon')
  });

  L.polygon([
    [51.609, -0.1],
    [51.503, -0.06],
    [51.51, -0.047]
  ]).addTo(mymap).on('click', function() {
    console.log('clicked on 2nd polygon')
  });

</script>

Si hace clic en cada polígono, verá su mensaje relacionado. Si hace clic en la parte superpuesta, solo verá el mensaje del segundo polígono.

Tienes que escuchar directamente el mapa "click" evento y determinar “manualmente” qué capas contienen la posición en la que se hizo clic.

Puedes usar folleto-pepita complemento (punto en polígono) por ejemplo para esta determinación:

map.on("click", function (event) {
  var clickedLayers = leafletPip.pointInLayer(event.latlng, geoJSONlayerGroup);
  // Do something with clickedLayers
});

Manifestación: https://jsfiddle.net/ve2huzxw/526/ (escuchar "mousemove" en vez de "click")

  • Al final utilicé el mismo enfoque y escuché hacer clic en eventos en el mapa mismo. no he probado leaflet-pip; en su lugar, utilicé turfjs/inside para determinar si la capa contiene el punto en el que se hizo clic. Aún así, creo que es lógico suponer que el evento debería propagarse a todas las capas.

    – kaveh

    28 de marzo de 2017 a las 16:48

  • Solo una nota al margen, esas son excelentes sugerencias. Desafortunadamente, esto no ayuda cuando tus capas son líneas simples.

    – Keul

    28 de enero de 2019 a las 10:48

Hay un complemento de folleto para propagar eventos a las capas subyacentes: https://github.com/danwild/leaflet-event-forwarder

Puede usarlo en su javascript para habilitar el reenvío de eventos, por ejemplo:

const myEventForwarder = new L.eventForwarder({
  map: map,
  events: {click: true, mousemove: false}
});

El problema es el orden en que se agregan las capas (geometrías). En mi caso, tenía una matriz de geometrías y lo que hice fue ordenar la matriz de geometrías usando sus límites L.LatLngBounds#containspor lo que si una geometría contiene otra, debe agregarse más tarde.

var geometries = [layerOne, layerTwo, ...];
geometries
  .sort((a, b) => {
    // in my case a separate function is required because the geometry could be a Circle, Rectangle, Polygon or Marker
    // and the methods to get the corresponding bounds are different.
    var boundsA = this.getBoundsFromGeometry(a);
    var boundsB = this.getBoundsFromGeometry(b);
    // if the second geometry contains the first, the order must be change so the layers don't overlap
    return boundsB.contains(boundsA) ? 1 : -1;
  })
  .forEach(l => this.map.addLayer(l));

Para mi la solución fue usar la opción interactive: false al crear la capa superior:

 var options = {
       style: feature => this.__determineStyle(feature),
       interactive: false,
 };

 var overlay = L.geoJson(geoJsonData, options);
 overlay.addTo(this.map);

https://leafletjs.com/reference-1.0.3.html#capa-interactiva

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad