Cesium中的Property详解

1,011 阅读4分钟

为什么使用Property

Cesium中,如果需要设置一个物体的持续变化,可以不停的去修改它的属性值。但是如果需要在各个不同的时间段进行不同的运动,那么这种方式就太低效了。那么Cesium就提供一种机制,让dimensions(物体)可以随时间自动发生变化,自动赋予不同的数值(位置)。

// 创建盒子
var blueBox = viewer.entities.add({
    name : 'Blue box',
    position: Cesium.Cartesian3.fromDegrees(-114.0, 40.0, 300000.0),
    box : {
        dimensions : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0),
        material : Cesium.Color.BLUE,
        outline: true,
    }
});
var property = new Cesium.SampledProperty(Cesium.Cartesian3);
property.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
                   new Cesium.Cartesian3(400000.0, 300000.0, 200000.0));
property.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'),
                   new Cesium.Cartesian3(400000.0, 300000.0, 700000.0));
blueBox.box.dimensions = property;

以上代码的意思就是在两个不同的时间点分别赋予不同的位置,用SampledProperty包装成一个property,最后赋给blueBox.box.dimensions。 由此可见,**Property**最大的特点是和时间相互关联,在不同的时间可以动态地返回不同的属性值。而Entity则可以感知这些Property的变化,在不同的时间驱动物体进行动态展示。

Property的分类

image.png

Property是抽象类

Property是所有Property类型的虚基类,不能直接实例化。它定义了以下接口。要实现了它定义的接口,才能实例化。这是官方为了用户能够自定义而设置的接口。 image.png Property的公共接口:

  • **getValue(time,result)**:是一个方法,用来获取某个时间点的特定属性值。它有两个参数:第一个是time,用来传递一个时间点;第二个是result,用来存储属性值,当然也可以是undefined。这个resultCesiumscratch机制,主要是用来避免频繁创建和销毁对象而导致内存碎片。**Cesium**就是通过调用**getValue**类似的一些函数来感知**Property**的变化的,当然这个方法我们在外部也是可以使用的。
  • **isConstant**​:用来判断该属性是否会随时间变化,是一个布尔值。Cesium会通过这个变量来决定是否需要在场景更新的每一帧中都获取该属性的数值,从而来更新三维场景中的物体。如果isConstanttrue,则只会获取一次数值,除非definitionChanged事件被触发。
  • **definitionChanged**:是一个事件,可以通过该事件,来监听该Property自身所发生的变化,比如数值发生修改。
  • **equals**:是一个方法,用来检测属性值是否相等。

基础Property

SampleProperty

用来通过给定多个不同时间点的Sample,然后在每两个时间点之间进行线性插值的一种Property。在时间点之间,物体会持续的变化,呈线性运动。

var property = new Cesium.SampledProperty(Cesium.Cartesian3);
property.addSample(Cesium.JulianDate.fromIso8601('2019-01-01T00:00:00.00Z'), 
                   new Cesium.Cartesian3(400000.0, 300000.0, 200000.0));
property.addSample(Cesium.JulianDate.fromIso8601('2019-01-03T00:00:00.00Z'), 
                   new Cesium.Cartesian3(400000.0, 300000.0, 700000.0));
blueBox.box.dimensions = property;

TimeIntervalCollectionProperty

Property用来指定各个具体的时间段的属性值,每个时间段内的属性值是恒定的,并不会发生变化,除非已经进入到下一个时间段。拿创建的盒子示例来说,表现出来的特点就是盒子尺寸的变化时跳跃式的。代码如下:

var property = new Cesium.TimeIntervalCollectionProperty(Cesium.Cartesian3);

property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
  iso8601 : '2019-01-01T00:00:00.00Z/2019-01-01T12:00:00.00Z',
  isStartIncluded : true,
  isStopIncluded : false,
  data : new Cesium.Cartesian3(400000.0, 300000.0, 200000.0)
}));
property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
  iso8601 : '2019-01-01T12:00:01.00Z/2019-01-02T00:00:00.00Z',
  isStartIncluded : true,
  isStopIncluded : false,
  data : new Cesium.Cartesian3(400000.0, 300000.0, 400000.0)
}));
property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
  iso8601 : '2019-01-02T00:00:01.00Z/2019-01-02T12:00:00.00Z',
  isStartIncluded : true,
  isStopIncluded : false,
  data : new Cesium.Cartesian3(400000.0, 300000.0, 500000.0)
}));
property.intervals.addInterval(Cesium.TimeInterval.fromIso8601({
  iso8601 : '2019-01-02T12:00:01.00Z/2019-01-03T00:00:00.00Z',
  isStartIncluded : true,
  isStopIncluded : true,
  data : new Cesium.Cartesian3(400000.0, 300000.0, 700000.0)
}));

blueBox.box.dimensions = property;

ConstantProperty

//这两段代码等同
blueBox.box.dimensions = new Cesium.Cartesian3(400000.0, 300000.0, 200000.0);
blueBox.box.dimensions = new ConstantProperty(new Cesium.Cartesian3(400000.0, 300000.0, 200000.0));

这说明了box.dimensions的类型并不是Cartesian3,而是一个Property。虽然我们赋值了一个Cartesian3,但是Cesium内部会隐晦地转化成了一个ConstantProperty。虽然叫ConstantProperty,但是,这里Constant的意思并不是说这个Property不可改变,而是说它不会随时间发生变化。 所以,这种直接赋值的方式,其实就是使用了ConstantProperty

CompositeProperty

CompositeProperty的意思是组合的Property,可以把多种不同类型的ConstantPropertySamplePropertyTimeIntervalCollectionPropertyProperty组合在一起来操作。比如前一个时间段需要线性运动,后一段时间再跳跃式运动。

PositionProperty

PositionPropertyProperty一样,是一个虚类,并不能直接实例化,他扩展了Property的接口,增加了referenceFrame,同时只能用来表示position

MaterialProperty

MaterialProperty是用来专门表示材质的Property,它对Property进行了扩展,增加了getType方法,用来获取材质类型。 MaterialProperty也是一个虚基类,派生类有:

  • CheckerboardMaterialProperty
  • ColorMaterialProperty
  • CompositeMaterialProperty
  • GridMaterialProperty
  • ImageMaterialProperty
  • MaterialProperty
  • PolylineArrowMaterialProperty
  • PolylineDashMaterialProperty
  • PolylineGlowMaterialProperty
  • PolylineOutlineMaterialProperty
  • StripeMaterialProperty

其他类型的Property

CallbackProperty(callBack, isConstant)

CallbackProperty是自由度最高的一种Property,让用户通过自定义,回调函数,来返回需要的值。回调函数中,用户可以使用time来给定value,也可以以自己的方式给给定。 以下代码就是不通过time,自己手动调整dimension的示例。

var l = 200000.0;
var property = new Cesium.CallbackProperty(function (time, result) {
  result = result || new Cesium.Cartesian3(0, 0, 0);

  l += 10000.0;
  if (l > 700000.0) {
    l = 200000.0;
  }

  result.x = 400000.0;
  result.y = 300000.0;
  result.z = l;

  return result;
}, false);

blueBox.box.dimensions = property;