OpenLayers Supercluster Integration – Fetch Underlying Features for Each Cluster

clusteringopenlayersperformance

I am using the open layers 3 with supercluster at the moment, extending the example provided here : https://jsfiddle.net/d5gwvz2y/2/

My question is: How does one fetch all the underlying features behind a cluster if clicked? In open layers cluster implementation you could use cluster forEachFeature, or just getFeatures.

Here is a sample of the clusters working using default cluster implementation http://www.wwarn.org/surveyor/NMFI/ when a cluster is clicked, an array of features are returned, which can then be iterated through.

Best Answer

I had to make some changes to the fiddle to get it running. What I changed:

  1. Use latest version of Supercluster (2.3.0) because it has a new function called getLeaves that you need (see 3.).
  2. Create a FeatureCollection (to have the advantage of identifying features by properties - e.g. name) and load it with supercluster:
var count = 200000;

// create featurecollection
var featureCollection = {
  "type": "FeatureCollection",
  "features": []
};

// add features to featurecollection
for (var i = 0; i < count; ++i) {
    var feature = {
    "type": "Feature",
    "properties": {
      "name": "point_"+i
    },
        "geometry": {
            "type": "Point",
            "coordinates": [(Math.random() * (-78.31801021112759 + 74.65681636347132) - 74.65681636347132).toFixed(10), (Math.random() * (37.92771687103033 - 39.366988155008926) + 39.366988155008926).toFixed(10)]
        }
    };
    featureCollection.features.push(feature);
}

// create supercluster
var index = supercluster({
    radius: 100,
    maxZoom: 16
});
index.load(featureCollection.features);
  1. Use getLeaves(clusterId, clusterZoom, limit = 10, offset = 0) in your select event (as described in the supercluster project):
selectSingleClick.on('select', function (selectEvent) {
  // get selected feature
  var feature = selectEvent.selected[0];
  // get parameter to call getLeaves
  var zoom = map.getView().getZoom();
  var clusterId = feature.get("cluster_id");
  // get features in cluster
  var featuresInCluster = index.getLeaves(clusterId, zoom, Infinity, 0);

  // iterate over features (NO ol.Feature objects!)
  for(let clusterObj of featuresInCluster){
    // do stuff with your feature!
  }
});

Have a look at this working JSFiddle.

EDIT: I updated the JSFiddle to fit the question requirements of looping through the resulting child elements...

Note that you do not access features in the cluster as ol.Feature objects because the access is realized with supercluster not openlayers! If necessary you could access the features in openlayers by searching for certain properties to identify the feature (e.g. name property in the provided JSFiddle).

Related Question