Source: commands/AnimationEntity.js




/**
 * 通过参数构造一个模型Entity,使得其能够实时运动,考虑贴地
 * 1 构造后调用addTrackPoint实时添加点位
 * 2 实时跟踪车辆运行轨迹时场景下可用
 * 3 可自行添加设置历史轨迹,播放,暂停等方法
 * 4 比setinterval方法更流畅精确,直接使用cesium内部时间戳
 */
export class AnimationEntity {
  /**
   * 构造函数
   *
   * @param {Object} [options] An object with the following properties:
   * @param {Cartisian3} [options.initPosition=undefined] Whether or not to enable clustering.
   * @param {Number} [options.dateTime=20] 时间差,预留缓存时间差,单位s
   * @param {Number} [options.properties={}] 可选模型的属性信息
   * @param {Number} [options.offsetHeading=3.14] 方位角偏移,弧度制,另外其它的偏移参数暂未考虑
   * @param {Boolean} [options.modelurl=""] gltf模型地址
   *
   * @alias AnimationEntity
   * @constructor
   */
  constructor(option) {
    //记录最新的轨迹点
    this.latestPosition = option.initPosition;
    //默认时间差是10s这个取决于数据到来的差值,如果系统灵敏度高,这个值可以适当减少
    this.offsettime = option.offsettime || 20;
    //设定初始时间
    this.initDatetime = option.dateTime || Cesium.JulianDate.now();
    this.offsetHeading=option.offsetHeading||3.14;
    this.entyproperties = option.properties || {};
    //添加点的同时修改当前场景时间戳延后数秒,达到真实的时间段。
    let modelurl = option.modelurl || "static/models/car2.glb";
    let that = this;
    this.realproperty = new Cesium.SampledPositionProperty();
    this.realproperty.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD;
    this.realproperty.backwardExtrapolationType = Cesium.ExtrapolationType.HOLD;
    let start = Cesium.JulianDate.addSeconds(
      this.initDatetime,
      -this.offsettime,
      new Cesium.JulianDate()
    );
    if (this.latestPosition) {
      //this.realproperty.addSample(start, this.latestPosition);
      this.realproperty.addSample(this.initDatetime, this.latestPosition);
    }
    //设置模型在地形上的贴地效果
    this.realproperty.setInterpolationOptions({
      interpolationDegree: 2,
      interpolationAlgorithm: Cesium.LagrangePolynomialApproximation,
    });

    //这里有个偏移量,原因在于模型参考系,这里需要重构下

    let carorientationsproperty = new Cesium.VelocityOrientationProperty(
      this.realproperty
    );

    let dd = carorientationsproperty.getValue.bind(carorientationsproperty);
    carorientationsproperty.getValue = function (time, result) {
      let quad = dd(time, result);
      if (!quad) return quad;
      let mat3 = Cesium.Matrix3.fromQuaternion(quad);
      //
      let offsettranslationmat3 = Cesium.Matrix3.fromRotationZ(that.offsetHeading);
      let rotationScratch = Cesium.Matrix3.multiply(
        mat3,
        offsettranslationmat3,
        new Cesium.Matrix3()
      );
      return Cesium.Quaternion.fromRotationMatrix(rotationScratch, result);
    };
    //记录前一个轨迹点
    //this.prePosition = undefined;
    this.enty = viewer.entities.add({
      //这里id也使用name,方便检索
      id: "tempcar",
      name: "testcar",
      position: this.realproperty,
      properties: this.entyproperties,
      orientation: carorientationsproperty,
      model: {
        upAxis: Cesium.Axis.Y,
        uri: modelurl,
        minimumPixelSize: 128,
        maximumScale: 200,
        scale: 1.0,
        silhouetteSize: 2,
        heightReference: 1,
      },
      path: {
        show: true,
        resolution: 1,
        material: new Cesium.PolylineGlowMaterialProperty({
          glowPower: 0.1,
          color: Cesium.Color.PINK,
        }),
        trailTime: 60,
        width: 5,
      },
    });

    //回溯系统时间到offset之前

    viewer.clock.startTime = start; //将多个点的第一个点设为轨迹播放的开始时间
    viewer.clock.currentTime = start; //修改时间轴的当前时间
    viewer.clock.shouldAnimate = true; //开始播放
    this.enty.addTrackPoint = this.addTrackPoint.bind(this);
    return this.enty;
  }

  /**
   * 动态新增轨迹点
   * @param {*} point
   * @param {*} datetime
   */
  addTrackPoint(point, datetime) {
    if (point && datetime) {
      this.realproperty.addSample(datetime, point);
    }
  }

  /**
   * 销毁对象
   */
  destory() {
    viewer.entities.remove(this.enty);
    //回归系统的正常时间,暂不考虑
  }
}