Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Leaflet : ordering GeoJSON elements inside a layer

I'm displaying a GeoJSON layer using leaflet, with the pointToLayer function. Everything works ok so far.

But I would like to display my points in a certain order, based on a property of the GeoJSON. This is important because the radiuses of my points varies with this property, and I need to display the smaller circles on top. I hope I make myself clear.

I've tried many things, but here's what I think is my best try :

var pointLayer = L.geoJson(centroids, {
                pointToLayer: function (feature, latlng) {
                    return L.circleMarker(latlng, {
                        fillColor: "#76C551",
                        color: "#000",
                        weight: 1,
                        fillOpacity: 1
                    });
                },
                onEachFeature: function (feature, layer) {
                    var radius = calcPropRadius(feature.properties.nb);
                    layer.setRadius(radius);
                    feature.zIndexOffset = 1/feature.properties.nb*1000;
                    layer.bindPopup(feature.properties.name + " : " + String(feature.zIndexOffset));
                }
            });

You can notice that the zIndexOffset of features can be read in the popups, and they look ok. But the displaying order of the circles doesn't reflect the zIndexOffset. I've tried using the setZIndexOffset method, but as I understand it it works only with markers.

Does anyone know how to do this ? Thanks a lot for any insight !

like image 972
J. Pierson Avatar asked Aug 23 '16 13:08

J. Pierson


1 Answers

Whereas ghybs answer works perfectly for leaflet 0.7, switching to leaflet 1.0 allows the use of panes which makes for an easier solution :

var pointLayer = L.geoJson(centroids, {
            pointToLayer: function (feature, latlng) {
                return L.circleMarker(latlng, {
                    fillColor: "#76C551",
                    color: "#000",
                    weight: 1,
                    fillOpacity: 1
                });
            },
            onEachFeature: function (feature, layer) {
                var radius = calcPropRadius(feature.properties.nb);
                layer.setRadius(radius);
                layer.setStyle({pane: 'pane'+ feature.properties.nb});
                var currentPane = map.createPane('pane' + feature.properties.nb);
                currentPane.style.zIndex = Math.round(1/feature.properties.nb*10000);
                layer.bindPopup(feature.properties.name + " : " + String(feature.zIndexOffset));
            }
        });

Hope it can be of use to someone else !

like image 172
J. Pierson Avatar answered Sep 20 '22 04:09

J. Pierson