Huw Davies
Huw Davies

Reputation: 811

Clustering custom html markers with mapbox-gl-js

I'm using the mapbox-gl-js API and I'm using it with react to create some custom markers as follows:

        let div = document.createElement('div');
        let marker = new mapboxgl.Marker(div, {
            offset: [ -20, 80 ]
        });

        marker.setLngLat(person.geometry.coordinates);

        render(
            <MapPersonIcon />,
            div,
            () => {
                marker.addTo(map);
            }
        );

result

This worked great. However I would now like to cluster these markers, producing the same affect as the functionality found with layers i.e.

https://www.mapbox.com/mapbox-gl-js/example/cluster/

clusters

Does anyone know whether this is possible (hopefully with custom clusters too) or whether it will be available in an upcoming release?

Upvotes: 11

Views: 7487

Answers (2)

Abraham Brookes
Abraham Brookes

Reputation: 2007

This feature is now in Mapbox GL js - https://docs.mapbox.com/mapbox-gl-js/example/cluster-html/

Key takeaways:

When setting your data source using map.addSource, make sure you define cluster: true and clusterRadius: int, like so:

map.addSource( 'sourceName', {
    type: "geojson",
    data: {
        type: 'FeatureCollection',
        features: [JSON]
    },
    cluster: true,
    clusterRadius: 80,
});

That will push mapbox to cluster your icons, but you need to tell mapbox what to do when it clusters those icons:

map.on( 'moveend', updateMarkers ); // moveend also considers zoomend

The business (trimmed down for relevance):

function updateMarkers(){
    var features = map.querySourceFeatures( 'sourceName' );

    for ( var i = 0; i < features.length; i++ ) {
        var coords = features[ i ].geometry.coordinates;
        var props = features[ i ].properties;
            
        if ( props.cluster ){ // this property is only present when the feature is clustered
            // generate your clustered icon using props.point_count
            var el = document.createElement( 'div' );
            el.classList.add( 'mapCluster' );
            el.innerText = props.point_count;
            marker = new mapboxgl.Marker( { element: el } ).setLngLat( coords );
                
        } else { // feature is not clustered, create an icon for it
            var el = new Image();
            el.src = 'icon.png';
            el.classList.add( 'mapMarker' );
            el.dataset.type = props.type; // you can use custom data if you have assigned it in the GeoJSON data
            marker = new mapboxgl.Marker( { element: el } ).setLngLat( coords );
        }
            
        marker.addTo( map );
    }
}

NOTE: Don't copy paste this code, rather use it in conjunction with https://docs.mapbox.com/mapbox-gl-js/example/cluster-html/ to get the whole picture. Hope this helps!

Upvotes: 8

Huw Davies
Huw Davies

Reputation: 811

Answering own question:

At current it seems that this isn't possible as per mapbox's github: enter image description here

If you would like to cluster your markers you will need to use mapbox's native maki icons (please see above example picture & URL) until a plugin is available for your custom HTML markers.

Upvotes: 2

Related Questions