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. 考虑错误处理和日志记录

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

相关推荐
浮游本尊6 分钟前
React 18.x 学习计划 - 第四天:React Hooks深入
前端·学习·react.js
future_studio28 分钟前
聊聊 Unity(小白专享、C# 小程序 之 日历、小闹钟)
前端·html
Yeats_Liao1 小时前
Go Web 编程快速入门 · 04 - 请求对象 Request:头、体与查询参数
前端·golang·iphone
祈祷苍天赐我java之术1 小时前
Redis 数据类型与使用场景
java·开发语言·前端·redis·分布式·spring·bootstrap
草莓熊Lotso2 小时前
C++ 方向 Web 自动化测试入门指南:从概念到 Selenium 实战
前端·c++·python·selenium
JS.Huang2 小时前
【JavaScript】原生函数
开发语言·javascript·ecmascript
Olrookie2 小时前
若依前后端分离版学习笔记(二十)——实现滑块验证码(vue3)
java·前端·笔记·后端·学习·vue·ruoyi
533_3 小时前
[vue] dayjs 显示实时时间
前端·javascript·vue.js
故事与他6453 小时前
XSS_and_Mysql_file靶场攻略
前端·学习方法·xss
ftpeak4 小时前
JavaScript性能优化实战
开发语言·javascript·性能优化