cesium聚合效果(一):dataSource

1、概述

通过cesium中dataSource自带的clustering来实现billboard数据的聚合显示效果,并根据数据类别设置显示不同的billboard图标。

2、数据处理

将后端返回的json数据处理成标准的geojson格式,如果后端返回的数据或者使用的测试数据已是geojson格式,请忽略此处。

javascript 复制代码
//数据处理--后端返回数据转换成geojson数据
const data2Geojson = (data) => {
    const geojson = {
        "type": "FeatureCollection",
        "features": []
    }
    data.forEach(item => {
        geojson.features.push({
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "icon": item.icon,
                "coordinates": [parseFloat(item.longitude), parseFloat(item.latitude)]
            },
            "properties": {
                ...item
            }
        })
    })
    return geojson;
}

3、聚合实现

加载geojson数据,完成聚合效果的显示和清除操作。

ini 复制代码
import pic from "@/assets/clusterIcon/facility.gif";  //默认billboard
import cluster1 from "@/assets/clusterIcon/cluster1.png";  
import cluster2 from "@/assets/clusterIcon/cluster2.png";  
import cluster3 from "@/assets/clusterIcon/cluster3.png";  
//实现聚合效果
let dataSourceCollection = null;
let dataSourcePromise = null;
const setEntityCluster = async(data) => {
    await removeEntityCluster(); //清除上一次绘制的聚合效果
    let geojson = await data2Geojson(data); //数据转换为geojson格式
    //读取geojson,并将数据源添加至DataSourceCollection
    dataSourceCollection = new Cesium.DataSourceCollection();
    dataSourcePromise = dataSourceCollection.add(Cesium.GeoJsonDataSource.load(geojson));
    dataSourcePromise.then(dataSource =>{
        // 加载geojson
        viewer.dataSources.add(dataSource);
        //命名用于后续删除
        dataSource.name = 'entityClusterGeojson';
        // 视角切换到geojson
        viewer.flyTo(dataSource.entities.values);
        //设置entity属性
        dataSource.entities.values.forEach(entity => {
            let properties = entity.properties;
            let icon = pic;
            if(properties.type._value == "1"){
                icon = cluster1;
            }else if(properties.type._value == "2"){
                icon = cluster2;
            }else{
                icon = cluster3;
            }
            entity.uuid = properties.id._value;
            entity.name = properties.name._value;
            entity.billboard = {
                image: icon,
                width: 36,
                height: 36,
            };
            entity.label = {
                show: true,
               text: properties.name._value || 'test',
                font: 'bold 15px Microsoft YaHei', 
                verticalOrigin: Cesium.VerticalOrigin.CENTER,// 竖直对齐方式
                horizontalOrigin: Cesium.HorizontalOrigin.LEFT,  // 水平对齐方式
                pixelOffset: new Cesium.Cartesian2(15, 0),// 偏移量
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,//贴地
                disableDepthTestDistance: Number.POSITIVE_INFINITY,//一直显示,不被地形等遮挡
            };
            entity.type = properties.type._value;
        })
        //聚合参数设置
        dataSource.clustering.enabled = true;  //开启聚合功能
        dataSource.clustering.pixelRange = 46;  //聚合像素范围
        dataSource.clustering.minimumClusterSize = 1; //最小聚合数量
        let removeListener;
         const customStyle = () => {
            if (Cesium.defined(removeListener)) {
                removeListener();
                removeListener = undefined;
            } else {
                removeListener = dataSource.clustering.clusterEvent.addEventListener(
                    (clusteredEntities, cluster) => {
                        if (cluster.label.id.length == 0 || !cluster.label.id[0]) {
                            cluster.label.show = false;
                            cluster.billboard.show = false;
                            return;
                        }
                        //设置聚合后billboard样式,当有多个图标时,显示第一个图标和对应label
                        const img = cluster.label.id[0].billboard.image._value;
                        cluster.label.show = true;
                        cluster.label.text = cluster.label.id[0].label.text._value || "";
                        cluster.label.showBackground = true;
                        cluster.label.verticalOrigin = Cesium.VerticalOrigin.CENTER;
                        cluster.label.horizontalOrigin = Cesium.HorizontalOrigin.CENTER;
                        cluster.label.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
                        cluster.label.disableDepthTestDistance = Number.POSITIVE_INFINITY;
                        cluster.label.pixelOffset = new Cesium.Cartesian2(0, 10);
                        cluster.label.font = " bold 15px Microsoft YaHei";
                        cluster.label.backgroundColor = Cesium.Color.ORANGE.withAlpha(0.2);
                        cluster.billboard.show = true;
                        cluster.billboard.id = cluster.label.id;
                        cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
                        cluster.billboard.width = 36;
                        cluster.billboard.height = 36;
                        cluster.billboard.image = img;
                        cluster.entityType = "entityCluster";
                        cluster.billboard.horizontalOrigin = Cesium.HorizontalOrigin.CENTER;
                        cluster.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
                        cluster.billboard.disableDepthTestDistance = Number.POSITIVE_INFINITY;
                    }
                )
            }
            const pixelRange = dataSource.clustering.pixelRange;
            dataSource.clustering.pixelRange = 0;
            dataSource.clustering.pixelRange = pixelRange;
        }
        //设置鼠标点击事件
        let isFirst = true; //设置标识,避免重复执行点击事件
        viewer.screenSpaceEventHandler.setInputAction((click) => {
            const pickedObject = viewer.scene.pick(click.position);
            if (pickedObject && pickedObject.id && pickedObject.id instanceof Array){
                //获取点击数据对象
                let obj = data.find((item) => item.id == pickedObject.id[0].uuid);
                if(obj && isFirst){
                    isFirst = false;
                    //自定义后续操作逻辑...
                    setTimeout(() => {
                        isFirst = true;
                    }, 1000)
                }  
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
        customStyle();//调用聚合监听事件
    })
    
   
}
//清除聚合
const removeEntityCluster = () =>{
    dataSourceCollection = dataSourceCollection && dataSourceCollection.destroy();
    if(dataSourcePromise){
        viewer.dataSources.remove(viewer.dataSources.getByName("entityClusterGeojson")[0])
    }
},

4、实现效果

项目地址:github.com/DLFouge/vue...

欢迎指正与star

相关推荐
开心工作室_kaic1 小时前
ssm111基于MVC的舞蹈网站的设计与实现+vue(论文+源码)_kaic
前端·vue.js·mvc
迂 幵2 小时前
vue el-table 超出隐藏移入弹窗显示
javascript·vue.js·elementui
上趣工作室2 小时前
vue2在el-dialog打开的时候使该el-dialog中的某个输入框获得焦点方法总结
前端·javascript·vue.js
家里有只小肥猫2 小时前
el-tree 父节点隐藏
前端·javascript·vue.js
_xaboy3 小时前
开源项目低代码表单设计器FcDesigner扩展自定义的容器组件.例如col
vue.js·低代码·开源·动态表单·formcreate·低代码表单·可视化表单设计器
_xaboy3 小时前
开源项目低代码表单设计器FcDesigner扩展自定义组件
vue.js·低代码·开源·动态表单·formcreate·可视化表单设计器
mez_Blog4 小时前
Vue之插槽(slot)
前端·javascript·vue.js·前端框架·插槽
爱睡D小猪4 小时前
vue文本高亮处理
前端·javascript·vue.js
paopaokaka_luck4 小时前
基于Spring Boot+Vue的多媒体素材管理系统的设计与实现
java·数据库·vue.js·spring boot·后端·算法
开心工作室_kaic4 小时前
ssm102“魅力”繁峙宣传网站的设计与实现+vue(论文+源码)_kaic
前端·javascript·vue.js