Cesium实战系列文章总目录
:
传送门
1.实现效果
2.实现方法
2.1官方API
Cesium官方提供了EntityCluster
接口,可以实现广告牌、点、标签的聚合效果。
官方API:传送门
官方文档中EntityCluster的配置项参数:
属性 | 说明 |
---|---|
enabled | 是否开启聚合功能 |
pixelRange | 开启聚合的像素边界范围大小 |
minimumClusterSize | 最少聚合对象的数量 |
clusterBillboards | 是否聚合广告牌 |
clusterLabels | 是否聚合标签 |
clusterPoints | 是否聚合点 |
shows | 即聚合后是否显示 |
官方沙盒聚合例子参考:传送门
2.2聚合图标
2.2.1原始图标
Cesium提供的图标,由PinBuilder
类提供
官方API:传送门
可以在原始图标中添加新图标或者文字的形式生成新图标,但新图标的外形样式是固定的。
2.2.2 自定义图片
也可以根据聚合数量进行分级设置
不同的聚合图标。
2.2.3 图片文字合成新图标
本文使用固定的分级图标与聚合点位数量实时合成新图标
的方式。
具体将图片与文字合成新图标的方法可以参考上一篇博客:传送门
2.3代码实现:
总体实现代码如下:
/**
* @description: 点聚合功能效果
* @param {*} viewer
* @return {*}
*/
function initCluster(viewer) {
new Cesium.GeoJsonDataSource().load("./data/sz_poi.geojson").then(dataSource => {
viewer.dataSources.add(dataSource);
// 设置聚合参数
dataSource.clustering.enabled = true;
dataSource.clustering.pixelRange = 60;
dataSource.clustering.minimumClusterSize = 2;
// foreach用于调用数组的每个元素,并将元素传递给回调函数。
dataSource.entities.values.forEach(entity => {
// 将点拉伸一定高度,防止被地形压盖
entity.position._value.z += 50.0;
// 使用大小为64*64的icon,缩小展示poi
entity.billboard = {
image: './icons/poi.png',
width: 32,
height: 32,
};
entity.label = {
text: 'POI',
font: 'bold 15px Microsoft YaHei',
// 竖直对齐方式
verticalOrigin: Cesium.VerticalOrigin.CENTER,
// 水平对齐方式
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
// 偏移量
pixelOffset: new Cesium.Cartesian2(15, 0),
}
});
// 添加监听函数
dataSource.clustering.clusterEvent.addEventListener(
function(clusteredEntities, cluster) {
// 关闭自带的显示聚合数量的标签
cluster.label.show = false;
cluster.billboard.show = true;
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
// 根据聚合数量的多少设置不同层级的图片以及大小
if (clusteredEntities.length >= 20) {
cluster.billboard.image = combineIconAndLabel('./icons/cluster_4.png', clusteredEntities.length, 64);
cluster.billboard.width = 72;
cluster.billboard.height = 72;
} else if (clusteredEntities.length >= 12) {
cluster.billboard.image = combineIconAndLabel('./icons/cluster_3.png', clusteredEntities.length, 64);
cluster.billboard.width = 56;
cluster.billboard.height = 56;
} else if (clusteredEntities.length >= 8) {
cluster.billboard.image = combineIconAndLabel('./icons/cluster_2.png', clusteredEntities.length, 64);
cluster.billboard.width = 48;
cluster.billboard.height = 48;
} else {
cluster.billboard.image = combineIconAndLabel('./icons/cluster_1.png', clusteredEntities.length, 64);
cluster.billboard.width = 40;
cluster.billboard.height = 40;
}
}
)
});
}
/**
* @description: 将图片和文字合成新图标使用(参考Cesium源码)
* @param {*} url:图片地址
* @param {*} label:文字
* @param {*} size:画布大小
* @return {*} 返回canvas
*/
function combineIconAndLabel(url, label, size) {
// 创建画布对象
let canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
let ctx = canvas.getContext("2d");
let promise = new Cesium.Resource.fetchImage(url).then(image => {
// 异常判断
try {
ctx.drawImage(image, 0, 0);
} catch (e) {
console.log(e);
}
// 渲染字体
// font属性设置顺序:font-style, font-variant, font-weight, font-size, line-height, font-family
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);
return canvas;
});
return promise;
}