经纬志
首页 / Cesium / 教程

时间轴与动画

先看结论

Cesium 的时钟不是一个装饰控件。场景里几乎每个属性都可以绑定时间, 轨迹、飞行、生长动画都由同一个 Clock 驱动,改倍速和循环只影响这个时钟。

最后验证 2026-11-03 · CesiumJS 1.121 · 难度:进阶 · 核验 2026-10-29 · 引用本文

时钟决定场景里的「现在」

viewer.clock 是一个 Cesium.Clock。它保存三个时间点: 开始、结束、当前。时间轴显示的是开始到结束这段区间,动画播放的是当前时间向前推进的过程。 所有时间都必须是 Cesium.JulianDate,不能传 JavaScript 的 Date。

var clock = viewer.clock;

clock.startTime = Cesium.JulianDate.fromIso8601('2026-10-29T08:00:00Z');
clock.stopTime = Cesium.JulianDate.fromIso8601('2026-10-29T09:00:00Z');
clock.currentTime = clock.startTime.clone();

clock.clockRange = Cesium.ClockRange.LOOP_STOP;              // 播到末尾后停住
clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER;  // 用倍速推进
clock.multiplier = 30;                                       // 30 倍速

viewer.timeline.zoomTo(clock.startTime, clock.stopTime);
参数取值效果
clockRangeLOOP_STOP到结束时间停止,当前时间停在末尾
clockRangeLOOP到末尾后跳回开始时间循环播放
clockRangeCLAMPED不循环,但允许用户拖到区间外,时间被夹住
clockStepSYSTEM_CLOCK_MULTIPLIER按真实流逝时间乘以 multiplier 推进
clockStepSYSTEM_CLOCK与系统时间同步,multiplier 无效
clockStepTICK_DEPENDENT每次 tick 固定前进 multiplier 秒

倍速只在 SYSTEM_CLOCK_MULTIPLIER 下生效。改成 SYSTEM_CLOCK 后, 界面上拖倍速滑块不会有任何反应,这是设计如此,不是控件坏了。

用采样属性造一条轨迹

位置随时间变化,就要用 SampledPositionProperty。 它保存若干「时间点 + 坐标」的样本,渲染时按当前时间插值出一个位置。 这种做法比每帧手动改 entity.position 更平滑,也更省 CPU。

var start = Cesium.JulianDate.fromIso8601('2026-10-29T08:00:00Z');

var waypoints = [
  [116.20, 39.80], [116.35, 39.95], [116.50, 39.88],
  [116.60, 40.02], [116.45, 40.10]
];

var position = new Cesium.SampledPositionProperty();
position.setInterpolationOptions({
  interpolationDegree: 1,
  interpolationAlgorithm: Cesium.LinearApproximation
});

waypoints.forEach(function (p, i) {
  var t = Cesium.JulianDate.addSeconds(start, i * 60, new Cesium.JulianDate());
  position.addSample(t, Cesium.Cartesian3.fromDegrees(p[0], p[1], 1200));
});

viewer.entities.add({
  availability: new Cesium.TimeIntervalCollection([
    new Cesium.TimeInterval({ start: start, stop: Cesium.JulianDate.addSeconds(start, 300, new Cesium.JulianDate()) })
  ]),
  position: position,
  orientation: new Cesium.VelocityOrientationProperty(position),
  model: {
    uri: '/models/plane.glb',
    minimumPixelSize: 48,
    maximumScale: 20000
  },
  path: {
    resolution: 60,
    width: 3,
    leadTime: 0,
    trailTime: 300,
    material: Cesium.Color.fromCssColorString('#ffb400')
  }
});

VelocityOrientationProperty 根据位置的差分自动算出朝向, 模型不用再手动设 orientation。样本点越密,转向越跟得上; 点太稀疏时模型会在拐点处突然掉头。

线性插值不等于匀速。每个样本间隔 60 秒,但两点之间的实际距离不同, 模型的瞬时速度就会忽快忽慢。需要匀速运动时,按距离等分采样点,而不是按时间等分。

按时间段改颜色和可见性

颜色、显示开关这类属性可以用 TimeIntervalCollectionProperty, 给不同时间区间配不同值。播放到某个区间,属性自动切换,不需要监听时钟事件。

var highlight = new Cesium.TimeIntervalCollectionProperty();

highlight.intervals.addInterval(new Cesium.TimeInterval({
  start: Cesium.JulianDate.addSeconds(start, 120, new Cesium.JulianDate()),
  stop: Cesium.JulianDate.addSeconds(start, 210, new Cesium.JulianDate()),
  isStartIncluded: true,
  isStopIncluded: false,
  data: Cesium.Color.fromCssColorString('#ff5252')
}));

highlight.intervals.addInterval(new Cesium.TimeInterval({
  start: Cesium.JulianDate.addSeconds(start, 210, new Cesium.JulianDate()),
  stop: Cesium.JulianDate.addSeconds(start, 300, new Cesium.JulianDate()),
  data: Cesium.Color.fromCssColorString('#4d9bff')
}));

viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(116.391, 39.907, 260),
  point: {
    pixelSize: 14,
    color: highlight,
    outlineColor: Cesium.Color.WHITE,
    outlineWidth: 2
  }
});

区间之外的时刻没有值,属性取默认值。想让起点之前也有颜色, 加一个从 startTime 到第一个区间开始的时间段即可。

时间轴控件的外观

时间轴默认显示刻度与当前时间标签。展示型页面通常把它简化: 隐藏倍速滑块、改标签格式、固定显示区间。

viewer.timeline.makeLabel = function (time) {
  return Cesium.JulianDate.toIso8601(time).slice(11, 16);  // 只显示 HH:MM
};

// 清空倍速滑块刻度,只保留播放与暂停
viewer.animation.viewModel.shuttleRingTicks = [];

viewer.timeline.zoomTo(clock.startTime, clock.stopTime);

注意事项

  • 开启 scene.requestRenderMode 后,时间推进不会自动重绘;需要调用 viewer.scene.requestRender(),或者保持时钟暂停、只在数据变化时渲染。
  • SampledPositionProperty 的样本必须按时间递增加入;倒序加入会让插值区间找不到。
  • path 的 trailTime 是「尾迹长度」,单位是秒,不是点数;设置过大时整条轨迹都会画出来,等于关闭尾迹效果。
  • 实体没有设置 availability 时,在时钟区间外仍然可见,容易被误认为动画没生效。
  • 用 clock.onTick 做逐帧逻辑时要判断 clock.canAnimate,暂停状态下也会触发回调。

动画卡顿先看数据量。一条轨迹几千个样本时,插值和路径几何的更新都会变慢。 把 path.resolution 从 60 降到 30,并把轨迹拆成多段按需显示,通常比调时钟参数有效。

引用本文

经纬志(2026)。《时间轴与动画》。https://www.jingweizhi.com/cesium/tutorial/time-animation.html(访问日期 2026-11-03)。