Leaflet / Leaflet.VectorGrid

Display gridded vector data (sliced GeoJSON or protobuf vector tiles) in Leaflet 1.0.0
598 stars 194 forks source link

Filter polygons with VectorGrid #153

Closed soli004 closed 5 years ago

soli004 commented 6 years ago

I have this large polygon geojson with population data. I want to filter to show only the polygons I want. The below script does not work, it still show all with no filter. Any suggestion how it should be done?

Thanks.

var tatort_omr = new L.layerGroup();

$.getJSON("../data/tatort.geojson", function(json) {
    var vectorGrid =  L.vectorGrid.slicer(json, {
        maxZoom: 20,
        rendererFactory: L.svg.tile,
        vectorTileLayerStyles: {
            sliced: {
                weight: 1,
                color: 'brown',
                opacity: 0.8,
                fill: true,
                fillColor: 'brown',
                stroke: true,
                fillOpacity: 0.6
            } 
        },
        interactive: true,
        polyToLayer: function(feature, latlng) {
            var pop = feature.properties.BEF;
            var num;
            // Filter between population of 50 000 to 100 000
            if (pop >= 50000 && pop <= 100000) {
                num = L.vectorGrid.slicer(json);
            } else {
                num = null
            }
            return num;
        }
    }) 
    .on('click', function(e) {
        var properties = e.layer.properties;
        L.popup()
            .setContent(
                "<b>CityName</b>: " + properties.TATORT +
                "<br><b>Population</b>: " + properties.BEF + '.st'
            )
            .setLatLng(e.latlng)
            .openOn(map);
    })
    vectorGrid.addTo(tatort_omr)
})
JamesLMilner commented 6 years ago

@soli004 please can you remember to use JavaScript code formatting when you post code? See this guide.

You create tiles from geojson the layer name defaults to 'sliced'. This you can style with a function, so you could do something like this to hide the polygons that don't have the correct population:

L.vectorGrid.slicer(geoJsonDocument, {
   vectorTileLayerStyles: {
      sliced: function(properties, zoom) {
            var pop = properties.pop;
            if (pop >= 50000 && pop <= 100000) {
                return {
                    weight: 1,
                    color: 'brown',
                    opacity: 0.8,
                    fill: true,
                    fillColor: 'brown',
                    stroke: true,
                    fillOpacity: 0.6
                }
            } else {
                return {
                    fillOpacity: 0,
                    stroke: false,
                    fill: false,
                    opacity: 0,
                    weight: 0,
                }
            }
       }
    }
}).addTo(map);
soli004 commented 6 years ago

@JamesMilnerUK Excellent it works perfect!!! I only got one more question.

If you want to filter many and have them each as its own layer group instead of writing this code for each filter with the change of population and the layer group name. I'm thinking that the better practice would be to use just one .js file instead of many (performance gain) and put all the layerGroup names into the LayerControl. Something similar like this example below.... Is this totally wrong way of thinking? How should I proceed with this?

var pop_less_2 = new L.layerGroup();
var pop_2_5 = new L.layerGroup();
var pop_5_10 = new L.layerGroup();
var pop_10_20 = new L.layerGroup();
var pop_20_30 = new L.layerGroup();
var pop_30_50 = new L.layerGroup();
var pop_50_100 = new L.layerGroup();
var pop_more_100 = new L.layerGroup();
L.vectorGrid.slicer(geoJsonDocument, {
   vectorTileLayerStyles: {
      sliced: function(properties, zoom) {
            var pop = properties.pop;
            if (pop <= 2000) {
                return {pop_less_2, style: 'brown'}
            else if (pop >= 2000 && pop <= 5000) {
                return {pop_2_5, style: 'brown'}
            else if (pop >= 5000 && pop <= 10000) {
                return {pop_5_10, style: 'brown'}
            else if (pop >= 10000 && pop <= 20000) {
                return {pop_10_20, style: 'brown'}
            else if (pop >= 20000 && pop <= 30000) {
                return {pop_20_30, style: 'brown'}
            else if (pop >= 30000 && pop <= 50000) {
                return {pop_30_50, style: 'brown'}
            else if (pop >= 50000 && pop <= 100000) {
                return {pop_50_100, style: 'brown'}
            else if (pop >= 100000) {
                return {pop_more_100, style: 'brown'}

.........

L.control.layers({'Population' : pop_less_2, 'Population': pop_2_5.... etc