该功能包含两个部分:
1.加载点集合:点集合数据源可能来源于.kml、.geojson等文件或源自数据库的api接口;
2.创建聚合效果:自定义聚合点样式和聚合数量;
cesium点聚合
1.获取并加载点集合:
//1.从kml文件中加载点集,并生成数据集合
const dataSourcePromise = viewer.dataSources.add(
Cesium.KmlDataSource.load(
"./SampleData/kml/facilities/facilities.kml",
{
camera: viewer.scene.camera,
canvas: viewer.scene.canvas,
clamToGround: true,
}
)
);
//2.从json文件中加载点集,并生成数据集合
const dataSourcePromise = viewer.dataSources.add(
Cesium.GeoJsonDataSource.load(
"./SampleData/json/facilities/facilities.geojson",
{
camera: viewer.scene.camera,
canvas: viewer.scene.canvas,
clamToGround: true,
}
)
);
//3.从api接口加载点集,并生成数据集合
function dataSourceFromApi() {
var dataSource1 = new Cesium.CustomDataSource("dataSource1"); //自定义一个名为dataSource1的空数据集
var dataSourcePromise;
// 通过接口获取数据集
axios.post('/you_api', { key1: value1, key2: value2 }).then(function (response) {
const data = response.data;
if (!data || data.length === 0) return console.log("data is empty!")
for (let i = 0; i < data.entities.length; i++) {
// 对实体进行标注
var item = data.entities[i]; // 遍历获取每一条point数据,假设item是个对象
var img_path = "img/marker1/mark.png"; //标注点的icon
dataSource1.entities.add(new Cesium.Entity({
// name: name,
position: Cesium.Cartesian3.fromDegrees(item.lon, item.lat), //从item对象获取经纬度
billboard: {
// show: false,
image: img_path,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
scale: 1, // 标注点icon缩放比例
width: 26, // 设置标注点icon的高和宽,单位默认时px
height: 36
},
//
label: {
show: true, //是否显示标注点文本
scale: 0.5, //这里非常巧妙的先将字体大小放大一倍在缩小一倍
font: "normal 24px MicroSoft YaHei", //字体
fillColor: Cesium.Color.BLUE.withAlpha(0.7), //字体颜色
text: item.text, //从接口获取点的标记文本
pixelOffset: new Cesium.Cartesian2(0, -50), //文字显示的偏移量
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, //水平居中
verticalOrigin: Cesium.VerticalOrigin.CENTER, //垂直居中
style: Cesium.LabelStyle.FILL,
showBackground: true, //设置文本背景
backgroundColor: Cesium.Color.fromCssColorString("#66ffff") //设置文本背景颜色,
// backgroundColor: Cesium.Color.GRAY.withAlpha(0.6)
}
}))
}
dataSourcePromise = viewer.dataSources.add(dataSource1);
})
return dataSourcePromise
}
2.创建聚合效果:
// 聚合效果
dataSourcePromise.then(function (dataSource) {
const pixelRange = 20;
const minimumClusterSize = 5;
const enabled = true;
dataSource.clustering.enabled = enabled; //聚合开启
dataSource.clustering.pixelRange = pixelRange; //设置像素范围,以扩展显示边框
dataSource.clustering.minimumClusterSize = minimumClusterSize; //设置最小的聚合点数目,超过此数目才能聚合
let removeListener;
//按聚合层级创建对应图标
const pinBuilder = new Cesium.PinBuilder();
var pin100 = pinBuilder
.fromText("100+", Cesium.Color.BLUE, 48)
.toDataURL();
var pin50 = pinBuilder
.fromText("50+", Cesium.Color.BLUE, 48)
.toDataURL();
var pin40 = pinBuilder
.fromText("40+", Cesium.Color.RED, 48)
.toDataURL();
var pin30 = pinBuilder
.fromText("30+", Cesium.Color.RED, 48)
.toDataURL();
var pin20 = pinBuilder
.fromText("20+", Cesium.Color.RED, 48)
.toDataURL();
var pin10 = pinBuilder
.fromText("10+", Cesium.Color.RED, 48)
.toDataURL();
// 10以内聚合图标
const singleDigitPins = new Array(8);
for (let i = 0; i < singleDigitPins.length; ++i) {
singleDigitPins[i] = pinBuilder
.fromText(`${i + 2}`, Cesium.Color.VIOLET, 48)
.toDataURL();
}
customStyle();
function customStyle() {
if (Cesium.defined(removeListener)) {
removeListener();
removeListener = undefined;
} else {
removeListener = dataSource.clustering.clusterEvent.addEventListener(
function (clusteredEntities, cluster) {
cluster.label.show = false;
cluster.billboard.show = true;
cluster.billboard.id = cluster.label.id;
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
if (clusteredEntities.length >= 100) {
cluster.billboard.image = pin100;
} else if (clusteredEntities.length >= 50) {
cluster.billboard.image = pin50;
} else if (clusteredEntities.length >= 40) {
cluster.billboard.image = pin40;
} else if (clusteredEntities.length >= 30) {
cluster.billboard.image = pin30;
} else if (clusteredEntities.length >= 20) {
cluster.billboard.image = pin20;
} else if (clusteredEntities.length >= 10) {
cluster.billboard.image = pin10;
} else {
cluster.billboard.image =
singleDigitPins[clusteredEntities.length - 2];
}
}
);
}
// force a re-cluster with the new styling
const pixelRange = dataSource.clustering.pixelRange;
dataSource.clustering.pixelRange = 0;
dataSource.clustering.pixelRange = pixelRange;
}
})