实现效果如下

实现步骤
- 后端接口获取全部点位数据
- EntityCluster 是DataSource的一个属性,DataSource 中在通过加载entities 自动展示聚合数据,DataSouce 可以之前加载行政边界时候用过,可以通过load 加载数据,DataSource 是一个接口,有很多实现类,但是我们这边是从后端接口获取的,不是geoJson 数据,可以使用CustomDataSource 自定义数据源,然后赋值entities
- 修改聚合样式,Cesium 可以通过pinBuilder 实现点位以及聚合后的数字,修改里面的文字即可,也可以通过设置自定义图片实现。
- 自定义样式,按照聚合数量的多少选择不同的图片,同时设置图片的大小
- 很多人也可能是为了找这个图标,我提供一个方法,阿里云图标库 ,直接搜索聚合找自己想要的样式就可以
具体代码实现 MapCollection.ts
import * as Cesium from 'cesium'
import { EgasService } from '@/api/installService'
import { MapEntityType } from '@/views/egas/gis/MapEvent'
import { CustomDiffuseCircleMaterialProperty } from '@/views/egas/gis/material/CustomDiffuseCircleMaterialProperty'
export const addBaithonEquipmentPoints = async (viewer: Cesium.Viewer) => {
await clearAllPoints(viewer)
const result: any = await EgasService.baithonEquipmentPointDataList()
const dataSource = new Cesium.CustomDataSource('myData')
result.data.forEach((item: any) => {
if (item.isAlarms) {
dataSource.entities.add({
name: MapEntityType.BAITHON_POINT,
properties: new Cesium.PropertyBag(item),
position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude, 0),
billboard: {
image: `/imgs/map_icon/location_warning.png`,
pixelOffset: new Cesium.Cartesian2(0, -10)
},
ellipse: {
semiMajorAxis: 150,
semiMinorAxis: 150,
material: new CustomDiffuseCircleMaterialProperty({
color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
speed: 2.0,
circleCount: 2,
gradient: 0.2
})
}
})
} else {
dataSource.entities.add({
name: MapEntityType.BAITHON_POINT,
properties: new Cesium.PropertyBag(item),
position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude, 0),
billboard: {
image: `/imgs/map_icon/location_normal.png`,
pixelOffset: new Cesium.Cartesian2(0, -10)
}
})
}
})
dataSource.clustering.enabled = true
dataSource.clustering.pixelRange = 15
dataSource.clustering.minimumClusterSize = 3
dataSource.clustering.clusterEvent.addEventListener(async (clusteredEntities, cluster) => {
cluster.label.show = false
cluster.label.font = '14px Helvetica'
cluster.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM
if (clusteredEntities.length >= 20) {
combineIconAndLabel(
'./imgs/map_icon/cluster/cluster_04.png',
clusteredEntities.length,
64
).then((item) => {
cluster.billboard.image = item.toDataURL()
cluster.billboard.width = 72
cluster.billboard.height = 72
})
} else if (clusteredEntities.length >= 12) {
combineIconAndLabel(
'./imgs/map_icon/cluster/cluster_03.png',
clusteredEntities.length,
64
).then((item) => {
cluster.billboard.image = item.toDataURL()
cluster.billboard.width = 56
cluster.billboard.height = 56
})
} else if (clusteredEntities.length >= 8) {
combineIconAndLabel(
'./imgs/map_icon/cluster/cluster_02.png',
clusteredEntities.length,
64
).then((item) => {
cluster.billboard.image = item.toDataURL()
cluster.billboard.width = 48
cluster.billboard.height = 48
})
} else {
combineIconAndLabel(
'./imgs/map_icon/cluster/cluster_01.png',
clusteredEntities.length,
64
).then((item) => {
cluster.billboard.image = item.toDataURL()
cluster.billboard.width = 40
cluster.billboard.height = 40
})
}
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM
cluster.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
cluster.billboard.show = true
})
await viewer.dataSources.add(dataSource)
await viewer.flyTo(dataSource)
}
export const clearAllPoints = (viewer: Cesium.Viewer) => {
const entitiesToRemove: Cesium.Entity[] = []
viewer.entities.values.forEach((entity) => {
if (entity.name === MapEntityType.BAITHON_POINT) {
entitiesToRemove.push(entity)
}
})
entitiesToRemove.forEach((entity) => {
viewer.entities.remove(entity)
})
}
const combineIconAndLabel = (url, label, size) => {
const canvas = document.createElement('canvas')
canvas.width = size
canvas.height = size
const ctx = canvas.getContext('2d')
return Cesium.Resource.fetchImage(url).then((image) => {
try {
ctx.drawImage(image, 0, 0)
} catch (e) {
console.log(e)
}
ctx.fillStyle = Cesium.Color.WHITE.toCssColorString()
ctx.font = 'bold 20px Microsoft YaHei'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(label, size / 2, size / 2 + 4)
return canvas
})
}
export const clearWarning = async (viewer: Cesium.Viewer) => {
await addBaithonEquipmentPoints(viewer)
}