Vue+Cesium加载GeoJSON并设置entity.billboard,在组件销毁/释放实体entity时报错

**背景:**Vue+Cesium加载GeoJSON并设置entity.billboard,在组件销毁/释放实体entity时报错:TypeError: Cannot read properties of undefined (reading '_textureAtlas') at Billboard.setImage (webpack-internal:///./node_modules/cesium/Source/Scene/Billboard.js:1268:98)

复制代码
  async estimate() {
      try {
        // 使用Promise.all来同时处理多个axios请求
        const [floodLayerResponse, alterLayerResponse] = await Promise.all([
          axios.get('/api' + this.featuresLayer.model.floodLayer),
          axios.get('/api' + this.featuresLayer.model.alterLayer)
        ]);

        // 处理floodLayer数据
        const floodDs = await Cesium.GeoJsonDataSource.load(floodLayerResponse.data, {
          clampToGround: true
        });
        viewer.dataSources.add(floodDs);

        floodDs.entities.values.forEach(entity => {
          entity.polygon.outline = false;
          let properties = entity.properties;
          const score = properties['_degree']['_value'];
          let color;
          if (score === 1 || score === 2) {
            color = Cesium.Color.fromCssColorString("#fdfdfd");
          } else if (score === 3 || score === 4 || score === 5) {
            color = Cesium.Color.fromCssColorString("rgba(160,190,253,0.7)");
          } else {
            color = Cesium.Color.fromCssColorString("rgba(6,76,169,0.87)");
          }
          entity.polygon.material = color;
        });

        // 处理alterLayer数据
        alterDs = await Cesium.GeoJsonDataSource.load(alterLayerResponse.data);
        viewer.dataSources.add(alterDs);

        alterDs.entities.values.forEach(entity => {
          if(!entity.billboard){
            entity.billboard=new Cesium.BillboardGraphics();
          }
          entity.billboard = {
            image: picUrl, // 确保url已经被定义
            scale: 2,
            width: 16,
            height: 16,
            pixelOffset: new Cesium.Cartesian2(0, -20)
          };
        });
        this.descriptionVisi=true;

      } catch (error) {
        console.error('Error loading layers:', error);
      }},

释放资源报错: TypeError: Cannot read properties of undefined (reading '_textureAtlas') at Billboard.setImage)

复制代码
 viewer.entities.removeAll();
 viewer.scene.primitives.removeAll();

将设置了billborad的entities先释放,在释放所有primitives

复制代码
      //设置了billbord数据需单独先去除,否则报错:TypeError: Cannot read properties of undefined (reading '_textureAtlas')at Billboard.setImage (webpack-internal:///./node_modules/cesium/Source/Scene/Billboard.js:1268:98)
      alterDs.entities.removeAll();
      viewer.scene.primitives.removeAll();
      this

总结:

Cesium 中遇到 TypeError: Cannot read properties of undefined (reading '_textureAtlas') 这类错误通常与尝试访问未正确初始化或已被销毁的对象的属性有关。在你提到的场景中,这个错误发生在尝试设置 Billboardimage 属性时,而该 Billboard 或其相关的资源(如纹理图集 _textureAtlas)可能已经不再有效或未正确加载。

这个问题可能由几个原因引起:

  1. Billboard 已被销毁 :在 Cesium 中,如果你移除了包含 BillboardEntity 或直接从 PrimitiveCollection 中移除了 Billboard,然后尝试再次访问或修改它,就可能导致此类错误。

  2. 资源加载问题 :如果 Billboard 使用的图像资源在尝试设置时没有正确加载,也可能导致内部状态不一致。

  3. Cesium 内部状态问题:在某些极端情况下,Cesium 的内部状态可能因为错误的使用或与其他库的冲突而变得不一致。

解决步骤

  1. 检查 Billboard 的存在性

    在尝试修改 Billboard 之前,确保它仍然存在且未被销毁。你可以通过检查其 isDestroyed() 方法(如果 Cesium 版本支持)或使用简单的条件语句来验证。

    if (billboard && !billboard.isDestroyed()) {
    billboard.image = 'new-image-url.png';
    }

  2. 注意:isDestroyed() 方法可能在某些 Cesium 版本中不可用。

  3. 确保资源已加载

    如果你正在动态更改 Billboard 的图像,请确保新的图像 URL 是有效的,并且图像已经加载到 Cesium 中。你可以使用 Cesium 的 Resource 类或监听图像加载事件来确保图像已准备好。

  4. 安全地移除 Entities

    当你需要移除所有 entities 时,确保你正确地从 Cesium 的 viewer.entities 中移除了它们。你可以遍历并逐个移除,或者如果可能,直接清空整个集合(注意,直接清空可能会导致事件监听器等问题)。

    viewer.entities.removeAll();

如果你需要更细致地控制移除过程,可以遍历 entities 集合并逐个调用 destroy() 方法(尽管 removeAll() 通常已经足够)。

  1. 检查 Cesium 版本

    确保你使用的 Cesium 版本没有已知的此类问题的 bug。有时,升级到最新版本可以解决这类问题。

  2. 查看控制台和网络请求

    使用浏览器的开发者工具查看控制台输出和网络请求,看是否有与图像加载或 Cesium 内部错误相关的更多信息。

  3. 考虑错误处理和日志记录

    在你的应用中增加错误处理和日志记录,以帮助诊断何时何地发生了此类问题。

相关推荐
用户479492835691521 分钟前
你每天都在用的 JSON.stringify ,V8 给它开了“加速通道”
前端·chrome·后端
狗狗摇屁屁23 分钟前
JS手写防抖
开发语言·javascript·ecmascript
JIngJaneIL27 分钟前
基于java+ vue办公管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
清风细雨_林木木32 分钟前
Chart.js和 Echart的区别
开发语言·javascript·ecmascript
静待雨落38 分钟前
Electron无边框窗口如何拖拽以及最大化和还原窗口
前端·electron
沐泽__1 小时前
iframe内嵌页面双向通信
前端·javascript·chrome
小北方城市网1 小时前
第4 课:Vue 3 路由与状态管理实战 —— 从单页面到多页面应用
前端·javascript·vue.js
ohyeah1 小时前
用 Vue3 + Coze API 打造冰球运动员 AI 生成器:从图片上传到风格化输出
前端·vue.js·coze
interception1 小时前
爬虫逆向,瑞数6,补环境,国家专利
javascript·爬虫·python·网络爬虫
Dragon Wu1 小时前
TailWindCss 核心功能总结
前端·css·前端框架·postcss