Skip to content

点聚合 Supercluster ​

Point Cluster (Supercluster)

▶ 在线运行案例

点聚合 Supercluster

你将学到什么 ​

  • 引入 Supercluster 做屏幕空间聚合
  • getClusters(bbox, zoom) 按视口与层级取簇
  • camera.changed 监听视角变化重算
  • 聚合点展开时取 最近子点 代表位置

效果说明 ​

加载全国城市 JSON,缩放地图时相近城市合并为单图标;放大后拆散为独立 billboard。

核心概念 ​

Supercluster 流程 ​

GeoJSON Feature[] → supercluster.load()
                         ↓
              getClusters([west,south,east,north], zoom)
                         ↓
              BillboardCollection.add / removeAll
js
const supercluster = new Supercluster({
    radius: 40,    // 聚合半径(像素级算法参数)
    extent: 512,
    minZoom: 0,
    maxZoom: 16,
});
supercluster.load(points);

视口与层级 ​

js
const bbox = viewer.camera.computeViewRectangle();
const bounds = [west, south, east, north].map(i => Cesium.Math.toDegrees(i));

// 用当前渲染瓦片 level 近似 zoom
const level = viewer.scene.globe._surface._tilesToRender[0]._level;
const clusters = supercluster.getClusters(bounds, level);

聚合点代表位置 ​

若 cluster.properties.cluster 为真,从 getLeaves 里找 离簇中心最近 的原始点,避免图标漂在空处。

实现步骤 ​

  1. fetch 城市 JSON,转为 { type:'Feature', geometry:{coordinates} }
  2. setClusterCollection(viewer, points, callback) 封装聚合
  3. 初次 setBillboards(clusters)
  4. camera.changed → billboards.removeAll() → 重新 getClusters → setBillboards

代码要点 ​

js
viewer.camera.changed.addEventListener(function () {
    const level = getLevel();
    if (!level) return;
    const clusters = supercluster.getClusters(getBounds(), level);
    billboards.removeAll();
    setBillboards(clusters);
});

依赖

案例注释要求自行引入 Supercluster(npm 或 script)。官方内置方案见下一篇 官方点聚合。

源码 ​

完整源码见 GitHub。

小结 ​

  • 外部 Supercluster 灵活可控;Cesium 内置 clustering 更简单
  • 上一篇:海量点 · 下一篇:海量面线

基础功能 · Cesium.js · 10/19