cesium实现点聚合效果

该博客介绍了如何使用Cesium的EntityCluster接口实现地图上的点聚合功能,包括官方API的使用、自定义聚合图标的方法。通过调整像素范围和最小聚合数量,实现不同级别的聚合效果。同时,根据聚合数量动态合成新图标,提供了代码示例展示如何结合图片和文字生成聚合图标。
摘要由CSDN通过智能技术生成


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

  • 13
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论
假设有一组地理坐标数据,如下所示: | 纬度 | 经度 | | ---- | ---- | | 31.231 | 121.473 | | 31.231 | 121.475 | | 31.233 | 121.477 | | 31.235 | 121.475 | | 31.237 | 121.473 | | 31.239 | 121.471 | | 31.241 | 121.469 | | 31.243 | 121.471 | | 31.245 | 121.473 | | 31.247 | 121.475 | 我们可以使用Cesium实现聚合,将附近的合并成一个聚合。具体实现步骤如下: 1. 创建Cesium Viewer对象: ```javascript var viewer = new Cesium.Viewer('cesiumContainer'); ``` 2. 将数据转换成Cesium的Entity对象,并添加到Viewer中: ```javascript var entities = []; var positions = [ [31.231, 121.473], [31.231, 121.475], [31.233, 121.477], [31.235, 121.475], [31.237, 121.473], [31.239, 121.471], [31.241, 121.469], [31.243, 121.471], [31.245, 121.473], [31.247, 121.475] ]; for (var i = 0; i < positions.length; i++) { var position = Cesium.Cartesian3.fromDegrees(positions[i][1], positions[i][0]); var entity = new Cesium.Entity({ position: position, point: { pixelSize: 10, color: Cesium.Color.RED } }); entities.push(entity); } viewer.entities.add(entities); ``` 3. 使用Cesium的Cluster实现聚合: ```javascript var pixelRange = 50; var minimumClusterSize = 3; var cluster = new Cesium.Cluster({ pixelRange: pixelRange, minimumClusterSize: minimumClusterSize, enabled: true }); viewer.dataSources.add(cluster); cluster.addEntities(entities); ``` 以上代码中,我们使用了Cesium的Cluster对象,设置了聚合的像素范围和最小聚合数量。最后将Entity添加到Cluster中即可实现聚合。 完整代码如下: ```javascript var viewer = new Cesium.Viewer('cesiumContainer'); var entities = []; var positions = [ [31.231, 121.473], [31.231, 121.475], [31.233, 121.477], [31.235, 121.475], [31.237, 121.473], [31.239, 121.471], [31.241, 121.469], [31.243, 121.471], [31.245, 121.473], [31.247, 121.475] ]; for (var i = 0; i < positions.length; i++) { var position = Cesium.Cartesian3.fromDegrees(positions[i][1], positions[i][0]); var entity = new Cesium.Entity({ position: position, point: { pixelSize: 10, color: Cesium.Color.RED } }); entities.push(entity); } var pixelRange = 50; var minimumClusterSize = 3; var cluster = new Cesium.Cluster({ pixelRange: pixelRange, minimumClusterSize: minimumClusterSize, enabled: true }); viewer.dataSources.add(cluster); cluster.addEntities(entities); ```
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

右弦GISer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值