Atlaslog
Atlaslog / OpenLayers / Tutorial / Clustering and heatmaps
OpenLayers · Tutorial

Clustering and heatmaps

Quick answer

This tutorial compares two ways to tame dense point data in OpenLayers: clustering counts nearby features and heatmaps render density as colour. It wraps a source in ol.source.Cluster with distance and minZoom, reads the features array to size the symbol, and zooms via view.fit on a computed extent. It then configures ol.layer.Heatmap with radius, blur, weight and gradient normalised to the 95th percentile. Readers can choose and combine both representations.

Last verified 2026-11-03 · OpenLayers 10.3.1 · Cite this page
Key points
Example
var raw = new ol.source.Vector({
  url: '/data/stations.geojson',
  format: new ol.format.GeoJSON({
    dataProjection: 'EPSG:4326',
    featureProjection: 'EPSG:3857'
  })
});

var clustered = new ol.source.Cluster({
  distance: 40,        // 聚合阈值,单位是像素
  minZoom: 13,         // 低于该级别不聚合
  source: raw
});

var clusterLayer = new ol.layer.Vector({
  source: clustered,
  style: function (feature) {
    var items = feature.get('features');
    var size = items.length;
    var radius = 8 + Math.min(size, 60) * 0.35;

    return new ol.style.Style({
      image: new ol.style.Circle({
        radius: radius,
        fill: new ol.style.Fill({ color: 'rgba(31, 95, 208, 0.85)' }),
        stroke: new ol.style.Stroke({ color: '#ffffff', width: 2 })
      }),
      text: new ol.style.Text({
        text: String(size),
        font: '600 11px sans-serif',
        fill: new ol.style.Fill({ color: '#ffffff' })
      })
    });
  }
});
map.on('singleclick', function (event) {
  var hit = map.forEachFeatureAtPixel(event.pixel, function (f) { return f; }, {
    hitTolerance: 6,
    layerFilter: function (layer) { return layer === clusterLayer; }
  });

  if (!hit) return;

  var items = hit.get('features');
  if (items.length === 1) {
    console.log('单点', items[0].get('name'));
    return;
  }

  var extent = ol.extent.createEmpty();
  items.forEach(function (f) {
    ol.extent.extend(extent, f.getGeometry().getExtent());
  });
  map.getView().fit(extent, { duration: 400, maxZoom: 17, padding: [40, 40, 40, 40] });
});
Notes
Runnable examplesChinese originalAll Tutorials
English edition written for Atlaslog. Code is taken from the original Chinese page and runs unchanged.
Cite this page

Atlaslog (2026). Clustering and heatmaps. https://www.jingweizhi.com/en/openlayers/tutorials/cluster-heatmap.html (accessed 2026-11-03).