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

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

相关推荐
吴声子夜歌4 分钟前
JavaScript——函数
开发语言·javascript·ecmascript
SuperEugene9 分钟前
Vue3 + Element Plus 表单开发实战:防重复提交、校验、重置、loading 统一|表单与表格规范篇
前端·javascript·vue.js
SuperEugene11 分钟前
Vue3 + Element Plus 中后台弹窗规范:开闭、传参、回调,告别弹窗地狱|Vue 组件与模板规范篇
开发语言·前端·javascript·vue.js·前端框架
桜吹雪12 分钟前
在前端运行Qwen3.5原生多模态模型
前端·人工智能·机器学习
孟祥_成都14 分钟前
前端下午茶:这 3 个网页特效建议收藏(送源码)
前端·javascript·css
SuperEugene14 分钟前
VXE-Table 4.x 实战规范:列配置 + 合并单元格 + 虚拟滚动,避坑卡顿 / 错乱 / 合并失效|表单与表格规范篇
开发语言·前端·javascript·vue.js·前端框架·vxetable
qq_2837200519 分钟前
WebGL基础教程(十四):投影矩阵深度解析——正交 vs 透视,从公式推导到实战
线性代数·矩阵·webgl·正交·投影
火车叼位27 分钟前
Volta 下 `corepack` 失踪之谜:问题不在 Node,而在命令入口
前端
cmd30 分钟前
别再用错!5种JS类型判断方法,从原理到实战一文吃透
前端·javascript
小江的记录本34 分钟前
【Redis】Redis常用命令速查表(完整版)
java·前端·数据库·redis·后端·spring·缓存