经纬志
首页 / deck.gl / 教程

聚合图层:六边形与热力

先看结论

聚合图层的输入是原始点位,输出是空间单元。选择六边形、网格还是热力, 取决于要表达「多少个」还是「有多密」,两者对半径单位的要求也不一样。

最后验证 2026-11-03 · deck.gl 9.0 · 难度:进阶 · 核验 2026-10-29 · 引用本文

聚合是一次 GPU 分箱

HexagonLayer 先把每个点归入六边形单元,统计单元内的点数或权重和, 再按统计值给单元上色。因此 radius 的单位是米,不是像素, 缩放时单元会跟着地面一起变化。

var hexagon = new deck.HexagonLayer({
  id: 'density-hex',
  data: stations,
  getPosition: function (d) { return [d.lng, d.lat]; },
  getColorWeight: function (d) { return d.flow; },
  colorAggregation: 'SUM',
  radius: 900,
  coverage: 0.92,
  extruded: true,
  elevationScale: 12,
  elevationRange: [0, 3000],
  colorRange: [
    [255, 245, 200],
    [255, 210, 120],
    [255, 160, 60],
    [240, 100, 40],
    [190, 40, 60]
  ],
  pickable: true,
  autoHighlight: true
});

coverage 控制六边形填充比例,1 表示单元紧贴,0.8 会在单元之间留出缝隙。 elevationScale 只是视觉放大,不改变统计数据。

颜色区间是分位数映射。colorRange 的几档颜色默认按统计值的分位切分, 不是等间距数值。需要固定阈值时用 colorDomain 显式指定范围。

热力图:连续密度

HeatmapLayer 在屏幕空间叠加高斯核,半径以像素计。 它不产生可拾取的单元,适合做背景密度层,不适合承载交互。

var heat = new deck.HeatmapLayer({
  id: 'density-heat',
  data: stations,
  getPosition: function (d) { return [d.lng, d.lat]; },
  getWeight: function (d) { return d.flow; },
  radiusPixels: 42,
  intensity: 1.4,
  threshold: 0.06,
  colorRange: [
    [0, 0, 255, 0],
    [0, 128, 255, 120],
    [0, 255, 200, 180],
    [255, 220, 0, 220],
    [255, 80, 0, 255]
  ],
  aggregation: 'SUM'
});

threshold 用来压掉低权重的噪点,intensity 提高整体亮度。 两个参数都调过之后仍偏暗,通常是权重没有归一化。

参数适用图层单位说明
radiusHexagonLayer / GridLayer米单元尺寸,随缩放变化
cellSizeGridLayer米方格边长
radiusPixelsHeatmapLayer像素核半径,缩放时不变
coverageHexagonLayer0–1单元填充比例
getColorWeight聚合图层数值参与统计的权重
colorAggregation聚合图层SUM / MEAN / MAX单元内权重如何合并
elevationScaleHexagonLayer / GridLayer倍数仅影响高度显示

两种聚合的组合用法

低缩放级别用热力图看整体分布,放大后切换为六边形并显示计数。 两个图层共享同一份数据,通过 visible 切换,避免同时渲染造成叠加失真。

function layersFor(zoom) {
  var showHex = zoom >= 11;
  return [
    new deck.HeatmapLayer({
      id: 'density',
      data: stations,
      getPosition: function (d) { return [d.lng, d.lat]; },
      getWeight: function (d) { return d.flow; },
      radiusPixels: 36,
      visible: !showHex
    }),
    new deck.HexagonLayer({
      id: 'hex',
      data: stations,
      getPosition: function (d) { return [d.lng, d.lat]; },
      getColorWeight: function (d) { return d.flow; },
      colorAggregation: 'SUM',
      radius: 700,
      extruded: true,
      visible: showHex
    })
  ];
}

注意事项

  • 聚合结果不可逐条拾取。info.object 是单元对象,原始点在其 points 属性里。
  • radius 过大时一个单元会吞掉整片区域,过小则单元数量暴增,先按视野宽度估算合适的值。
  • 权重字段缺失时按 1 计数,不会报错,容易误以为权重没生效。
  • extruded 开启后单元是三维柱体,需要俯仰角才能看出高度差异。
  • 热力图的透明色阶会与底图混合,深色底图上应把低值档的 alpha 调高。

先定统计口径再调视觉。颜色区间、高度倍数都只是表达手段, 单元内的统计值才是数据。口径不稳定时,换一个缩放级别结论就会变。

引用本文

经纬志(2026)。《聚合图层:六边形与热力》。https://www.jingweizhi.com/deckgl/tutorial/aggregation.html(访问日期 2026-11-03)。