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

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

相关推荐
前端老鹰1 分钟前
JavaScript Intl.RelativeTimeFormat:自动生成 “3 分钟前” 的国际化工具
前端·javascript
梦想CAD控件1 分钟前
(在线CAD插件)网页CAD实现图纸表格智能提取
前端·javascript·全栈
木子雨廷19 分钟前
Flutter 开发一个plugin
前端·flutter
重生之我是一名前端程序员21 分钟前
websocket + xterm 前端实现网页版终端
前端·websocket
sorryhc23 分钟前
【AI解读源码系列】ant design mobile——Space间距
前端·javascript·react.js
uhakadotcom37 分钟前
NPM与NPX的区别是什么?
前端·面试·github
GAMC1 小时前
如何修改node_modules的组件不被install替换?可以使用patch-package
前端
页面仔Dony1 小时前
webpack 与 Vite 深度对比
前端·前端工程化
Juchecar1 小时前
Vue3 组件生命周期详解
前端·vue.js
页面仔Dony1 小时前
打包工具配置base、publicPath字段的作用和区别
前端·前端工程化