Skip to content

平台是数据驱动和 time-dynamic visualization,这些可都是仰仗 Property 属性机制来实现的。

Property 最大的特点是和时间相互关联,在不同的时间可以动态地返回不同的属性值。而 Entity 则可以感知这些 Property 的变化,在不同的时间驱动物体进行动态展示。

运行效果

注:为了方便理解,可以参考示例源码去调试体验进行理解。

1.为什么要用 Property?

还是举个例子来说吧。比如我想在地球上的某个位置加一个盒子,可以这样写代码:

js
// 创建盒子
var marsBox = new mars3d.graphic.BoxEntity({
  position: [117.220164, 31.834887, 39.6],
  style: {
    dimensions: new Cesium.Cartesian3(400.0, 300.0, 500.0),
    color: 'rgba(0,255,255,0.8)',
    outline: true
  }
});
graphicLayer.addGraphic(marsBox);
// 创建盒子
var marsBox = new mars3d.graphic.BoxEntity({
  position: [117.220164, 31.834887, 39.6],
  style: {
    dimensions: new Cesium.Cartesian3(400.0, 300.0, 500.0),
    color: 'rgba(0,255,255,0.8)',
    outline: true
  }
});
graphicLayer.addGraphic(marsBox);

box 加在固定位置。 但是呢,如果我想让这个盒子逐渐变长,该怎么操作呢?如下图所示:

image

盒子逐渐变长 方法是有的,就是可以不停地去修改 marsBox.position,类似这样:

setInterval(function(){ marsBox.entityGraphic.dimensions = xxx; }, 200);

如果场景中有很多物体,在不同的时间段要发生各种走走停停地运动时,这样操作可能会很累人。那么 Cesium 就提供一种机制,让 dimensions 可以随时间自动发生变化,自动赋予不同的数值(位置)。这也就是 property 的作用了。以下代码的加入,就可以让盒子如上图所示做线性运动了。

js
var property = new Cesium.SampledProperty(Cesium.Cartesian3);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  new Cesium.Cartesian3(400.0, 300.0, 100.0)
);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:20')),
  new Cesium.Cartesian3(400.0, 300.0, 900.0)
);
marsBox.setStyle({ dimensions: property });
var property = new Cesium.SampledProperty(Cesium.Cartesian3);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  new Cesium.Cartesian3(400.0, 300.0, 100.0)
);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:20')),
  new Cesium.Cartesian3(400.0, 300.0, 900.0)
);
marsBox.setStyle({ dimensions: property });

以上代码的意思就是在两个不同的时间点分别赋予不同的位置,用 SampledProperty 包装成一个 property,最后赋给 marsBox 的 dimensions 样式。

由此可见,Property 最大的特点是和时间相互关联,在不同的时间可以动态地返回不同的属性值。而 Entity 则可以感知这些 Property 的变化,在不同的时间驱动物体进行动态展示。

平台是数据驱动和 time-dynamic visualization,这些可都是仰仗 Property 属性机制来实现的。

当然,Property 可不只是这么简单,以下再详细论述。

2.Property 的分类

Cesium 的 Property 不止有刚才示例代码中的 SampleProperty,还有很多其他的类型。如果搜索一下 Cesium 的 API 文档,会有很多。如下图所示:

image

Cesium API 文档搜索 Property 我们简单分类一下

image

2.Property 虚基类

Property是所有 Property 类型的虚基类。它定义了以下接口。

image

Property 类型的公共接口

  • getValue 是一个方法,用来获取某个时间点的特定属性值。它有两个参数:第一个是 time,用来传递一个时间点;第二个是 result,用来存储属性值,当然也可以是 undefined。这个 result 是 Cesium 的 scratch 机制,主要是用来避免频繁创建和销毁对象而导致内存碎片。Cesium 就是通过调用 getValue 类似的一些函数来感知 Property 的变化的,当然这个方法我们在外部也是可以使用的。

  • isConstant 用来判断该属性是否会随时间变化,是一个布尔值。Cesium 会通过这个变量来决定是否需要在场景更新的每一帧中都获取该属性的数值,从而来更新三维场景中的物体。如果 isConstant 为 true,则只会获取一次数值,除非 definitionChanged 事件被触发。

  • definitionChanged 是一个事件,可以通过该事件,来监听该 Property 自身所发生的变化,比如数值发生修改。

  • equals 是一个方法,用来检测属性值是否相等。

2.基本 Property 类型

2. SampleProperty 类

SampleProperty 类是我们最早在上述示例中使用的就是它,用来通过给定多个不同时间点的 Sample,然后在每两个时间点之间进行线性插值的一种 Property。代码写法如下:

js
var property = new Cesium.SampledProperty(Cesium.Cartesian3);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  new Cesium.Cartesian3(400.0, 300.0, 100.0)
);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:20')),
  new Cesium.Cartesian3(400.0, 300.0, 900.0)
);
//让盒子一直存在
// property.addSample(Cesium.JulianDate.fromDate(new Date('2017-08-26 00:00:00')), new Cesium.Cartesian3(400.0, 300.0, 900.0))

marsBox.setStyle({ dimensions: property });
var property = new Cesium.SampledProperty(Cesium.Cartesian3);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  new Cesium.Cartesian3(400.0, 300.0, 100.0)
);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:20')),
  new Cesium.Cartesian3(400.0, 300.0, 900.0)
);
//让盒子一直存在
// property.addSample(Cesium.JulianDate.fromDate(new Date('2017-08-26 00:00:00')), new Cesium.Cartesian3(400.0, 300.0, 900.0))

marsBox.setStyle({ dimensions: property });

盒子逐渐变长

image

2. TimeIntervalCollectionProperty

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

image

代码如下:

js
var property = new Cesium.TimeIntervalCollectionProperty();
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:00.00Z/2017-08-25T00:00:02.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 200.0)
  })
);
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:02.00Z/2017-08-25T00:00:04.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 400.0)
  })
);
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:04.00Z/2017-08-25T00:00:06.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 500.0)
  })
);
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:06.00Z/2017-08-25T00:00:08.00Z',
    isStartIncluded: true,
    isStopIncluded: true,
    data: new Cesium.Cartesian3(400.0, 300.0, 700.0)
  })
);

marsBox.setStyle({ dimensions: property });
var property = new Cesium.TimeIntervalCollectionProperty();
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:00.00Z/2017-08-25T00:00:02.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 200.0)
  })
);
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:02.00Z/2017-08-25T00:00:04.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 400.0)
  })
);
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:04.00Z/2017-08-25T00:00:06.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 500.0)
  })
);
property.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:06.00Z/2017-08-25T00:00:08.00Z',
    isStartIncluded: true,
    isStopIncluded: true,
    data: new Cesium.Cartesian3(400.0, 300.0, 700.0)
  })
);

marsBox.setStyle({ dimensions: property });

2. ConstantProperty

通过对 TimeIntervalCollectionProperty 和 SampleProperty 的描述,读者应该基本了解 Property 的特点。 我们回过头来说下 ConstantProperty,其实这才是最常用的 Property,也是平台默认使用的 Property。

示例代码如下:

js
let dimensions = new Cesium.Cartesian3(400.0, 300.0, 200.0);
marsBox.setStyle({ dimensions: dimensions });
let dimensions = new Cesium.Cartesian3(400.0, 300.0, 200.0);
marsBox.setStyle({ dimensions: dimensions });

以上代码貌似没有使用 ConstantProperty,实际上他是等同于:

js
let dimensions = new ConstantProperty(
  new Cesium.Cartesian3(400.0, 300.0, 200.0)
);
marsBox.setStyle({ dimensions: dimensions });
let dimensions = new ConstantProperty(
  new Cesium.Cartesian3(400.0, 300.0, 200.0)
);
marsBox.setStyle({ dimensions: dimensions });

也就是 Entity 的 dimensions style 样式并不是 Cartesian3,而是一个 Property。虽然我们赋值了一个 Cartesian3,但是 Cesium 内部会隐晦地转化成了一个 ConstantProperty。注意只会隐晦地转化成 ConstantProperty,而不是 SampleProperty,更不是 TimeIntervalCollectionProperty。

虽然叫 ConstantProperty,但是,这里 Constant 的意思并不是说这个 Property 不可改变,而是说它不会随时间发生变化。

举个例子,我们可以通过 property.getValue(viewer.clock.currentTime) 方法来获取某个时间点 property 的属性值。如果 property 是 SampleProperty 或者 TimeIntervalCollectionProperty 的话,不同的时间点,可能 getValue 出不同的数值。但是如果这个 property 是 ConstantProperty,那么无论什么时间(getValue 的第一个参数不起作用),最后返回的数值都是一样的。

但是不会随时间变化,并不代表不可改变。ConstantProperty 还有一个 setValue 的方法,开发者可以通过调用它,来在适当的时候改变 property 的值。

比如,我可以通过点击按钮来修改 ConstantProperty,代码如下:

js
marsBox.entityGraphic.dimensions.setValue(
  new Cesium.Cartesian3(400.0, 300.0, 700.0)
);
marsBox.entityGraphic.dimensions.setValue(
  new Cesium.Cartesian3(400.0, 300.0, 700.0)
);

需要注意的是,虽然最终效果一样,但是以下两种写法的意义是不一样的。

js
//会创建一个新的ConstantProperty
marsBox.entityGraphic.dimensions = new Cesium.Cartesian3(400.0, 300.0, 200.0);
//会修改原有的ConstantProperty的值。
marsBox.entityGraphic.dimensions.setValue(
  new Cesium.Cartesian3(400.0, 300.0, 700.0)
);
//会创建一个新的ConstantProperty
marsBox.entityGraphic.dimensions = new Cesium.Cartesian3(400.0, 300.0, 200.0);
//会修改原有的ConstantProperty的值。
marsBox.entityGraphic.dimensions.setValue(
  new Cesium.Cartesian3(400.0, 300.0, 700.0)
);

2. CompositeProperty

CompositeProperty的意思是组合的 Property,可以把多种不同类型的 ConstantProperty、SampleProperty、TimeIntervalCollectionProperty 等 Property 组合在一起来操作。比如前一个时间段需要线性运动,后一段时间再跳跃式运动。则可以使用类似下面这段代码来实现。

js
// 1 sampledProperty
var sampledProperty = new Cesium.SampledProperty(Cesium.Cartesian3);
sampledProperty.addSample(
  Cesium.JulianDate.fromIso8601('2017-08-25T00:00:00.00Z'),
  new Cesium.Cartesian3(400.0, 300.0, 100.0)
);
sampledProperty.addSample(
  Cesium.JulianDate.fromIso8601('2017-08-25T00:00:10.00Z'),
  new Cesium.Cartesian3(400.0, 300.0, 500.0)
);

// 2 ticProperty
var ticProperty = new Cesium.TimeIntervalCollectionProperty();
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:10.00Z/2017-08-25T00:00:12.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 600.0)
  })
);
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:12.00Z/2017-08-25T00:00:14.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 700.0)
  })
);
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:14.00Z/2017-08-25T00:00:16.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 800.0)
  })
);
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:16.00Z/2017-08-25T00:00:18.00Z',
    isStartIncluded: true,
    isStopIncluded: true,
    data: new Cesium.Cartesian3(400.0, 300.0, 900.0)
  })
);

// 3 compositeProperty
var compositeProperty = new Cesium.CompositeProperty();
compositeProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:00.00Z/2017-08-25T00:00:10.00Z',
    data: sampledProperty
  })
);
compositeProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:10.00Z/2017-08-25T00:00:20.00Z',
    isStartIncluded: false,
    isStopIncluded: false,
    data: ticProperty
  })
);

// 4 设置dimensions
marsBox.setStyle({ dimensions: compositeProperty });
// 1 sampledProperty
var sampledProperty = new Cesium.SampledProperty(Cesium.Cartesian3);
sampledProperty.addSample(
  Cesium.JulianDate.fromIso8601('2017-08-25T00:00:00.00Z'),
  new Cesium.Cartesian3(400.0, 300.0, 100.0)
);
sampledProperty.addSample(
  Cesium.JulianDate.fromIso8601('2017-08-25T00:00:10.00Z'),
  new Cesium.Cartesian3(400.0, 300.0, 500.0)
);

// 2 ticProperty
var ticProperty = new Cesium.TimeIntervalCollectionProperty();
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:10.00Z/2017-08-25T00:00:12.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 600.0)
  })
);
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:12.00Z/2017-08-25T00:00:14.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 700.0)
  })
);
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:14.00Z/2017-08-25T00:00:16.00Z',
    isStartIncluded: true,
    isStopIncluded: false,
    data: new Cesium.Cartesian3(400.0, 300.0, 800.0)
  })
);
ticProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:16.00Z/2017-08-25T00:00:18.00Z',
    isStartIncluded: true,
    isStopIncluded: true,
    data: new Cesium.Cartesian3(400.0, 300.0, 900.0)
  })
);

// 3 compositeProperty
var compositeProperty = new Cesium.CompositeProperty();
compositeProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:00.00Z/2017-08-25T00:00:10.00Z',
    data: sampledProperty
  })
);
compositeProperty.intervals.addInterval(
  Cesium.TimeInterval.fromIso8601({
    iso8601: '2017-08-25T00:00:10.00Z/2017-08-25T00:00:20.00Z',
    isStartIncluded: false,
    isStopIncluded: false,
    data: ticProperty
  })
);

// 4 设置dimensions
marsBox.setStyle({ dimensions: compositeProperty });

最终实现的效果如下:

image

2. PositionProperty 坐标属性

基于 PositionProperty 的类型有以下几种:

稍加留意,就会发现,和普通的 Property 相比,只是多了一个 Position,所以用法上也大同小异,只不过他们是用来专门表示位置的。

2. SampledPositionProperty

SampledPositionProperty的用法,不多解释,直接看代码吧:

js
var property = new Cesium.SampledPositionProperty();
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  Cesium.Cartesian3.fromDegrees(117.198461, 31.834956, 40.2)
);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:20')),
  Cesium.Cartesian3.fromDegrees(117.231979, 31.833411, 35.6)
);

marsBox.position = property;
var property = new Cesium.SampledPositionProperty();
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  Cesium.Cartesian3.fromDegrees(117.198461, 31.834956, 40.2)
);
property.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:20')),
  Cesium.Cartesian3.fromDegrees(117.231979, 31.833411, 35.6)
);

marsBox.position = property;

效果如下:

image

SamplePropertySampledPositionProperty 有一个特有的方法:setInterpolationOptions,用来修改不同的插值方式。以下是以 Cesium 的 Interpolation 示例中的截图来说明他们的不同之处。

image

js
//线性插值
marsBox.position.setInterpolationOptions({
  interpolationDegree: 1,
  interpolationAlgorithm: Cesium.LinearApproximation
});

//Lagrange插值
marsBox.position.setInterpolationOptions({
  interpolationDegree: 5,
  interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});

//Hermite插值
marsBox.position.setInterpolationOptions({
  interpolationDegree: 2,
  interpolationAlgorithm: Cesium.HermitePolynomialApproximation
});
//线性插值
marsBox.position.setInterpolationOptions({
  interpolationDegree: 1,
  interpolationAlgorithm: Cesium.LinearApproximation
});

//Lagrange插值
marsBox.position.setInterpolationOptions({
  interpolationDegree: 5,
  interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});

//Hermite插值
marsBox.position.setInterpolationOptions({
  interpolationDegree: 2,
  interpolationAlgorithm: Cesium.HermitePolynomialApproximation
});

另外在 cesium 中,提供了三种样条插值方法, LinearSplineCatmullRomSplineHermiteSpline

2. MaterialProperty

MaterialProperty是用来专门表示材质的 Property,它对 Property 进行了扩展,增加了 getType 方法,用来获取材质类型。 效果如下: image

MaterialProperty 也是一个虚基类,派生类有:

使用上大同小异,我们以 ColorMaterialProperty来说明一下。

js
marsBox.setStyle({
  material: new Cesium.ColorMaterialProperty(new Cesium.Color(0, 1, 0))
});
// 以上代码等同于
marsBox.setStyle({ material: new Cesium.Color(0, 1, 0) });
marsBox.setStyle({
  material: new Cesium.ColorMaterialProperty(new Cesium.Color(0, 1, 0))
});
// 以上代码等同于
marsBox.setStyle({ material: new Cesium.Color(0, 1, 0) });

效果如下:

image

ColorMaterialProperty的动态变化

如果希望 Color 动起来的话,也是可以的。ColorMaterialProperty 的内部有一个 color 属性,可以赋予一个 SampledProperty 来实现动态效果。

js
var colorProperty = new Cesium.SampledProperty(Cesium.Color);
colorProperty.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  new Cesium.Color(0, 0, 1)
);
colorProperty.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:10')),
  new Cesium.Color(1, 1, 0)
);

marsBox.setStyle({ material: new Cesium.ColorMaterialProperty(colorProperty) });
var colorProperty = new Cesium.SampledProperty(Cesium.Color);
colorProperty.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  new Cesium.Color(0, 0, 1)
);
colorProperty.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:10')),
  new Cesium.Color(1, 1, 0)
);

marsBox.setStyle({ material: new Cesium.ColorMaterialProperty(colorProperty) });

效果如下:

image

2. CallbackProperty

CallbackProperty是自由度最高的一种 Property,让用户通过自定义,回调函数,来返回需要的值。回调函数中,用户可以使用 time 来给定 value,也可以以自己的方式给给定。

以下代码就是不通过 time,自己手动调整 dimension 的示例。

js
var len = 100.0;
var property = new Cesium.CallbackProperty(function (time, result) {
  result = result || new Cesium.Cartesian3(400.0, 300.0, 500.0);

  len += 3.0;
  if (len > 900.0) {
    len = 100.0;
  }

  result.x = 400.0;
  result.y = 300.0;
  result.z = len;

  return result;
}, false);

marsBox.setStyle({ dimensions: property });
var len = 100.0;
var property = new Cesium.CallbackProperty(function (time, result) {
  result = result || new Cesium.Cartesian3(400.0, 300.0, 500.0);

  len += 3.0;
  if (len > 900.0) {
    len = 100.0;
  }

  result.x = 400.0;
  result.y = 300.0;
  result.z = len;

  return result;
}, false);

marsBox.setStyle({ dimensions: property });

效果如下,盒子逐渐变长:

image

2. ReferenceProperty

ReferenceProperty可以直接链接到别的对象的 Property 上,相当于引用,省得自己构建了。比如这里我创建了一个红色的盒子 redBox,希望它和之前的蓝色盒子一起变大。那么可以使用以下代码:

以下代码就是不通过 time,自己手动调整 dimension 的示例。

js
var collection = graphicLayer.dataSource.entities;
let dimensions = new Cesium.ReferenceProperty(collection, marsBox.uuid, [
  'box',
  'dimensions'
]);
redBox.setStyle({ dimensions: dimensions });
var collection = graphicLayer.dataSource.entities;
let dimensions = new Cesium.ReferenceProperty(collection, marsBox.uuid, [
  'box',
  'dimensions'
]);
redBox.setStyle({ dimensions: dimensions });

效果如下,盒子逐渐变长:

image

ReferenceProperty 的使用

ReferenceProperty构造函数的参数 ReferenceProperty 构造函数的参数有三个。第一个参数用来指定需要引用的对象所属的 collection,如果没有自己专门创建 EntityCollection 的话,可以直接使用 viewer.entities。第二个参数传递所指对象的 id。第三个参数指定属性的位置的数组,如果是有层级的属性,可以依次写入。比如 ['billboard', 'scale'] 指定的是 entity.billboard.scale 属性。当然还有其他设置方式,可以参见API 文档

2. PropertyBag

PropertyBag虽然不是以 Property 结尾,但实际上也是一个 Property。它的特点是可以包装一个对象(JS 中的对象概念),该对象的每一个属性(JS 中的属性概念),都可以作为一个动态的 Property。

比如之前修改 dimensions 的话,dimensions 是作为一个 Cartesian3 类型变量整体封装到 Property 中去的,如果我们只想修改 dimensions 的 x。则可以使用 PropertyBag 来实现,代码如下:

js
var zp = new Cesium.SampledProperty(Number);
zp.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  100.0
);
zp.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:10')),
  800.0
);

let dimensions = new Cesium.PropertyBag({
  x: 400.0,
  y: 300.0,
  z: zp
});
marsBox.setStyle({ dimensions: dimensions });
var zp = new Cesium.SampledProperty(Number);
zp.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:00')),
  100.0
);
zp.addSample(
  Cesium.JulianDate.fromDate(new Date('2017-08-25 08:00:10')),
  800.0
);

let dimensions = new Cesium.PropertyBag({
  x: 400.0,
  y: 300.0,
  z: zp
});
marsBox.setStyle({ dimensions: dimensions });

效果如下,盒子逐渐变长:

image

效果和 sampleProperty 类似,但是修改的只是 dimensions 的 x。

2. PropertyArray

PropertyArray和上述的 PropertyBag 类似,只是其内部封装了一个数组而已。这里不再赘述。

2. VelocityOrientationProperty

VelocityOrientationProperty 用来 Entity 的 position 的位置变化,来计算出移动的方向,最后把速度方向输出成 Orientation。Cesium 自带的示例中有一个 Interpolation 中有其用法,不再赘述。

2. VelocityVectorProperty

VelocityVectorProperty 与上面的 Property 类似,把速度方向转成 Vector。使用示例如下:

js
//计算演示的SampledPositionProperty轨迹
function getSampledPositionProperty(points) {
  let property = new Cesium.SampledPositionProperty();

  let start = map.clock.currentTime;
  let positions = mars3d.LngLatArray.toCartesians(points);
  for (let i = 0; i < positions.length; i++) {
    let time = Cesium.JulianDate.addSeconds(
      start,
      i * 20,
      new Cesium.JulianDate()
    );
    let position = positions[i];
    property.addSample(time, position);
  }
  return property;
}

let propertyFJ = getSampledPositionProperty([
  [117.198461, 31.834956, 40.2],
  [117.231979, 31.833411, 35.6]
]);
var graphic = new mars3d.graphic.BillboardEntity({
  position: propertyFJ,
  orientation: new Cesium.VelocityOrientationProperty(propertyFJ),
  style: {
    image: 'img/marker/huojian.svg',
    scale: 0.5,
    alignedAxis: new Cesium.VelocityVectorProperty(propertyFJ, true)
  }
});
graphicLayer.addGraphic(graphic);
//计算演示的SampledPositionProperty轨迹
function getSampledPositionProperty(points) {
  let property = new Cesium.SampledPositionProperty();

  let start = map.clock.currentTime;
  let positions = mars3d.LngLatArray.toCartesians(points);
  for (let i = 0; i < positions.length; i++) {
    let time = Cesium.JulianDate.addSeconds(
      start,
      i * 20,
      new Cesium.JulianDate()
    );
    let position = positions[i];
    property.addSample(time, position);
  }
  return property;
}

let propertyFJ = getSampledPositionProperty([
  [117.198461, 31.834956, 40.2],
  [117.231979, 31.833411, 35.6]
]);
var graphic = new mars3d.graphic.BillboardEntity({
  position: propertyFJ,
  orientation: new Cesium.VelocityOrientationProperty(propertyFJ),
  style: {
    image: 'img/marker/huojian.svg',
    scale: 0.5,
    alignedAxis: new Cesium.VelocityVectorProperty(propertyFJ, true)
  }
});
graphicLayer.addGraphic(graphic);

可见图像的摆放方向和位置移动的方向保持一致。效果如下:

image