How to simultaneously add new markers and remove old markers associated with polygon clicks in leaflet

旧巷老猫 提交于 2021-02-19 01:32:05

问题


I have a map with Geojson polygons where each polygon is identified by a unique ID. I have a separate Geojson of point markers where each point is associated with a polygon with the same polygon ID, as well as a unique identifier for each individual point.

The initial map display is of only polygons. Each polygon click will display the points that are associated with the clicked polygon. When a new polygon is clicked, I want to plot the points associated with the new polygon while simultaneously removing the previously plotted points. So each time the user clicks a polygon, ONLY points within that polygon are ever displayed.

Here is some minimally reproducible code: https://jsfiddle.net/3v7hd2vx/1146/

var polys = {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#555555",
        "fill-opacity": 0.5,
        "polygon": "one"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -87.33032226562499,
              37.90953361677018
            ],
            [
              -85.374755859375,
              37.90953361677018
            ],
            [
              -85.374755859375,
              39.036252959636606
            ],
            [
              -87.33032226562499,
              39.036252959636606
            ],
            [
              -87.33032226562499,
              37.90953361677018
            ]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#555555",
        "fill-opacity": 0.5,
        "polygon": "two"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -85.3857421875,
              37.90953361677018
            ],
            [
              -83.3642578125,
              37.90953361677018
            ],
            [
              -83.3642578125,
              39.04478604850143
            ],
            [
              -85.3857421875,
              39.04478604850143
            ],
            [
              -85.3857421875,
              37.90953361677018
            ]
          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#555555",
        "fill-opacity": 0.5,
        "polygon": "three"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -87.34130859375,
              36.90597988519294
            ],
            [
              -83.3642578125,
              36.90597988519294
            ],
            [
              -83.3642578125,
              37.91820111976663
            ],
            [
              -87.34130859375,
              37.91820111976663
            ],
            [
              -87.34130859375,
              36.90597988519294
            ]
          ]
        ]
      }
    }
  ]
}; 
var pts = {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "id": "one",
        "animal": "bear"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -86.72607421875,
          38.77121637244273
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "id": "one",
        "animal": "fish"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -86.583251953125,
          38.487994609214795
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "id": "two",
        "animal": "tiger"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -84.276123046875,
          38.38472766885085
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "id": "two",
        "animal": "lizard"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -85.067138671875,
          38.70265930723801
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "id": "three",
        "animal": "dog"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -83.880615234375,
          37.483576550426996
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "marker-color": "#7e7e7e",
        "marker-size": "medium",
        "marker-symbol": "",
        "id": "three",
        "animal": "horse"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          -85.93505859374999,
          37.709899354855125
        ]
      }
    }
  ]
};

var map = L.map("map", {
    center: [37.5, -85], 
  zoom: 7
});
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png").addTo(map);

var defaultStyle = {
  fillColor: "whitesmoke", 
  color: "#171717", 
  fillOpacity: 1, 
  weight: 1
};

// create polygon geojson, add to map 
var polyJson = L.geoJson(polys, defaultStyle).addTo(map);

// empty layer group to add markers to 
var layerGroup = L.layerGroup();

// loop through polygon layers for events
polyJson.eachLayer(function(layer){

    // zoom to bbox on each polygon click
    layer.on("click", function(e){
    var bbox = e.target.getBounds();
    var sw = bbox.getSouthWest();
    var ne = bbox.getNorthEast();
    map.fitBounds([sw, ne]);

    // the clicked polygon identifier 
    var clickedPoly = e.target.feature.properties.polygon;

    // pts added to map when they match the clickedpoly id
    L.geoJson(pts, {
        pointToLayer: function(feature, latlng){
        if(feature.properties.id === clickedPoly){

           var clicked = L.circleMarker(latlng, { 
             color: "red"
           }).addTo(map).addTo(layerGroup);
        }
      }
    });
  });
});

polyJson.on("click", function(){
    if(map.hasLayer(layerGroup)){
    map.removeLayer(layerGroup);
  }else{
    map.addLayer(layerGroup);
    //layerGroup.removeLayers();
  }
});

In this example, the entire layerGroup of points is removed every other click based on the conditional statement at the end of the code block. But each new click continues to append markers to the layerGroup, so ALL selected markers are displayed every other click.

My inclination is to have each "group" of markers named by the polygon that they lie within, so when displayed markers do not match the currently clicked polygon ID, they will be removed both from the map AND from the layerGroup. I've worked extensively with Leaflet in R, but I'm not sure how to accomplish this in JS (or if the logic is even the same in the different languages). I can't manually define each layer because I'll be iterating through many dynamically loaded polygons and points.


回答1:


One simple way to fill your layer with teh desired points would be to:

  • make your layerGroup a permanent layer,
  • empty this layer when the user clicks on a polygon with layerGroup.clearLayers()
  • fill layerGroup with the valid markers (determined by the filter property) and let Leaflet handle the markers without interfering with pointToLayer.

Basically, simplify things:).

For example:

layer.on("click", function(e){
    var bbox = e.target.getBounds();
    var sw = bbox.getSouthWest();
    var ne = bbox.getNorthEast();
    map.fitBounds([sw, ne]);

    // the clicked polygon identifier 
    var clickedPoly = e.target.feature.properties.polygon;

    layerGroup.clearLayers();
    layerGroup.addLayer(L.geoJson(pts, {
        pointToLayer: function(feature, latlng){
            return L.circleMarker(latlng, { 
                color: "red"
            });
        },
        filter: function (feature) {
            return feature.properties.id === clickedPoly;
        }
    }));
});

And a demo https://jsfiddle.net/3v7hd2vx/1147/



来源:https://stackoverflow.com/questions/50295792/how-to-simultaneously-add-new-markers-and-remove-old-markers-associated-with-pol

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!