文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

详解cesium实现大批量POI点位聚合渲染优化方案

2023-05-19 05:15

关注

前言

cesium目前只提供了entityCluster这个聚合类,使打点聚合更方便快捷的实现,但是一般在真正做项目的时候,大家会经常碰到成千上万个甚至几十万个点位需要聚合打点,那这时候你如果还是用entity去实现的话,怕是要被用户按在地上疯狂摩擦,摩擦。。。?

思考

我们可以通过模拟entityCluster这个类的实现方式,利用源码中的算法,改成primitive的实现方式;

开发

拉下cesium的源码,搜EntityCluster关键字,我们可以找到EntityCluster.js这个文件,那么这个代码就是实现聚合的核心逻辑,接下来我们可以复制一份出来,将EntityCluster全部改为PrimitiveCluster,接着getScreenSpacePositions这个方法里将entity的逻辑删除,否则会因为item.id为entity对象为空导致报错

function getScreenSpacePositions(
  collection,
  points,
  scene,
  occluder,
  entityCluster
) {
  if (!defined(collection)) {
    return;
  }
  const length = collection.length;
  for (let i = 0; i < length; ++i) {
    const item = collection.get(i);
    item.clusterShow = false;
    if (
      !item.show ||
      (entityCluster._scene.mode === SceneMode.SCENE3D &&
        !occluder.isPointVisible(item.position))
    ) {
      continue;
    }
    // const canClusterLabels =
    //   entityCluster._clusterLabels && defined(item._labelCollection);
    // const canClusterBillboards =
    //   entityCluster._clusterBillboards && defined(item.id._billboard);
    // const canClusterPoints =
    //   entityCluster._clusterPoints && defined(item.id._point);
    // if (canClusterLabels && (canClusterPoints || canClusterBillboards)) {
    //   continue;
    // }
    const coord = item.computeScreenSpacePosition(scene);
    if (!defined(coord)) {
      continue;
    }
    points.push({
      index: i,
      collection: collection,
      clustered: false,
      coord: coord,
    });
  }
}

好了,源码大体就是改这么多了,接下来就是怎么用;

使用

import PrimitiveCluster from "@/utils/cesiumCtrl/primitiveCluster";
// 初始化标签实例
const billboardsCollectionCombine = new Cesium.BillboardCollection();
// 初始化实体
const primitives = viewer.scene.primitives.add(
  new Cesium.PrimitiveCollection()
);
getGeojson("/json/schools.geojson").then(({ res }) => {
    // 先获取点位数据
    console.log(res);
    const { features } = res;
    formatClusterPoint(features);
  });
// 整理聚合数据
const formatClusterPoint = (features) => {
  var scene = viewer.scene;
  var primitivecluster = new PrimitiveCluster();
  //与entitycluster相同设置其是否聚合 以及最大最小值
  primitivecluster.enabled = true;
  primitivecluster.pixelRange = 60;
  primitivecluster.minimumClusterSize = 2;
  // primitivecluster._pointCollection = pointCollection;
  // primitivecluster._labelCollection = labelCollection;
  for (let i = 0; i < features.length; i++) {
    const feature = features[i];
    const coordinates = feature.geometry.coordinates;
    const position = Cesium.Cartesian3.fromDegrees(
      coordinates[0],
      coordinates[1]
    );
    // 带图片的点
    billboardsCollectionCombine.add({
      image: "/images/mark-icon.png",
      width: 32,
      height: 32,
      position,
    });
  }
  // 将数据传给primitivecluster的标签属性
  primitivecluster._billboardCollection = billboardsCollectionCombine;
  // 初始化
  primitivecluster._initialize(scene);
  // 将标签数据添加到实体中
  primitives.add(primitivecluster);
  // 监听相机缩放
  primitivecluster.clusterEvent.addEventListener(
    (clusteredEntities, cluster) => {
      // 关闭自带的显示聚合数量的标签
      cluster.label.show = false;
      cluster.billboard.show = true;
      cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
      // 根据聚合数量的多少设置不同层级的图片以及大小
      cluster.billboard.image = combineIconAndLabel(
        "/images/school-icon.png",
        clusteredEntities.length,
        64
      );
      // cluster.billboard.image = "/images/school-icon.png";
      cluster.billboard._imageHeight = 60;
      cluster.billboard._imageWidth = 60;
      cluster.billboard._dirty = false;
      cluster.billboard.width = 40;
      cluster.billboard.height = 40;
    }
  );
  return primitivecluster;
};

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.BLACK.toCssColorString();
    ctx.font = "bold 20px Microsoft YaHei";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(label, size / 2, size / 2);
    return canvas;
  });
  return promise;
}

ok,以上就是完整的使用方法,主要是如何使用,不然会造成canvas相关方面的报错等等;

详细源码细节可以查看:github.com/tingyuxuan2… ,此开源项目集合了目前常用的一些三维动画场景,还在不断更新中;

以上就是详解cesium实现大批量POI点位聚合渲染优化方案的详细内容,更多关于cesium大批量POI点位聚合渲染的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯