Leaflet: How to toggle GeoJSON feature properties

2020-03-07 06:47发布

问题:

I have a single GeoJSON object that contains over 2000+ features and each feature is part of one category (i.e. "Electrical", "Military", etc). There are a total of about 38 categories.

Here's the schema example of my collection:

{"type":"Feature","properties":{"category":"Electrical","Name":"Plant No 1"},"geometry":{"type":"Point","coordinates":[81.73828125,62.59334083012024]}},{"type":"Feature","properties":{"category":"Electrical","Name":"Plane No 2"},"geometry":{"type":"Point","coordinates":[94.5703125,58.722598828043374]}},{"type":"Feature","properties":{"category":"Military","Name":"Base 1"},"geometry":{"type":"Point","coordinates":[104.4140625,62.91523303947614]}}

Here's my L.geoJson function that iterates through the collection:

var allPoints = L.geoJson(myCollection, {
    onEachFeature: function(feature, layer){
        layer.bindPopup(L.Util.template(popTemplate, feature.properties));
    },
    "stylel": function(feature){
        return { "color": legend[feature.properties.category]
    }
}}).addTo(map);

How can I assign each category property to my L.control function so the user can toggle on/off the various categories from the collection? I could do this if I made each category a dataset and an individual geoJSOn layer, but that's too much work to do all 38 categories.

My attempt:

L.control.layers({
    'Street Map': L.mapbox.tileLayer('mapbox.streets').addTo(map)
},{
    'Electrical': myCollection[feature.properties.category["Electrical"]],
    'Military': myCollection[feature.properties.category["Military"]]
});

Is there a better way to do this? Thanks!

回答1:

You can simply assign your layers within the onEachFeature function. You could even automate the creation of Layer Groups for each category.

Result:

var categories = {},
    category;

function onEachFeature(feature, layer) {
    layer.bindPopup(L.Util.template(popTemplate, feature.properties));
    category = feature.properties.category;
    // Initialize the category array if not already set.
    if (typeof categories[category] === "undefined") {
        categories[category] = [];
    }
    categories[category].push(layer);
}

// Use function onEachFeature in your L.geoJson initialization.

var overlays = {},
    categoryName,
    categoryArray;

for (categoryName in categories) {
    categoryArray = categories[categoryName];
    overlays[categoryName] = L.layerGroup(categoryArray);
}

L.control.layers(basemaps, overlays).addTo(map);

EDIT: replaced overlays to be a mapping instead of an array.



回答2:

Iterate your GeoJSON collection and create multiple L.GeoJSON layers, one per category and add them as overlays to your L.Control.Layers instance.

var controlLayers = L.control.layers({
    'Street Map': L.mapbox.tileLayer('mapbox.streets').addTo(map)
}).addTo(map);

// Object to store category layers
var overlays = {};

// Iterate the collection
collection.features.forEach(function (feature) {

    var category = feature.properties.category;

    // Check if there's already an overlay for this category
    if (!overlays[category]) {

        // Create and store new layer in overlays object
        overlays[category] = new L.GeoJSON(null, {
            'onEachFeature': function () {},
            'style': function () {}
        });

        // Add layer/title to control
        controlLayers.addOverlay(overlays[category], category); 
    }

    // Add feature to corresponding layer
    overlays[category].addData(feature);
});

Here's an example on Plunker: http://plnkr.co/edit/Zv2xwv?p=preview