cesium 使用entity 实现大量poi点聚合保姆级教程(提供图标素材)

需求:

需要在地图上渲染大量的点位,点位太密集了,看起来效果很差,所以需要把某一个相同范围内的点聚合起来显示一个数字,代表这个范围有多少个内容,当相机靠近的时候才把这些定位的详细绘制出来

实现思路:

cesium中已经实现了 EntityCluster 聚合类

enabled: 是否启用集群

pixelRange: 扩展屏幕空间边界框的像素范围。(这个值越大聚合的范围就会越大,显示到屏幕上的点就会越少)

minimumClusterSize:可聚类的屏幕空间对象的最小数量。

clusterBillboards: 是否对实体的广告牌进行聚类。

clusterLabels: 是否对实体的标签进行聚类。

clusterPoints: 是否对实体的点进行聚类。

show: 确定是否显示集群中的实体。

实现代码:

import * as Cesium from 'cesium';
import type { Viewer } from 'cesium';

export default class DrawService {
  viewer: Viewer;

  dataSource: any; // 聚合点的容器

  removeListener: any;

  constructor(viewer: Viewer) {
    this.viewer = viewer;
    this.dataSource = new Cesium.CustomDataSource('myData');
    this.initClustering();
    this.viewer.dataSources.add(this.dataSource);
  }


  // 有聚合功能的点用这个方法
  drawclusteringPoint(positions: Cesium.Cartesian3, imgUrl: string, text?: string) {
    const billboard = this.dataSource.entities.add({
      position: positions,
      billboard: {
        image: imgUrl, // default: undefined
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        // pixelOffset: new Cesium.Cartesian2(0, -50), // default: (0, 0)
        // eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0), // default
        // horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // default
        // verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // default: CENTER
        scale: 0.4, // default: 1.0
        // color: Cesium.Color.LIME, // default: WHITE
        // rotation: Cesium.Math.PI_OVER_FOUR, // default: 0.0
        // alignedAxis: Cesium.Cartesian3.ZERO, // default
        // width: 100, // default: undefined
        // height: 25, // default: undefined
      },
    });
    if (text) {
      billboard.label = new Cesium.LabelGraphics({
        text: text,
        show: false,
        font: '14px Helvetica',
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(0, -20),
      });
    }
    return billboard;
  }

  initClustering() {
    const that = this;
    const dataSourcePromise = this.viewer.dataSources.add(this.dataSource);
    dataSourcePromise.then(function (dataSource) {
      const pixelRange = 50; // 增加这个值可以使平面中聚合的访问更大,显示的点就会变少很多
      const minimumClusterSize = 3;
      const enabled = true;
      dataSource.clustering.enabled = enabled; // 是否聚合
      dataSource.clustering.pixelRange = pixelRange;
      dataSource.clustering.minimumClusterSize = minimumClusterSize;
      that.customStyle();
    });
  }

  customStyle() {
    const that = this;
    const pinBuilder = new Cesium.PinBuilder();
    const singleDigitPins = new Array(8);
    for (let i = 0; i < singleDigitPins.length; ++i) {
      singleDigitPins[i] = pinBuilder.fromText(`${i + 2}`, Cesium.Color.VIOLET, 48).toDataURL();
    }
    if (Cesium.defined(that.removeListener)) {
      that.removeListener && that.removeListener();
      that.removeListener = undefined;
    } else {
      that.removeListener = that.dataSource.clustering.clusterEvent.addEventListener(function (
        clusteredEntities,
        cluster
      ) {
        cluster.label.show = false;
        cluster.label.font = '14px Helvetica';
        cluster.billboard.show = true;
        cluster.billboard.id = cluster.label.id;
        cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;

        if (clusteredEntities.length >= 100) {
          cluster.billboard.image = './assets/img/cluster/100.png';
          cluster.billboard.scale = 1.4;
        } else if (clusteredEntities.length >= 50) {
          cluster.billboard.image = './assets/img/cluster/50.png';
          cluster.billboard.scale = 1.3;
        } else if (clusteredEntities.length >= 20) {
          cluster.billboard.image = './assets/img/cluster/20.png';
          cluster.billboard.scale = 1.2;
        } else if (clusteredEntities.length >= 10) {
          cluster.billboard.image = './assets/img/cluster/10.png';
          cluster.billboard.scale = 1.2;
        } else if (clusteredEntities.length >= 3) {
          cluster.billboard.image = './assets/img/cluster/3plus.png';
          // cluster.billboard.image = combineIconAndLabel(
          //   './assets/img/cluster/1.png',
          //   clusteredEntities.length,
          //   44
          // );
          // cluster.billboard.scale = 1.2;
          // cluster.billboard.image = singleDigitPins[clusteredEntities.length - 2];
          // cluster.billboard.scale = 0.8;
        }
      });
    }
    const { pixelRange } = that.dataSource.clustering;
    that.dataSource.clustering.pixelRange = 0;
    that.dataSource.clustering.pixelRange = pixelRange;
  }

  setSoucerceShowOrHide(isShow: boolean) {
    this.dataSource.entities.values.forEach((entity) => {
      entity.show = isShow;
    });
  }

  // 根据某一类来控制显示和隐藏
  setResourceShowOrHideByType(type: string, isShow: boolean) {
    this.dataSource.entities.values.forEach((entity) => {
      if (entity.workName === type) {
        entity.show = isShow;
      }
    });
  }
}

图标素材:

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cesium中的entity聚合是指将多个entity合并为一个。这可以用于简化场景中的元素数量,提高性能。一个例子是将多个建筑物合并为一个大型建筑群。这可以通过创建一个新的entity,然后将其他entity添加到该entity的children属性中来实现。这样,所有的子entity都将成为该聚合entity的一部分,并且可以通过缩放、平移、旋转等方式一起操作。例如,可以通过以下代码将三个entity合并为一个: ```javascript var aggregationEntity = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), model: { uri: 'path/to/aggregationModel.glb' } }); aggregationEntity.name = 'Aggregation'; var entity1 = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), model: { uri: 'path/to/model1.glb' } }); var entity2 = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), model: { uri: 'path/to/model2.glb' } }); var entity3 = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883), model: { uri: 'path/to/model3.glb' } }); aggregationEntity.children.add(entity1); aggregationEntity.children.add(entity2); aggregationEntity.children.add(entity3); ``` 在这个例子中,我们创建了一个聚合entity `aggregationEntity`,并将其位置设置为经纬度坐标(-75.59777, 40.03883)。我们还创建了三个子entity `entity1`、 `entity2` 和 `entity3`,并将它们的位置设置为相同的经纬度坐标。然后,我们将这三个entity添加到聚合entity的children属性中。最后,我们将聚合entity的模型设置为一个包含三个建筑物的模型。这样,我们就创建了一个包含三个建筑物的大型建筑群entity
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值