第13章 - 动画与时间系统
第13章:动画与时间系统
13.1 时钟系统
13.1.1 Clock 配置
const clock = viewer.clock;
// 时间范围
clock.startTime = Cesium.JulianDate.fromIso8601('2024-01-01T00:00:00Z');
clock.stopTime = Cesium.JulianDate.fromIso8601('2024-01-07T00:00:00Z');
clock.currentTime = Cesium.JulianDate.fromIso8601('2024-01-01T12:00:00Z');
// 播放速度
clock.multiplier = 60; // 60倍速
clock.shouldAnimate = true; // 开始播放
// 时钟范围模式
clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 循环
// Cesium.ClockRange.UNBOUNDED // 无限制
// Cesium.ClockRange.CLAMPED // 限制在范围内
// 时钟步进
clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER;
// Cesium.ClockStep.TICK_DEPENDENT // 依赖tick
// Cesium.ClockStep.SYSTEM_CLOCK // 系统时钟
13.1.2 时间事件
// 监听时钟tick
clock.onTick.addEventListener(function(clock) {
const currentTime = clock.currentTime;
console.log('当前时间:', Cesium.JulianDate.toIso8601(currentTime));
});
// 监听时钟停止
clock.onStop.addEventListener(function(clock) {
console.log('时钟停止');
});
13.2 Timeline 控件
const timeline = viewer.timeline;
// 缩放时间轴
timeline.zoomTo(
Cesium.JulianDate.fromIso8601('2024-01-01'),
Cesium.JulianDate.fromIso8601('2024-01-31')
);
// 监听时间轴事件
timeline.addEventListener('settime', function(e) {
console.log('时间轴时间改变');
}, false);
13.3 时间动态属性
13.3.1 SampledProperty
// 创建采样位置属性
const positionProperty = new Cesium.SampledPositionProperty();
// 添加采样点
const times = [
Cesium.JulianDate.fromIso8601('2024-01-01T00:00:00Z'),
Cesium.JulianDate.fromIso8601('2024-01-01T01:00:00Z'),
Cesium.JulianDate.fromIso8601('2024-01-01T02:00:00Z')
];
const positions = [
Cesium.Cartesian3.fromDegrees(116.0, 39.0, 1000),
Cesium.Cartesian3.fromDegrees(117.0, 39.5, 2000),
Cesium.Cartesian3.fromDegrees(118.0, 40.0, 1500)
];
for (let i = 0; i < times.length; i++) {
positionProperty.addSample(times[i], positions[i]);
}
// 设置插值
positionProperty.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
// Cesium.LinearApproximation
// Cesium.HermitePolynomialApproximation
});
// 创建动态实体
const movingEntity = viewer.entities.add({
name: '移动对象',
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: times[0],
stop: times[times.length - 1]
})
]),
position: positionProperty,
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
model: {
uri: 'aircraft.glb',
scale: 100
},
path: {
material: Cesium.Color.YELLOW,
width: 2,
leadTime: 0,
trailTime: 3600
}
});
// 跟踪实体
viewer.trackedEntity = movingEntity;
13.3.2 其他动态属性
// 采样颜色属性
const colorProperty = new Cesium.SampledProperty(Cesium.Color);
colorProperty.addSample(times[0], Cesium.Color.RED);
colorProperty.addSample(times[1], Cesium.Color.GREEN);
colorProperty.addSample(times[2], Cesium.Color.BLUE);
// 采样数值属性
const scaleProperty = new Cesium.SampledProperty(Number);
scaleProperty.addSample(times[0], 1.0);
scaleProperty.addSample(times[1], 2.0);
scaleProperty.addSample(times[2], 1.5);
// 时间区间颜色
const timeIntervalColor = new Cesium.TimeIntervalCollectionProperty();
timeIntervalColor.intervals.addInterval(new Cesium.TimeInterval({
start: times[0],
stop: times[1],
data: Cesium.Color.RED
}));
timeIntervalColor.intervals.addInterval(new Cesium.TimeInterval({
start: times[1],
stop: times[2],
data: Cesium.Color.BLUE
}));
13.4 场景动画
13.4.1 属性动画
// 实体属性动画
function animateEntityScale(entity, fromScale, toScale, duration) {
const startTime = performance.now();
function animate() {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / (duration * 1000), 1);
// 缓动函数
const easedProgress = Cesium.EasingFunction.QUADRATIC_IN_OUT(progress);
const currentScale = fromScale + (toScale - fromScale) * easedProgress;
entity.model.scale = currentScale;
if (progress < 1) {
requestAnimationFrame(animate);
}
}
animate();
}
// 颜色渐变动画
function animateColor(entity, fromColor, toColor, duration) {
const startTime = performance.now();
function animate() {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / (duration * 1000), 1);
const currentColor = Cesium.Color.lerp(fromColor, toColor, progress, new Cesium.Color());
if (entity.polygon) {
entity.polygon.material = currentColor;
}
if (progress < 1) {
requestAnimationFrame(animate);
}
}
animate();
}
13.4.2 轨迹动画
// 创建轨迹动画
class TrajectoryAnimation {
constructor(viewer, waypoints, options = {}) {
this.viewer = viewer;
this.waypoints = waypoints;
this.duration = options.duration || 60; // 秒
this.entity = null;
}
create() {
const startTime = Cesium.JulianDate.now();
const stopTime = Cesium.JulianDate.addSeconds(startTime, this.duration, new Cesium.JulianDate());
// 配置时钟
this.viewer.clock.startTime = startTime.clone();
this.viewer.clock.stopTime = stopTime.clone();
this.viewer.clock.currentTime = startTime.clone();
this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
this.viewer.clock.multiplier = 1;
// 创建位置属性
const positionProperty = new Cesium.SampledPositionProperty();
const interval = this.duration / (this.waypoints.length - 1);
this.waypoints.forEach((wp, i) => {
const time = Cesium.JulianDate.addSeconds(startTime, i * interval, new Cesium.JulianDate());
const position = Cesium.Cartesian3.fromDegrees(wp.lon, wp.lat, wp.height || 0);
positionProperty.addSample(time, position);
});
positionProperty.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});
// 创建实体
this.entity = this.viewer.entities.add({
name: '动画对象',
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({ start: startTime, stop: stopTime })
]),
position: positionProperty,
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
point: { pixelSize: 12, color: Cesium.Color.RED },
path: {
material: Cesium.Color.YELLOW,
width: 2,
trailTime: this.duration
}
});
return this.entity;
}
play() {
this.viewer.clock.shouldAnimate = true;
}
pause() {
this.viewer.clock.shouldAnimate = false;
}
setSpeed(multiplier) {
this.viewer.clock.multiplier = multiplier;
}
track() {
this.viewer.trackedEntity = this.entity;
}
destroy() {
if (this.entity) {
this.viewer.entities.remove(this.entity);
this.entity = null;
}
}
}
// 使用
const animation = new TrajectoryAnimation(viewer, [
{ lon: 116.0, lat: 39.0, height: 1000 },
{ lon: 117.0, lat: 39.5, height: 2000 },
{ lon: 118.0, lat: 40.0, height: 1500 },
{ lon: 119.0, lat: 39.5, height: 1000 }
], { duration: 120 });
animation.create();
animation.track();
animation.play();
13.5 本章小结
本章介绍了动画与时间系统:
- 时钟系统:Clock 配置、时间事件
- Timeline 控件:时间轴控制
- 动态属性:SampledProperty、插值
- 场景动画:属性动画、轨迹动画
在下一章中,我们将详细介绍交互与事件处理。
13.6 思考与练习
- 创建一个卫星轨道动画。
- 实现动画播放控制面板。
- 开发多对象同步运动效果。
- 实现时间倒放功能。
- 创建历史轨迹回放工具。

浙公网安备 33010602011771号