iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详解cesium实现大批量POI点位聚合渲染优化方案
  • 467
分享到

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

cesium大批量POI点位聚合渲染cesiumPOI 2023-05-19 05:05:54 467人浏览 八月长安
摘要

目录前言思考开发使用 前言 cesium目前只提供了entityCluster这个聚合类,使打点聚合更方便快捷的实现,但是一般在真正做项目的时候,大家会经常碰到成千上万个甚至几十万

前言

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点位聚合渲染的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解cesium实现大批量POI点位聚合渲染优化方案

本文链接: https://www.lsjlt.com/news/212561.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作