通过Primitive解决数据量过大时Entity卡顿及点位过导致密观感较差的问题

一、遇到的问题
在三维开发中如果数据量过大时使用Entity会出现数据加载耗时较长、页面卡顿等情况,但是如果使用Primitive又没有聚合图的功能,在camera高度较高时点位密密麻麻观感比较差。

二、解决方案
1、实现Primitive聚合图
通过查找资料发现可以通过模拟EntityCluster这个类的实现方式,利用源码中的算法,改成Primitive的实现方式。

缺点:数据量太大的的时候,camera高度变化时还是会有卡顿的现象

2、热力图
可以设置在camera高于一定高度时显示热力图、高度较低时再显示Primitive
1)直接加载iServer热力图

缺点:会被三维挡住(或许可以使用S3MTilesLayer的coverImageryLayer 方法尝试一下)

2)通过heatmap.js加载

缺点:不能随高度变化进行点位变化,通过随高度修改radius参数的方式也不够美观。

3、设置广告牌scaleByDistance 参数
scaleByDistance 参数可以根据广告牌与相机的距离,获取或设置广告牌的远近缩放属性。

三、具体操作
1、Primitive聚合图
在Vue中可以通过以下方式来使用PrimitiveCluster

let cesiumLib = require("./PrimitiveCluster.js")
let PrimitiveCluster = cesiumLib.default;
 
// 创建广告牌集合
let billboardsCollectionCombine = Viewer.scene.primitives.add(
      new Cesium.BillboardCollection({
         scene: Viewer.scene,
      })
);
// 交给聚合类进行处理
this.addPrimitiveClusterToScene(billboardsCollectionCombine);
 
//创建具有指定初始属性的广告牌并将其添加到集合中
for (let i = 0; i < features.length; i++) {
    const feature = features[i];
    // 带图片的点
    billboardsCollectionCombine.add({
       id: i,
       name: "HwVideo",
       image: "./static/img/extendApp/icon/camera-blue.png",
       width: 32,
       height: 32,
       scale: 1,
       show: true,
       position: Cesium.Cartesian3.fromDegrees(feature.longitude, feature.latitude, 15),
    });
}
 
addPrimitiveClusterToScene(data,isPrimitiveCollection = true){
    formatClusterPoint(data,isPrimitiveCollection);
 
      // 整理聚合数据
      function formatClusterPoint(data,isPrimitiveCollection){
        let scene = Viewer.scene;
        let primitivecluster = new PrimitiveCluster();
        let primitivesCollection = new Cesium.PrimitiveCollection();
 
        //与entitycluster相同设置其是否聚合 以及最大最小值
        primitivecluster.enabled = true;
        primitivecluster.pixelRange = 60;
        primitivecluster.minimumClusterSize = 2;
 
        let billboardsCollectionCombine;
        if(isPrimitiveCollection){
          billboardsCollectionCombine = data;
        }else{
          billboardsCollectionCombine = scene.primitives.add(
            new Cesium.BillboardCollection({
              scene: scene,
            })
          );
          //后面设置聚合的距离及聚合后的图标颜色显示与官方案例一样
          for (let i = 0; i < data.length; i++) {
            const feature = data[i];
            const position = feature.position;
            // 带图片的点
            billboardsCollectionCombine.add({
              image: "./static/img/extendApp/icon/facility.gif",
              // width: 32,
              // height: 32,
              scale: 1,
              position,
            });
          }
        }
        primitivecluster._billboardCollection = billboardsCollectionCombine;
        // 同时在赋值时调用_initialize方法
        primitivecluster._initialize(scene,500);
 
        primitivesCollection.add(primitivecluster);
        let primitives = Viewer.scene.primitives.add(primitivesCollection);
 
        let pinBuilder = new Cesium.PinBuilder();
        let pin10000 = pinBuilder.fromText('10000+', Cesium.Color.RED, 65).toDataURL();
        let pin5000 = pinBuilder.fromText('5000+', Cesium.Color.ORANGE, 65).toDataURL();
        let pin1000 = pinBuilder.fromText('1000+', Cesium.Color.YELLOW, 65).toDataURL();
 
        primitivecluster.clusterEvent.addEventListener((clusteredEntities, cluster) => {
            // 关闭自带的显示聚合数量的标签
            cluster.label.show = false;
            cluster.billboard.show = true;
            cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
            cluster.billboard._dirty = false;
            
            if (clusteredEntities.length >= 10000) {
                cluster.billboard.image = pin10000;
            } else if (clusteredEntities.length >= 5000) {
                cluster.billboard.image = pin5000;
            } else if (clusteredEntities.length >= 1000) {
                cluster.billboard.image = pin1000;
            } else {
              cluster.billboard.image = pinBuilder.fromText(clusteredEntities.length, Cesium.Color.VIOLET, 65).toDataURL()
            }
          }
        );
        return primitivecluster;
     };
 }
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值