MapSnippets logoMapSnippets logo

Point Clustering with OpenLayers

OpenLayers

Group nearby point features into clusters using ol.source.Cluster with dynamic styling based on cluster size.

progress_activityLoading map...
var features = [];
for (var i = 0; i < 200; i++) {
  features.push(new ol.Feature({
    geometry: new ol.geom.Point(ol.proj.fromLonLat([2.3 + Math.random() * 0.3, 48.8 + Math.random() * 0.15]))
  }));
}
var clusterSource = new ol.source.Cluster({
  distance: 40,
  source: new ol.source.Vector({ features: features })
});
var clusterLayer = new ol.layer.Vector({
  source: clusterSource,
  style: function(feature) {
    var size = feature.get('features').length;
    return new ol.style.Style({
      image: new ol.style.Circle({ radius: 10 + Math.min(size, 20), fill: new ol.style.Fill({ color: size > 5 ? '#e63946' : '#457b9d' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) }),
      text: new ol.style.Text({ text: size.toString(), fill: new ol.style.Fill({ color: '#fff' }), font: 'bold 12px sans-serif' })
    });
  }
});
var map = new ol.Map({
  target: 'map',
  layers: [
    new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', attributions: '&copy; <a href="https://www.maptiler.com/copyright/">MapTiler</a>' }) }),
    clusterLayer
  ],
  view: new ol.View({ center: ol.proj.fromLonLat([2.45, 48.87]), zoom: 11 })
});

How it works

ol.source.Cluster wraps a vector source and groups features that are within a specified pixel distance. The distance parameter controls how aggressively points are merged.

The style function receives each cluster feature. feature.get('features') returns the array of original features in that cluster, so you can display the count and adjust the visual style based on cluster size.

As the user zooms in, clusters split into smaller groups and eventually into individual points.

Key APIs

API Description Docs
ol.source.Cluster Cluster source that groups nearby features openlayers.org
ol.style.Text Text label style openlayers.org
feature.get('features') Get original features in a cluster openlayers.org

FAQ

How do I adjust the cluster distance?

Change the distance property (in pixels). Higher values create fewer, larger clusters. Typical values are 30-60.

Can I animate clusters splitting and merging?

OpenLayers does not include built-in cluster animation. You can implement custom animations using ol.render.Event and canvas drawing.

Common mistakes

  • Accessing feature.getGeometry() on a cluster feature returns the cluster centroid, not individual points
  • Forgetting that feature.get('features') returns an array even for single-point clusters
  • Setting distance too low, resulting in overlapping markers at lower zoom levels
auto_awesome

Build maps using OpenLayers with AI

Generate code like this point clustering with openlayers example using the OpenLayers skill in your IDE.