Skip to main content

Cluster Points

Configure the map to cluster nearby points and show a count of the clustered points at higher zoom levels.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.21.0.css" />
        <script src="https://maps-sdk.trimblemaps.com/v3/trimblemaps-3.21.0.js"></script>
        <style>
            body { margin: 0; padding: 0; }

            #map {
                position: absolute;
                top: 0;
                bottom: 0;
                width: 100%;
            }
        </style>
    </head>
    <body>
        <div id="map"></div>

        <script>
            TrimbleMaps.APIKey = 'YOUR_API_KEY_HERE';
            const map = new TrimbleMaps.Map({
                container: 'map',
                center: new TrimbleMaps.LngLat(-78.566234, 40.499440),
                zoom: 8
            });

            const bounds = map.getBounds();
            const north = bounds.getNorth();
            const south = bounds.getSouth();
            const east = bounds.getEast();
            const west = bounds.getWest();

            // Functions for generating random points and features
            function getRandomPoint() {
                const lng = west + ((east - west) * Math.random());
                const lat = south + ((north - south) * Math.random());

                return [lng, lat];
            }

            function getGeoJsonFeatures() {
                const features = [];

                for (var i = 0; i < 250; i++) {
                    features.push({
                        type: 'Feature',
                        properties: {},
                        geometry: {
                            type: 'Point',
                            coordinates: getRandomPoint()
                        }
                    });
                }
                return features;
            }

            // Wait for the map to load before adding layers and data sources
            map.on('load', function() {
                // Use cluster properties on datasource to group data
                map.addSource('randomPoints', {
                    type: 'geojson',
                    cluster: true,
                    clusterRadius: 40,
                    clusterMaxZoom: 14,
                    data: {
                        type: 'FeatureCollection',
                        features: getGeoJsonFeatures()
                    }
                });

                // Use filter to shot clustered points
                map.addLayer({
                    id: 'clusteredPoints',
                    type: 'circle',
                    source: 'randomPoints',
                    filter: ['has', 'point_count'],
                    paint: {
                        'circle-radius': [
                            'step',
                            ['get', 'point_count'],
                            15, 5,
                            20, 50,
                            25
                        ],
                        'circle-color': '#E33',
                        'circle-stroke-color': '#FFF',
                        'circle-stroke-width': 3
                    }
                });

                // Show count for clustered points
                map.addLayer({
                    id: 'clusterCount',
                    type: 'symbol',
                    source: 'randomPoints',
                    filter: ['has', 'point_count'],
                    layout: {
                        'text-field': '{point_count}',
                        'text-font': ['Roboto Regular'],
                        'text-size': 12
                    },
                    paint: {
                        'text-color': '#FFF'
                    }
                });

                // Use filter to show unclustered points
                map.addLayer({
                    id: 'unclusteredPoints',
                    type: 'circle',
                    source: 'randomPoints',
                    filter: ['!', ['has', 'point_count']],
                    paint: {
                        'circle-radius': 10,
                        'circle-color': '#11A',
                        'circle-stroke-color': '#FFF',
                        'circle-stroke-width': 2
                    }
                });
            });
        </script>
    </body>
</html>
Last updated June 15, 2023.