Cesium 自定义Primitive

1、为什么要自定义Primitive

      a、在飞机飞行过程中,如果使用entity同时绘制飞机和线的时候,会发现飞机的飞行位置和线的位置不统一,出现差距,出现脱线。

      b、结合代码分析,cesium的线和飞机模型是分开渲染的,渲染的时段不一致,导致飞机在飞行过程的点位结合不上。

       c、采用同批次渲染就不会发生这个问题

2、如何自定义Primitive

        a、使用es6进行编码

        b、使用class

        c、提供update方法

        d、将自定义的primitive加入到primitivecollection中进行渲染

3、实现代码

        案例以初始实验为主,不以飞机案例来做。

        案例以点和文字加入一个渲染队列进行数据渲染。

        1、首先创建一个类CustomPrimitive

        包括类名、构造函数,以及对应的参数

import { LabelCollection, PointPrimitiveCollection, Cartesian3 } from "cesium";
export default class CustomPrimitive {
  /**
   * 自定义对象
   * @param options
   * @param {Cartesian3} options.position 点位置
   * @param {string} options.text 文本内容
   * @param {number} options.pixelSize 点的像素大小
   */
  constructor(options) {
    this._position = options.position;
    this._label = options.text;
    this._pixelSize = options.pixelSize;
    this._ready = false;
    /**
     * 渲染队列
     * @type {[]}
     * @private
     */
    this._primitiveCollection = [];
  }
}

        2、编写update方法,当数据没有完成注册时,执行注册,初始化实体对象

/**
   * 注册
   * @param frameState
   */
  init(frameState) {}

  /**
   * 更新
   * @param frameState
   */
  update(frameState) {
    if (!this._ready) {
      this._ready = true;
      this.init(frameState);
    }
    this._primitiveCollection.forEach((primitive) => {
      primitive && !primitive.isDestroyed() && primitive.update(frameState);
    });
  }

        3、编写注册对象,包括点集合和文本渲染

   

/**
   * 注册
   * @param frameState
   */
  init(frameState) {
    const points = new PointPrimitiveCollection();
    points.add({
      position: this._position,
      color: Color.fromCssColorString("#ff0000", new Color()),
      disableDepthTestDistance: 5000,
      outlineWidth: 1,
      outlineColor: Color.fromCssColorString("#ffff00", new Color()),
      pixelSize: this._pixelSize,
    });
    this._primitiveCollection.push(points);

    let labels = new LabelCollection();
    labels.add({
      text: this._label,
      position: this._position,
      disableDepthTestDistance: 5000,
      fillColor: Color.fromCssColorString("#ffffff", new Color()),
      font: "32px sans-serif",
      horizontalOrigin: HorizontalOrigin.CENTER,
      verticalOrigin: VerticalOrigin.BOTTOM,
      showBackground: true,
      backgroundColor: Color.fromCssColorString("#0EE3F6C1", new Color()),
      backgroundPadding: Cartesian2.fromArray([12, 7]),
    });
    this._primitiveCollection.push(labels);
  }

        4、渲染代码:将定义的Primitive对象加入到渲染队列

let origin2 = Cartesian3.fromDegrees(106, 26, 1600);
let origin21 = Cartesian3.fromDegrees(106, 26, 40);
viewer.camera.flyTo({
    destination: origin2,
    complete: () => {
      let primitive = new CustomPrimitive({
        position: origin21,
        text: "测试",
        pixelSize: 8,
      });
      viewer.scene.primitives.add(primitive);
    },
});

   4、渲染效果

全部代码

import {
  LabelCollection,
  PointPrimitiveCollection,
  Cartesian3,
  Color,
  Cartesian2,
  HorizontalOrigin,
  VerticalOrigin,
} from "cesium";
export default class CustomPrimitive {
  /**
   * 自定义对象
   * @param options
   * @param {Cartesian3} options.position 点位置
   * @param {string} options.text 文本内容
   * @param {number} options.pixelSize 点的像素大小
   */
  constructor(options) {
    this._position = options.position;
    this._label = options.text;
    this._pixelSize = options.pixelSize;
    this._ready = false;
    /**
     * 渲染队列
     * @type {[]}
     * @private
     */
    this._primitiveCollection = [];
  }

  /**
   * 注册
   * @param frameState
   */
  init(frameState) {
    const points = new PointPrimitiveCollection();
    points.add({
      position: this._position,
      color: Color.fromCssColorString("#ff0000", new Color()),
      disableDepthTestDistance: 5000,
      outlineWidth: 1,
      outlineColor: Color.fromCssColorString("#ffff00", new Color()),
      pixelSize: this._pixelSize,
    });
    this._primitiveCollection.push(points);

    let labels = new LabelCollection();
    labels.add({
      text: this._label,
      position: this._position,
      disableDepthTestDistance: 5000,
      fillColor: Color.fromCssColorString("#ffffff", new Color()),
      font: "32px sans-serif",
      horizontalOrigin: HorizontalOrigin.CENTER,
      verticalOrigin: VerticalOrigin.BOTTOM,
      showBackground: true,
      backgroundColor: Color.fromCssColorString("#0EE3F6C1", new Color()),
      backgroundPadding: Cartesian2.fromArray([12, 7]),
    });
    this._primitiveCollection.push(labels);
  }

  /**
   * 更新
   * @param frameState
   */
  update(frameState) {
    if (!this._ready) {
      this._ready = true;
      this.init(frameState);
    }
    this._primitiveCollection.forEach((primitive) => {
      primitive && !primitive.isDestroyed() && primitive.update(frameState);
    });
  }
}

从错误信息 `primitive.isDestroyed is not a function` 来看,这个问题通常是由于尝试调用了一个不存在的方法所导致的。具体来说,在 Cesium 中,`isDestroyed` 是一种常见的方法用于检查某个对象是否已经被销毁,但它并非所有类型的对象都有这个方法。 以下是可能出现该问题的原因以及解决方案: --- ### 可能原因及解决办法 #### 1. **使用的 Primitive 类型不支持 `isDestroyed`** 并不是所有的 Cesium 对象都实现了 `isDestroyed` 方法。例如一些自定义的对象或者第三方库扩展的对象可能并不具备该方法。 - **解决方法**: 确认当前对象确实属于支持 `isDestroyed` 的类型(如 `Cesium.Primitive` 或其他组件)。如果不确定,可以先打印出对象的完整属性来进行调试: ```javascript console.log(primitive); ``` #### 2. **对象已被释放或赋值为空** 如果在某处已经将原始对象设置为了 null 或者 undefined,则后续再访问其方法会报此类错误。 - **解决方法**: 在每次操作前加上安全性检查,确保对象仍然存在并且是有效引用。 ```javascript if (primitive && typeof primitive.isDestroyed === 'function') { console.log(primitive.isDestroyed()); } else { console.error("The object does not support .isDestroyed method"); } ``` #### 3. **版本兼容性问题** 若使用的是较老版本的 Cesium 库,某些 API 设计可能存在差异,比如 `isDestroyed` 方法可能是后期才添加到特定类中的特性之一。 - **解决方法**: 更新至最新稳定版 Cesium,并查阅官方文档核实目标对象的确切接口描述。同时对比新旧代码调整相应逻辑。 --- ### 示例修复代码 假设我们有一个场景需要循环遍历一组 primitives 判断它们的状态: ```javascript const primitives = viewer.scene.primitives; primitives.forEach(function(item) { // 添加安全校验 if (item && typeof item.isDestroyed === 'function') { const destroyedStatus = item.isDestroyed(); console.log(`Primitive status: ${destroyedStatus}`); } else { console.warn('This item either has been removed or lacks an "isDestroyed" property.'); } }); ``` 上述示例中加入了对每项内容的基本检验流程,防止直接触碰到非预期的数据而引发崩溃情况。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生活真难

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值