Appearance
ClusterLayer 点聚合
点聚合层:对既有
DataSource启用 Cesium 原生EntityCluster,按像素范围把邻近的海量点位 自动聚合成计数徽标(默认 canvas 双层圆 + 计数文本,颜色随数量阈值变化),缩放时聚合/散开实时切换。
能力定位
ClusterLayer 适合:
- 海量点位可视化:雷达/传感器目标、监控点、轨迹点在数据量大时的聚合显示;
- 视距自适应:相机拉远自动合并邻近点位为计数徽标,拉近自动散开为原始点位;
- 原生聚合力:基于 Cesium 公共
EntityCluster,不引入第三方聚合库。
与静态图标桶方案不同——源案例 PointObject/Cluser 预置 10+.png / 30+.png / 150+.png 等静态 图标按数量分档;本实现统一收敛为 createClusterIcon canvas 生成器(对齐 DynamicCluser 的 getCluserImage),按数量取阈值色动态绘制,不依赖静态图标资产。
构造函数
ts
constructor(options: ClusterLayerOptions)ts
interface ClusterLayerOptions {
dataSource: DataSource // 必填:待聚合的数据源(须已加载点位实体)
pixelRange?: number // 聚合像素范围,默认 30
minimumClusterSize?: number // 最小聚合个数,默认 3
clusterIcon?: (count: number) => string | HTMLCanvasElement // 聚合图标生成器,默认 createClusterIcon
labelShow?: boolean // 是否显示聚合点 label,默认 false
}| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
dataSource | DataSource | (必填) | 待聚合的数据源,调用方负责创建与 add/remove |
pixelRange | number | 30 | 聚合像素范围(对齐源案例 Cluser) |
minimumClusterSize | number | 3 | 最小聚合个数(对齐源案例 Cluser) |
clusterIcon | (count) => string | HTMLCanvasElement | createClusterIcon | 聚合图标生成器,返回 URL/dataURI/canvas |
labelShow | boolean | false | 是否显示聚合点 label |
生命周期
实现 Lifecycle<Viewer> 契约,on/off/destroy 均幂等:
ts
on(viewer: Viewer): void // 启用 dataSource.clustering + 注册 clusterEvent 监听
off(viewer: Viewer): void // 移除监听器 + 还原 dataSource.clustering.enabled 原值
destroy(viewer: Viewer): void // 等价于 off清理完整性:on 保存 clustering.enabled 原值,off/destroy 还原,不强制关闭调用方 已手动开启的聚类;监听器在 off/destroy 时移除,clusterEvent 不再残留回调。
基础示例
ts
import { ClusterLayer } from '@nexa/gis-cesium'
// 1. 准备点位数据源(调用方负责 add/remove)
const dataSource = await Cesium.GeoJsonDataSource.load(pointsGeoJson)
viewer.dataSources.add(dataSource)
// 2. 挂载点聚合层
const cluster = new ClusterLayer({
dataSource,
pixelRange: 30,
minimumClusterSize: 3,
})
cluster.on(viewer)
// 3. 页面或场景退出时统一销毁(幂等)
cluster.destroy(viewer)进阶示例
自定义聚合图标生成器与 label 显示:
ts
import { ClusterLayer, createClusterIcon } from '@nexa/gis-cesium'
const cluster = new ClusterLayer({
dataSource,
pixelRange: 40,
minimumClusterSize: 3,
// 自定义阈值色带:≥200 深红 / ≥50 橙 / ≥1 绿
clusterIcon: (count) =>
createClusterIcon(count, {
thresholds: [
{ value: 200, color: 'rgb(178, 34, 34)' },
{ value: 50, color: 'rgb(255, 165, 0)' },
{ value: 1, color: 'rgb(0, 200, 0)' },
],
}),
labelShow: true, // 聚合点同时显示 label
})
cluster.on(viewer)聚合计数徽标
createClusterIcon(count, options?) 生成聚合徽标(canvas 双层圆 + 白色计数文本), 颜色按 ClusterIconOptions.thresholds 从大到小匹配首个 count >= threshold.value:
- 默认色带(对齐源案例
DynamicCluser):≥100 红 / ≥50 黄 / ≥10 蓝 / ≥1 绿; - 未命中任何阈值时使用最末阈值色(如
count = 0→ 绿); - 图标边长默认按计数位数自适应(
String(count).length * 12 + 50),亦可通过size固定; - 浏览器环境返回
HTMLCanvasElement(可直接赋给billboard.image);非浏览器环境 (Node/测试)返回 1x1 透明占位 data URI,避免运行时异常。
ts
import { createClusterIcon, pickClusterColor } from '@nexa/gis-cesium'
createClusterIcon(120) // 红色计数徽标 canvas
pickClusterColor(3) // 'rgb(0, 255, 0)'(≥1)实现说明
- 原生聚合:仅使用 Cesium 公共
EntityClusterAPI (clustering.enabled / pixelRange / minimumClusterSize+clusterEvent),不触碰私有成员。 - 聚合样式:
clusterEvent回调把聚合点渲染为计数徽标——billboard.show = true、billboard.verticalOrigin = VerticalOrigin.BOTTOM、billboard.image = createClusterIcon(count),label.show按labelShow控制。 - 类型约束:Cesium d.ts 将
Billboard.image声明为string(运行时实际接受HTMLCanvasElement,见Cesium.d.tsBillboard.image的 JSDoc)。ClusterLayer在 回调参数上以局部结构类型ClusterStyle放宽该字段,避免在回调内断言,保持严格类型检查。 - 资源所有权:本层只拥有
clusterEvent监听器与clustering.enabled还原责任, 不创建也不移除调用方提供的dataSource(数据源归属调用方)。 - 无外部依赖:源案例的
cluserPoint.json为外部 URL(http://116.63.83.180:8088/...), 迁移时剥离,示例以内联 GeoJSON 演示,图标由 canvas 生成,不依赖静态图标资产。
清理责任
ts
cluster.destroy(viewer) // 或 cluster.off(viewer),等价且幂等重复调用 destroy/off 安全(未 on 时为空操作)。销毁后重新 on 可再次启用聚合。
Cesium 版本限制
- 依赖 Cesium 公共
EntityCluster(dataSource.clustering)与Event; Billboard.image类型为 d.ts 已知缺口(stringvsHTMLCanvasElement),运行时不受影响;- 已验证目标版本:Cesium 1.133.1。