Open layers supercluster integration - is it possible to fetch underlying features for each cluster?
I had to make some changes to the fiddle to get it running. What I changed:
- Use latest version of Supercluster (2.3.0) because it has a new function called
getLeaves
that you need (see 3.). - 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);
- 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).
It depends on what supercluster you are using. I assume it's the Mapbox supercluster, which lucky for you has implemented the method getLeaves() on 2017 Jan 18.
The method was implemented in particular for the purpose you are looking for ( you were not the first ask :-) ), and it was implemented with flexibility in mind as well (pagination).
The pull request also shows an in-detail explanation of the parameters of this function, I just copy them here for reference:
index.getLeaves(
clusterId, // cluster_id property of the clicked cluster
zoom, // zoom of the clicked cluster
limit, // how many points to return; 10 by default
offset); // how many points to skip for pagination; 0 by default
If you want to get all points in a cluster, either set limit
to Infinity
(yes, that's a valid value!), or use a negative value such as -1
.
If you try to retrieve large amount of point data (e.g. all 200k points in the example), you probably will have severe performance issues, plus you cannot sensibly display that information at once, either. Given your other example (showing details about a study represented by a point), you could use the additional parameters (limit, offset) to only request data as needed: Click on the cluster to open the popup/information, but only request a chunk of the data (e.g. the first ten studies), with the first being shown right away. Then, only when the user selects one of the other studies, do another request for the next chunk of studies. Not necessarily relevant to this question, but a quick introduction to pagination never hurts for stackexchange readers ;) : It's a great way to boost UX, with better performance allowing for sleeker ways to present data.
The relevant&merged pull request (My reputation limits me to only two links, so I had to "break" the link. Just add https:// in front):
github.com/mapbox/supercluster/pull/32
And if you want the background story of the pull request as well:
github.com/mapbox/mapbox-gl-js/issues/3318