Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapBox - Cluster Zooming

Is it possible to recreate the click to zoom on clustering like Craigslist Mapview does with MapBox? When you click, it zooms to the area those location dots are contained in.

Here's my clustering code:

map.on('load', function() {
map.addSource("location", {
    type: "geojson",
    data: "https://s3-us-west-2.amazonaws.com/s.cdpn.io/73873/test.geojson",
    cluster: true,
    clusterMaxZoom: 14,
    clusterRadius: 100
});

    map.addLayer({
    id: "clusters",
    type: "circle",
    source: "location",
    filter: ["has", "point_count"],
    paint: {
        "circle-color": {
            property: "point_count",
            type: "interval",
            stops: [
                [0, "#71AAC6"],
                [100, "#71AAC6"],
                [750, "#71AAC6"],
            ]
        },
        "circle-radius": {
            property: "point_count",
            type: "interval",
            stops: [
                [0, 20],
                [100, 30],
                [750, 40]
            ]
        }
    }
});

Here's my demo

Codepen Demo

like image 256
meow-meow-meow Avatar asked Oct 11 '25 09:10

meow-meow-meow


1 Answers

I don't think that you can do it in pure Mapbox, at least not easily.

But for those cluster specific usages there is Supercluster (an official Mapbox geospatial point clustering library) which has exactly what you want:

getClusterExpansionZoom(clusterId)

Returns the zoom on which the cluster expands into several children (useful for "click to zoom" feature) given the cluster's cluster_id.

Edit: actually you could do it without Supercluster:

  1. Using this JsFiddle example you can retrieve the points of the cluster you clicked.

    map.on('click', function(e) {
        const cluster = map.queryRenderedFeatures(e.point, { layers: ["cluster"] });
    
        if (cluster[0]) {
        // features: from the added source that are clustered
        const pointsInCluster = features.filter(f => {
            const pointPixels = map.project(f.geometry.coordinates)
          const pixelDistance = Math.sqrt(
            Math.pow(e.point.x - pointPixels.x, 2) + 
            Math.pow(e.point.y - pointPixels.y, 2) 
          );
          return Math.abs(pixelDistance) <= clusterRadius;
        });
        console.log(cluster, pointsInCluster);
      }
    });
    
  2. Then you can create a mapboxgl.LngLatBounds and extend it with all those points.

  3. You will obtain a LngLatBounds wrapping all your points so you can just call fitBounds on it and you are good to go.

like image 190
MeltedPenguin Avatar answered Oct 13 '25 22:10

MeltedPenguin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!