How to make MarkerClusters use panes

1.1k views Asked by At

Let's say we have the following map:

https://jsfiddle.net/fcumj09w/5/

In the above example, we have 2 marker cluster groups (clustRed and clustYellow) and a single marker outside of these groups.

I want the red marker cluster group to be on top (higher z-index) of the yellow marker cluster group, when zooming out.

I have created 3 custom panes to attach each cluster group to a different pane but it seems like panes don't work with cluster groups (or I haven't find the way to make them work).

What I tried:

var clustRed = L.markerClusterGroup({pane:'hilevel'});
var clustYellow = L.markerClusterGroup({pane:'lowlevel'});

I can only make panes work with the single marker:

L.circleMarker([45,5],{pane:"midlevel"}).addTo(map); 

How can I make Leaflet.markercluster use the pane that I specify?

1

There are 1 answers

1
ghybs On BEST ANSWER

Note: this functionality is now available as clusterPane option. Added since version 1.1.0.

var clustRed = L.markerClusterGroup({clusterPane: 'hilevel'});

Although Layer Groups in Leaflet (including the MarkerClusterGroup from Leaflet.markercluster plugin) inherit from the Layer base class, which indeed provide the pane option, any child layer added to them still use their own specified pane, if any, or use the default one (i.e. overlayPane).

It is still undecided whether that behaviour should be changed or not (see Leaflet issue #4279).

In the case of a MarkerClusterGroup, the latter even actually generates markers on its own, using the L.MarkerCluster class, which represent a cluster of individual markers.

From your description, you would like those generated markers to be inserted in specific panes.

In that case, you could very simply override the initialize method of L.MarkerCluster class so that it uses whichever pane you want. In your case, you would read the MarkerClusterGroup' option pane member:

L.MarkerCluster.include({
  initialize: function(group, zoom, a, b) {

    var latLng = a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0),
      options = {
        icon: this
      },
      pane = group.options.pane; // Read the MarkerClusterGroup's pane, if any.

    // If a pane is specified, add it to the MarkerCluster's options.
    if (pane) {
      options.pane = pane;
    }

    L.Marker.prototype.initialize.call(this, latLng, options);

    // Remaining code is unchanged compared to original method.
    this._group = group;
    this._zoom = zoom;
    this._markers = [];
    this._childClusters = [];
    this._childCount = 0;
    this._iconNeedsUpdate = true;
    this._boundsNeedUpdate = true;
    this._bounds = new L.LatLngBounds();
    if (a) {
      this._addChild(a);
    }
    if (b) {
      this._addChild(b);
    }
  }
});

Once this is patched, the generated marker clusters will use the pane that you specify when instantiating the MarkerClusterGroup, as shown in your question:

var clustRed = L.markerClusterGroup({pane:'hilevel'});
var clustYellow = L.markerClusterGroup({pane:'lowlevel'});

Updated JSFiddle: https://jsfiddle.net/fcumj09w/9/