Saltar al contenido

¿Cómo puedo tomar una selección de marcadores con Leaflet.draw?

Encontramos la solución a esta contrariedad, o por lo menos eso creemos. Si presentas alguna pregunta puedes escribirlo en el apartado de preguntas y sin tardar

Solución:

La mayor parte de lo que desea se puede hacer fácilmente utilizando los métodos de utilidad de Leaflet. Si quieres hacer esto con una forma compleja como L.Polygon vas a necesitar algo como TurfJS

Para L.Circle necesitas calcular la distancia entre el centro del círculo y compararla con el radio:

var marker = new L.Marker(...),
    circle = new L.Circle(...);

var contains = circle.getLatLng().distanceTo(marker.getLatLng()) < circle.getRadius();

Para L.Rectangle necesitas recuperar su objeto de límites y usar el método contiene:

var marker = new L.Marker(...),
    rectangle = new L.Rectangle(...);

var contains = rectangle.getBounds().contains(marker.getLatLng());

Como se dijo para polígonos complejos, usaría Turf pero hay más bibliotecas y complementos por ahí. Aquí hay un ejemplo usando Turf's inside método. Toma una característica de polígono y punto GeoJSON como parámetros, así que tenga en cuenta la conversión:

var marker = new L.Marker(...),
    polygon = new L.Polygon(...);

var contains = turf.inside(marker.toGeoJSON(), polygon.toGeoJSON());

Puede envolverlos en métodos convenientes para cada clase respectiva:

L.Polygon.include(
    contains: function (latLng) 
        return turf.inside(new L.Marker(latLng).toGeoJSON(), this.toGeoJSON());
     
);

L.Rectangle.include(
    contains: function (latLng) 
        return this.getBounds().contains(latLng);
    
);

L.Circle.include(
    contains: function (latLng) 
        return this.getLatLng().distanceTo(latLng) < this.getRadius();
    
);

var marker = new L.Marker(...),
    polygon = new L.Polygon(...),
    rectangle = new L.Rectangle(...),
    circle = new L.Circle(...);

polygon.contains(marker.getLatLng());
rectangle.contains(marker.getLatLng());
circle.contains(marker.getLatLng());

Tenga en cuenta que si implementa el método del polígono, no es necesario el método del rectángulo. Dado que el rectángulo se extiende desde el polígono, heredará el método. Lo dejé allí para que estuviera completo.

Ahora iterar sus marcadores y compararlos es fácil:

map.on(L.Draw.Event.CREATED, function (e) 
    markers.eachLayer(function (marker) 
        if (!e.layer.contains(marker.getLatLng())) 
            marker.remove();
        
    );
);

Espero que te ayude, aquí tienes un fragmento de trabajo:

var map = new L.Map('leaflet', 
    'center': [0, 0],
    'zoom': 0
);

var markers = new L.LayerGroup().addTo(map);

for (var i = 0; i < 300; i++) 
    var marker = new L.Marker([
        (Math.random() * (90 - -90) + -90).toFixed(5) * 1,
        (Math.random() * (180 - -180) + -180).toFixed(5) * 1
    ]).addTo(markers);


new L.Control.Draw(
    draw: 
        marker   : false,
        polygon  : true,
        polyline : false,
        rectangle: true,
        circle   : 
            metric: 'metric'
        
    ,
    edit: false
).addTo(map);

L.Polygon.include(
    contains: function (latLng) 
        return turf.inside(new L.Marker(latLng).toGeoJSON(), this.toGeoJSON());
     
);

L.Rectangle.include(
    contains: function (latLng) 
        return this.getBounds().contains(latLng);
    
);

L.Circle.include(
    contains: function (latLng) 
        return this.getLatLng().distanceTo(latLng) < this.getRadius();
    
);

map.on(L.Draw.Event.CREATED, function (e) 
    markers.eachLayer(function (marker) 
        if (!e.layer.contains(marker.getLatLng())) 
            marker.remove();
        
    );
);
body 
    margin: 0;


html, body, #leaflet 
    height: 100%;


  
    Leaflet 1.0.3
    
    
    [email protected]/dist/leaflet.css" />
    
  
  
    

Gracias @ iH8 por el genial ejemplo. Fui más lejos para evitar alguna repetición con

markers.eachLayer(function (marker) 
    ...

y extendió las envolturas con métodos adicionales usando matrices de marcadores en su lugar:


Primero noté que un LayerGroup tiene un objeto con key-valores que contienen todos los marcadores. Simplemente uso ese objeto para crear un array de marcadores:

// In the on draw event
...
// Set an array containing all the markers
var markers = jsonToArray(layerGroup._layers); 
...

function jsonToArray(jsonObject) 
  var result = [];
  var keys = Object.keys(jsonObject);
  keys.forEach(function (key) 
    result.push(jsonObject[key]);
  );
  return result;

Luego reutilizo las envolturas con modificado contains() métodos :

  L.Rectangle.include(
    // Single marker case
    contains: function (marker) 
      return this.getBounds().contains(marker.getLatLng());
    ,
    // Array of markers
    contains: function (markers) 
      var markersContained = [];
      markers.forEach(marker => 
        markersContained.push(this.getBounds().contains(marker.getLatLng()));
      )
      return markersContained;
    
  );

  L.Circle.include(
    contains: function (marker) 
      return this.getLatLng().distanceTo(marker.getLatLng()) < this.getRadius();
    ,
    contains: function (markers) 
      var markersContained = [];
      markers.forEach(marker => 
        markersContained.push(this.getLatLng().distanceTo(marker.getLatLng()) < this.getRadius());
      )
      return markersContained;
    
  );

y finalmente en el evento de sorteo, verifico si mis marcadores están contenidos dentro o no:

  map.on(L.Draw.Event.CREATED, function (geometry) 
    // Set an array containing all the markers
    var markers = jsonToArray(layerGroup._layers);

    var result = geometry.layer.contains(markers);
    console.log('result => ', result);
  );

function jsonToArray(jsonObject) 
  var result = [];
  var keys = Object.keys(jsonObject);
  keys.forEach(function (key) 
    result.push(jsonObject[key]);
  );
  return result;


var map = new L.Map('leaflet', 
    'center': [0, 0],
    'zoom': 0
);

var layerGroup = new L.LayerGroup().addTo(map);

for (var i = 0; i < 10; i++) 
    var marker = new L.Marker([
        (Math.random() * (90 - -90) + -90).toFixed(5) * 1,
        (Math.random() * (180 - -180) + -180).toFixed(5) * 1
    ]).addTo(layerGroup);


new L.Control.Draw(
    draw: 
        marker   : false,
        polygon  : false,
        polyline : false,
        rectangle: true,
        circle   : 
            metric: 'metric'
        
    ,
    edit: false
).addTo(map);

// Define contains() method for each geometry
L.Rectangle.include(
  contains: function (marker) 
    return this.getBounds().contains(marker.getLatLng());
  ,
  contains: function (markers) 
    var markersContained = [];
    markers.forEach(marker => 
      markersContained.push(this.getBounds().contains(marker.getLatLng()));
    )
    return markersContained;
  
);

L.Circle.include(
  contains: function (marker) 
    return this.getLatLng().distanceTo(marker.getLatLng()) < this.getRadius();
  ,
  contains: function (markers) 
    var markersContained = [];
    markers.forEach(marker => 
      markersContained.push(this.getLatLng().distanceTo(marker.getLatLng()) < this.getRadius());
    )
    return markersContained;
  
);

map.on(L.Draw.Event.CREATED, function (geometry) 
  // Set an array containing all the markers
  var markers = jsonToArray(layerGroup._layers);

  var result = geometry.layer.contains(markers);
  console.log('result => ', result);
);
body 
    margin: 0;


html, body, #leaflet 
    height: 100%;


  
    Leaflet 1.0.3
    
    
    [email protected]/dist/leaflet.css" />
    
  
  
    

Recuerda que tienes permiso de valorar este tutorial .

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 3.5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *