Deck.gl蜂窝聚合图怎么做?关键参数在哪配?
Deck.gl蜂窝聚合图怎么做?关键参数在哪配? 这是很多 WebGIS 开发者在做点数据可视化时会遇到的问题:点太多时直接渲染散点会卡顿,也很难看出空间热点,而蜂窝聚合图可以把大量点按六边形网格聚合,快速表达“哪里密集、哪里稀疏”。
本文以 deck.gl 的 HexagonLayer 为核心,讲清楚 Deck.gl蜂窝聚合图 的基本做法、关键参数、常见坑,以及如何判断聚合结果是否可信。适合已经会使用 Mapbox、MapLibre、React 或原生 JavaScript 加载地图的 GIS 学生、WebGIS 开发者和空间数据分析人员阅读。
引言:Deck.gl蜂窝聚合图适合解决什么问题
Deck.gl蜂窝聚合图 主要用于展示大量点数据的空间分布规律。例如:
- 共享单车停靠点热区分析
- 出租车上下客点聚合
- POI 密度分布
- 人口、事件、传感器点位的空间热点
- 城市网格化管理中的事件密度展示
如果你的数据是点要素,并且关注的是“空间密度”或“聚合统计值”,HexagonLayer 通常比普通 ScatterplotLayer 更适合。它会把点落入六边形网格中,然后根据每个网格内的点数量或权重值计算颜色和高度。

背景:为什么不用普通散点图直接画
在 WebGIS 项目中,很多人一开始会直接把点数据画成圆点。数据量较小时没有问题,但当点数量达到几万、几十万时,会出现三个典型问题:
- 视觉遮挡:大量点重叠,中心城区几乎变成一片颜色,看不出真实差异。
- 性能压力:浏览器需要绘制大量点对象,交互、缩放、拖拽可能变慢。
- 空间规律不明显:读者看到的是“点很多”,但不容易判断哪些区域是热点。
Deck.gl蜂窝聚合图 的价值在于把点要素变成统计单元。每一个六边形网格代表一个局部区域,颜色可以表示点数量,高度可以表示聚合值,从而更直观地展示空间密度。
简单理解:散点图强调“每个点在哪里”,蜂窝聚合图强调“哪个区域更密集”。
原理:HexagonLayer 是怎么聚合点数据的
Deck.gl 的 HexagonLayer 会读取每条数据的坐标,通过 getPosition 得到经纬度位置,然后按照指定的 radius 半径生成六边形网格。落在同一个六边形内的点会被聚合到一起。
默认情况下,蜂窝聚合图可以按点数量统计,也可以通过权重字段进行加权统计。例如每个点代表一次订单,按数量聚合即可;如果每个点还有金额字段,则可以按金额加权聚合。
常见核心参数如下:
| 参数 | 作用 | GIS理解 |
|---|---|---|
| data | 输入点数据数组 | 相当于点图层的数据源 |
| getPosition | 指定每条记录的坐标 | 通常返回 [经度, 纬度] |
| radius | 六边形网格半径,单位通常按米理解 | 决定聚合尺度 |
| colorRange | 设置不同聚合值对应的颜色 | 类似分级设色 |
| elevationRange | 设置柱体高度范围 | 控制三维柱状效果 |
| getColorWeight | 设置颜色统计使用的权重字段 | 可按数量、金额、强度等统计 |
| getElevationWeight | 设置高度统计使用的权重字段 | 控制柱体高度的统计依据 |
| coverage | 控制六边形填充比例 | 影响蜂窝之间是否留缝 |
| extruded | 是否显示三维高度 | true 为三维柱体,false 为二维蜂窝 |
步骤:Deck.gl蜂窝聚合图怎么做
步骤1:准备点数据
HexagonLayer 最常见的数据格式是 JavaScript 对象数组。每条记录至少需要经纬度字段。
const points = [
{lng: 116.397, lat: 39.908, count: 1, value: 35},
{lng: 116.401, lat: 39.912, count: 1, value: 20},
{lng: 116.389, lat: 39.903, count: 1, value: 50}
];
这里要特别注意坐标顺序。deck.gl 的经纬度坐标通常写成 [longitude, latitude],也就是 [经度, 纬度]。如果写反,图层可能会飞到错误位置,甚至完全看不到。
步骤2:创建 HexagonLayer
下面是一个最小可用的 Deck.gl蜂窝聚合图 配置示例:
const hexagonLayer = new deck.HexagonLayer({
id: 'hexagon-layer',
data: points,
getPosition: d => [d.lng, d.lat],
radius: 500,
extruded: true,
elevationScale: 30,
coverage: 0.9,
colorRange: [
[255, 255, 178],
[254, 204, 92],
[253, 141, 60],
[240, 59, 32],
[189, 0, 38]
],
elevationRange: [0, 3000],
pickable: true
});
这段配置中,最关键的是 getPosition 和 radius。前者决定点落在哪里,后者决定六边形网格多大。
步骤3:把图层加入 Deck 实例
如果你使用原生 deck.gl,可以把 HexagonLayer 放入 layers 数组中。
const deckgl = new deck.DeckGL({
container: 'map',
initialViewState: {
longitude: 116.397,
latitude: 39.908,
zoom: 10,
pitch: 45,
bearing: 0
},
controller: true,
layers: [hexagonLayer]
});
如果你是在 Mapbox 或 MapLibre 底图上叠加 deck.gl,一般会使用 DeckGL Overlay 或对应集成方式。核心思想不变:底图负责地图瓦片,HexagonLayer 负责点数据聚合渲染。
步骤4:配置 radius,决定聚合尺度
在 Deck.gl蜂窝聚合图 中,radius 是最容易影响结果解读的参数。半径太小,图面会碎,热点不明显;半径太大,局部差异会被抹平。
- 城市级 POI 密度:可从 300 米到 1000 米尝试。
- 区县级事件分布:可从 1000 米到 3000 米尝试。
- 全国范围点数据:通常需要更大的半径,或改用服务端聚合。
不要只为了“好看”随意调大 radius。GIS 分析中,聚合尺度会改变空间结论。建议在文章、图例或系统说明中明确写出蜂窝半径。
步骤5:配置颜色和高度
颜色一般用于表达聚合强度,高度用于增强三维视觉效果。你可以让颜色和高度都按点数量统计,也可以分别使用不同权重。
const hexagonLayer = new deck.HexagonLayer({
id: 'hexagon-layer',
data: points,
getPosition: d => [d.lng, d.lat],
radius: 500,
colorRange: [
[237, 248, 251],
[178, 226, 226],
[102, 194, 164],
[44, 162, 95],
[0, 109, 44]
],
getColorWeight: d => d.value,
colorAggregation: 'SUM',
getElevationWeight: d => d.value,
elevationAggregation: 'SUM',
elevationScale: 20,
extruded: true,
pickable: true
});
这段代码表示颜色和高度都按 value 字段求和。如果 value 表示订单金额,那么蜂窝颜色和高度表达的是区域订单金额总量,而不是点数量。
步骤6:开启 tooltip,验证聚合结果
做 Deck.gl蜂窝聚合图 时,不建议只看颜色。最好加上 tooltip,查看每个蜂窝中聚合了多少条点记录。
const deckgl = new deck.DeckGL({
container: 'map',
initialViewState: {
longitude: 116.397,
latitude: 39.908,
zoom: 10,
pitch: 45
},
controller: true,
layers: [hexagonLayer],
getTooltip: ({object}) => {
if (!object) return null;
return {
text: `点数量:${object.points.length}`
};
}
});
如果使用权重统计,可以进一步检查 object 中的聚合结果。不同版本和配置下返回对象结构可能略有差异,建议先在控制台打印 object,确认字段含义后再写 tooltip。
getTooltip: ({object}) => {
console.log(object);
return object ? {text: '查看控制台中的聚合对象'} : null;
}
常见坑:Deck.gl蜂窝聚合图为什么不显示或结果不对
1. 经纬度顺序写反
最常见错误是把坐标写成 [纬度, 经度]。deck.gl 常用的是 [经度, 纬度]。
getPosition: d => [d.lng, d.lat] // 正确
getPosition: d => [d.lat, d.lng] // 常见错误
2. 数据不是 WGS84 经纬度
WebGIS 前端图层通常使用经纬度输入。如果你的数据来自投影坐标系,例如 CGCS2000 高斯投影、Web Mercator 米制坐标或地方坐标,需要先转换到经纬度。否则 HexagonLayer 会把坐标当作经纬度解释,图层位置会严重错误。
3. radius 设置不合理
radius 太小可能导致几乎每个点单独占一个蜂窝,看起来像散点图;radius 太大则会把整个城市聚成几个大块。调参时建议从业务尺度出发,而不是只看视觉效果。
4. elevationScale 太大导致柱体夸张
如果柱体高度冲出屏幕,通常不是数据错了,而是 elevationScale 或 elevationRange 设置过大。可以先降低 elevationScale,再观察结果。
5. 权重字段存在空值或字符串
如果 getColorWeight 或 getElevationWeight 返回的是字符串、null、undefined,聚合结果可能异常。建议先清洗数据。
getColorWeight: d => Number(d.value) || 0
getElevationWeight: d => Number(d.value) || 0
6. 数据量过大但全部放在前端
deck.gl 的 WebGL 渲染能力很强,但不代表所有数据都应该一次性塞到浏览器。如果点数据达到百万级,并且还要频繁筛选、联动、更新,建议考虑服务端预聚合、瓦片化或使用二进制数据加载方式。
方法比较:蜂窝聚合、热力图和网格聚合怎么选
| 方法 | 适合场景 | 优点 | 限制 |
|---|---|---|---|
| HexagonLayer 蜂窝聚合 | 点密度、热点区域、三维聚合展示 | 空间单元清晰,适合解释聚合统计 | 结果受 radius 影响明显 |
| HeatmapLayer 热力图 | 连续热点趋势展示 | 视觉平滑,适合快速看趋势 | 不如蜂窝图容易解释具体统计单元 |
| GridLayer 方格聚合 | 规则网格统计、栅格化表达 | 和传统网格管理、栅格分析更接近 | 视觉上不如六边形自然 |
| ScatterplotLayer 散点图 | 点数量较少、关注单个位置 | 保留原始点位置 | 数据量大时遮挡严重 |
如果你的目标是做“可解释的空间聚合统计”,Deck.gl蜂窝聚合图 通常比热力图更合适。热力图适合展示趋势,蜂窝图适合展示每个统计单元的强弱。
检查清单:上线前逐项确认
- 数据坐标是否为经纬度,并且顺序为 [经度, 纬度]。
- getPosition 是否能为每条记录返回有效坐标。
- radius 是否符合业务分析尺度,而不是只为了视觉效果。
- colorRange 是否从浅到深,能表达强弱变化。
- getColorWeight 和 getElevationWeight 是否返回数值。
- 是否需要按 COUNT、SUM、MEAN 等方式聚合。
- tooltip 是否能帮助验证蜂窝内点数量或权重值。
- 数据量是否适合前端直接加载。
- 三维效果是否会遮挡底图或影响阅读。
- 图例、说明文字中是否标明蜂窝半径和统计口径。
FAQ:Deck.gl蜂窝聚合图常见问题
Deck.gl蜂窝聚合图和热力图有什么区别?
蜂窝聚合图把点统计到明确的六边形单元里,每个蜂窝都有相对清晰的统计含义;热力图更强调连续的热点趋势,视觉上更平滑,但具体数值解释不如蜂窝聚合图直接。
HexagonLayer 的 radius 单位是什么?
在常见经纬度地图场景中,可以把 radius 理解为以米为单位的聚合半径。实际显示效果还会受到地图投影、缩放级别和视图范围影响。做 GIS 分析时,建议用多个半径测试,并选择符合业务尺度的值。
Deck.gl蜂窝聚合图可以按字段求和吗?
可以。通过 getColorWeight、getElevationWeight 以及对应的聚合方式,可以让颜色和高度按某个字段求和、求平均或使用其他支持的统计方式。常见做法是按订单金额、事件强度、人口数等字段加权。
为什么我的蜂窝图显示在错误位置?
优先检查两个问题:第一,坐标顺序是否写成了 [经度, 纬度];第二,原始数据是否已经转换到 WGS84 经纬度。如果把投影坐标直接传给 getPosition,图层位置通常会明显错误。
数据很多时还适合用 HexagonLayer 吗?
适合,但要看数据量和交互需求。几十万点以内的前端聚合在很多场景下可以工作;如果达到百万级,或者需要复杂筛选和实时刷新,建议考虑服务端预聚合、切片加载或减少传输字段。
二维蜂窝图和三维蜂窝图怎么选?
如果主要用于严肃分析和报表展示,二维蜂窝图更稳定、干扰少;如果用于大屏、演示或需要突出热点强弱,三维蜂窝图更有冲击力。但三维柱体可能遮挡底图,必须控制 elevationScale。
结论:先定统计口径,再调视觉参数
做 Deck.gl蜂窝聚合图,不要一开始就陷入颜色和高度的视觉调参。正确流程应该是:先确认点数据坐标正确,再确定聚合半径 radius,然后决定按数量还是按权重字段统计,最后再配置 colorRange、elevationRange 和 tooltip。
如果只记住几个关键参数,可以重点掌握 getPosition、radius、colorRange、getColorWeight、getElevationWeight、elevationScale 和 extruded。这些参数基本决定了 Deck.gl蜂窝聚合图 的位置、聚合尺度、颜色含义和三维效果。
从 GIS 分析角度看,蜂窝聚合图不是单纯的“炫酷地图效果”,而是一种空间统计表达。只要把坐标、半径、权重和图例说明处理好,它就能成为 WebGIS 项目中非常实用的热点分析图层。