MapSnippets logoMapSnippets logo

Point Clustering with MapTiler SDK

MapTiler SDK

Cluster dense point data using a GeoJSON source with built-in clustering support in MapTiler SDK.

progress_activityLoading map...
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
  container: 'map',
  style: maptilersdk.MapStyle.STREETS,
  center: [2.3522, 48.8566],
  zoom: 11
});
const points = [];
for (let i = 0; i < 80; i++) {
  points.push({
    type: 'Feature',
    geometry: { type: 'Point', coordinates: [2.25 + Math.random() * 0.25, 48.8 + Math.random() * 0.15] },
    properties: { name: 'Location ' + (i + 1) }
  });
}
map.on('load', () => {
  map.addSource('points', {
    type: 'geojson',
    data: { type: 'FeatureCollection', features: points },
    cluster: true,
    clusterMaxZoom: 14,
    clusterRadius: 50
  });
  map.addLayer({ id: 'clusters', type: 'circle', source: 'points', filter: ['has', 'point_count'],
    paint: { 'circle-color': '#9C27B0', 'circle-radius': ['step', ['get', 'point_count'], 15, 10, 22, 30, 30], 'circle-stroke-width': 2, 'circle-stroke-color': '#ffffff' }
  });
  map.addLayer({ id: 'cluster-count', type: 'symbol', source: 'points', filter: ['has', 'point_count'],
    layout: { 'text-field': '{point_count_abbreviated}', 'text-size': 13 },
    paint: { 'text-color': '#ffffff' }
  });
  map.addLayer({ id: 'unclustered', type: 'circle', source: 'points', filter: ['!', ['has', 'point_count']],
    paint: { 'circle-color': '#ce93d8', 'circle-radius': 6, 'circle-stroke-width': 1, 'circle-stroke-color': '#ffffff' }
  });
});

How it works

Set cluster: true on a GeoJSON source to enable server-side clustering. The engine groups nearby points into clusters and exposes point_count and point_count_abbreviated properties.

Three layers render the data: large circles for clusters, text labels showing the count, and small circles for individual points. The filter property separates clustered from unclustered features.

The step expression scales circle radius by point count: small clusters get a 15px radius, large ones get 35px.

Key APIs

API Description Docs
cluster GeoJSON source option to enable clustering docs.maptiler.com/sdk-js/api/
clusterRadius Pixel radius for grouping points docs.maptiler.com/sdk-js/api/
map.addSource() Add a data source docs.maptiler.com/sdk-js/api/

FAQ

Can I click a cluster to zoom in?

Yes. Add a click handler on the clusters layer, call map.getSource('quakes').getClusterExpansionZoom(clusterId), then map.easeTo() to that zoom.

What is the maximum number of points for clustering?

There is no hard limit. The engine handles hundreds of thousands of points efficiently because clustering runs on a web worker.

Common mistakes

  • Forgetting the filter: without it, all three layers render on top of each other
  • Using DOM markers for large datasets: use circle/symbol layers with clustering instead
  • Adding cluster layers before load: sources and layers require the style to be loaded
auto_awesome

Build maps using MapTiler SDK with AI

Generate code like this point clustering with maptiler sdk example using the MapTiler SDK skill in your IDE.