cesium实现点聚合效果

文章目录

    • 1.实现效果
    • 2.实现方法
      • 2.1官方API
      • 2.2聚合图标
        • 2.2.1原始图标
        • 2.2.2 自定义图片
        • 2.2.3 图片文字合成新图标
      • 2.3代码实现:

Cesium实战系列文章总目录: 传送门

1.实现效果

2.实现方法

2.1官方API

Cesium官方提供了EntityCluster接口,可以实现广告牌、点、标签的聚合效果。
官方API:传送门
cesium实现点聚合效果_第1张图片官方文档中EntityCluster的配置项参数:

属性 说明
enabled 是否开启聚合功能
pixelRange 开启聚合的像素边界范围大小
minimumClusterSize 最少聚合对象的数量
clusterBillboards 是否聚合广告牌
clusterLabels 是否聚合标签
clusterPoints 是否聚合点
shows 即聚合后是否显示

官方沙盒聚合例子参考:传送门

2.2聚合图标

2.2.1原始图标

Cesium提供的图标,由PinBuilder类提供
官方API:传送门
cesium实现点聚合效果_第2张图片
可以在原始图标中添加新图标或者文字的形式生成新图标,但新图标的外形样式是固定的。

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;
}

你可能感兴趣的:(cesium,gis,cesium)