11

I use Mapbox GL JS and get a trouble with cluster. I add some layers I want to get a list of clustered points by click on cluster.

map.on('click', function(e) {
    var cluster = map.queryRenderedFeatures(e.point, { layers: ["cluster"] });

    if (cluster.length) {
        // get clustered points here
        console.log(cluster[0]);
    }
});

Work example on jsfiddle https://jsfiddle.net/L3hm8rur/

4 Answers4

30

The feature is now supported in the Mabox GL JS library.

Here is the API Doc - https://www.mapbox.com/mapbox-gl-js/api/#geojsonsource#getclusterchildren

How to get points under a cluster?

map.on('click',/* cluster layer id */ 'clusters', function (e) {

  var features = map.queryRenderedFeatures(e.point, { layers: ['clusters'] });
  var clusterId = features[0].properties.cluster_id,
  point_count = features[0].properties.point_count,
  clusterSource = map.getSource(/* cluster layer data source id */'cluster-source');

  // Get Next level cluster Children
  // 
  clusterSource.getClusterChildren(clusterId, function(err, aFeatures){
    console.log('getClusterChildren', err, aFeatures);
  });

  // Get all points under a cluster
  clusterSource.getClusterLeaves(clusterId, point_count, 0, function(err, aFeatures){
    console.log('getClusterLeaves', err, aFeatures);
  })

});
Ashish Singh
  • 1,004
  • 11
  • 23
8

EDIT: This is officially supported in recent versions of mapbox-gl-js, so you do not need to use the workaround I suggest below. See the other answer for more info.

Unfortunately, the behavior you're looking for is not supported at this time. The cluster layer does not contain the data of the individual points in the cluster.

A workaround would be to filter your GeoJSON source for points that are within your clusterRadius distance from the clicked point, and this will give you the points you're looking for.

JSFiddle: https://jsfiddle.net/aznkw784/

  • disclaimer - I work at Mapbox
mollymerp
  • 1,542
  • 9
  • 14
1

As @mollymerp mentioned earlier, supercluster has the method getChildren(clusterId, clusterZoom) which will return the children from the cluster.


EDIT

https://jsfiddle.net/denistsoi/bhzr6hpt/3/

For the above example - I used the getLeaves method, but it's better to systematically call the getChildren and hone down on each successive zoom level to determine what exists in the respective clusters


// GEOJSON being the valid geojson source
map.addSource('data', { 
   type: 'geojson', 
   data: [GEOJSON] 
}); 

map.on('click', function(e) {
  var cluster = map.queryRenderedFeatures(e.point, { layers: ["cluster"] });

  if (cluster.length) {
    // load values to determine cluster points & children

    var superc = supercluster({
       radius: 40,
       maxZoom: 16
    })

    superc.load(map.getSource('data').serialize().data.features);

    var children = superc.getChildren(0, map.getZoom());
    console.log(children); // returns array of children from clustered point;
  }
});
Denis Tsoi
  • 9,428
  • 8
  • 37
  • 56
  • Tried your answer but getting supercluster is not a function – Gnik Jul 09 '17 at 15:19
  • I forgot to add params object to supercluster - this may fix your problem @Prince – Denis Tsoi Jul 10 '17 at 02:25
  • Please visit the link for my code https://stackoverflow.com/questions/45003613/how-can-i-show-the-count-of-points-in-the-particular-latitude-and-longitude-in-m – Gnik Jul 10 '17 at 04:26
  • Still i'm getting supercluster is not a function even though updated as supercluster({ radius: 40, maxZoom: 16 }) – Gnik Jul 10 '17 at 04:27
  • gimme a jsfiddle link instead - (put in some data there as well) - I just removed an extra parenthesis; could've caused an issue there too – Denis Tsoi Jul 10 '17 at 06:08
  • also - when you require `supercluster` - do you know it's being loaded in properly? – Denis Tsoi Jul 10 '17 at 06:09
  • @Prince check the above JSFIDDLE and edit (you didn't include supercluster in the example. – Denis Tsoi Jul 10 '17 at 09:13
  • Now updated with supercluster.Still got supercluster is not a function. I forgot to tell you I'm implementing this in Ionic3 Angular4 application – Gnik Jul 10 '17 at 15:37
  • Eh. I honestly don't know mate, I mean I got a JSFIDDLE example that adds shows you the child properties when you click the cluster... – Denis Tsoi Jul 10 '17 at 16:04
0
           clusterSource.getClusterLeaves(clusterId, pointCount, 0, function (error, features) {
                // Print cluster leaves in the console
                console.log('Cluster leaves:', error, features);

                //build the bounding box with the selected points coordinates
                bounds = new (mapboxgl.LngLatBounds)();
                features.forEach(function (feature) {
                    bounds.extend(feature.geometry.coordinates);
                });
                //Move the map to fit the Bounding Box (BBox)
                return map.fitBounds(bounds, {
                    padding: 45, //orig 45
                    maxZoom: 16
                });
  • Please don't post only code as an answer, but also provide an explanation of what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Ran Marciano Mar 05 '21 at 15:44