🌌 Cesium 中的 JulianDate(儒略日期)和 Clock(时钟)
什么是儒略日期?
JulianDate 是 Cesium 时间系统的基石,采用天文学儒略日概念,具有以下优势:
- 连续无间断:不存在历法不连续问题(如闰年、闰秒)
- 高精度存储:分离日和秒数存储,避免浮点精度损失
- 时区无关性:以 UTC 时间为基准,避免时区混乱
- 科学标准:符合国际天文学联合会标准
时间表示结构
js
{
day: 2460830, // 整数部分 - 从儒略日起始日算起的天数
secondsOfDay: 43200 // 小数部分 - 当天已过去的秒数(0-86400)
}JulianDate 与常规日期的转换
js
new Cesium.JulianDate(julianDayNumber, secondsOfDay, timeStandard);| 名称 | 描述 |
|---|---|
julianDayNumber | 儒略日数,表示整天数 |
secondsOfDay | 当前儒略日数的秒数 |
timeStandard | 定义前两个参数的时间标准,默认Cesium.TimeStandard.UTC |
JulianDate 与北京时间
JulianDate 本身不涉及时区概念,它存储的是 UTC 时间,转换为北京时间需通过addHours添加 8 小时偏移。
js
// 创建当前时间对应的 JulianDate
const julianDate = Cesium.JulianDate.fromDate(new Date());
// 将 JulianDate 转换为北京时间
const beijingDate = Cesium.JulianDate.addHours(
julianDate,
8,
new Cesium.JulianDate()
);常规日期 → JulianDate
从当前时间创建
js
// 创建当前时间的JulianDate(推荐)
const nowJulian = Cesium.JulianDate.now();
// 从JavaScript Date创建
const jsDate = new Date();
const fromJsDate = Cesium.JulianDate.fromDate(jsDate);从 ISO 8601 字符串创建
js
// 从ISO 8601字符串创建(UTC时间)
const isoString = "2025-06-04T12:00:00Z"; // Z表示UTC时间
const fromIso = Cesium.JulianDate.fromIso8601(isoString);
// 带时区的ISO字符串(会自动转换为UTC)
const localIsoString = "2025-06-04T20:00:00+08:00"; // 北京时间
const fromLocalIso = Cesium.JulianDate.fromIso8601(localIsoString);JulianDate → 常规日期
转换为 JavaScript Date
js
const julianDate = Cesium.JulianDate.now();
// 转换为JavaScript Date(会丢失纳秒精度)
const jsDate = Cesium.JulianDate.toDate(julianDate);格式化为 ISO 8601 字符串
js
const julianDate = Cesium.JulianDate.now();
// 格式化为ISO 8601字符串(UTC)
const isoString = Cesium.JulianDate.toIso8601(julianDate);
// 输出: "2025-06-04T12:00:00.000Z"
// 带毫秒精度
const isoWithMs = Cesium.JulianDate.toIso8601(julianDate, 3);
// 输出: "2025-06-04T12:00:00.500Z"(假设500ms)时间操作实用函数
| 方法名 | 描述 |
|---|---|
addDays | 增加天数 |
addHours | 增加小时数 |
addMinutes | 增加分钟数 |
addSeconds | 增加秒数 |
增加时间
js
const baseDate = Cesium.JulianDate.fromIso8601("2025-06-04T12:00:00Z");
const result = new Cesium.JulianDate();
// 增加1天3小时30分钟
const newDate = Cesium.JulianDate.addDays(baseDate, 1, result);
Cesium.JulianDate.addHours(newDate, 3, result);
Cesium.JulianDate.addMinutes(result, 30, result);
console.log(Cesium.JulianDate.toIso8601(result));
// 输出: "2025-06-05T15:30:00Z"减少时间(使用负数)
js
const baseDate = Cesium.JulianDate.fromIso8601("2025-06-04T12:00:00Z");
const result = new Cesium.JulianDate();
// 减少2小时
Cesium.JulianDate.addHours(baseDate, -2, result);
console.log(Cesium.JulianDate.toIso8601(result));
// 输出: "2025-06-04T10:00:00Z"Cesium 中的时钟 Clock
Clock 作为时间推进引擎,其工作流程如下:
- 初始化:设置 startTime、stopTime 和初始 currentTime
- 推进:根据 clockStep 和 multiplier 计算新时间
- 边界检查:根据 clockRange 处理边界行为
- 事件触发:调用 onTick 监听器
js
new Cesium.Clock(options);| 属性 | 类型 | 说明 |
|---|---|---|
currentTime | JulianDate | 当前场景时间(可读写) |
startTime | JulianDate | 时间轴起始时间 |
stopTime | JulianDate | 时间轴结束时间 |
multiplier | Number | 时间流逝倍率(正=正向播放,负=倒放) |
clockStep | ClockStep | 判断对每一帧的调用是否依赖于帧或系统时钟。 |
clockRange | ClockRange | 到达时间边界的行为:UNBOUNDED:不停止,CLAMPED:停止在边界,LOOP_STOP:循环播放 |
shouldAnimate | Boolean | 是否自动播放(true=播放,false=暂停) |
ClockStep 属性
ClockStep 决定时间如何前进:
| ClockStep 值 | 说明 | 适用场景 |
|---|---|---|
SYSTEM_CLOCK | 与系统时间同步 | 实时模拟 |
SYSTEM_CLOCK_MULTIPLIER | 系统时间 × 倍率 | 加速/减速模拟 |
TICK_DEPENDENT | 每帧前进固定时间 | 精确控制动画 |
ClockRange 属性
ClockRange 控制到达边界时的行为:
| ClockRange 值 | 说明 | 适用场景 |
|---|---|---|
UNBOUNDED | 不受限制继续前进 | 无边界时间 |
CLAMPED | 停在边界 | 固定区间动画 |
LOOP_STOP | 循环播放 | 重复动画 |
基础配置
js
const clock = new Cesium.Clock({
startTime: Cesium.JulianDate.fromIso8601("2023-01-01T00:00:00Z"),
currentTime: Cesium.JulianDate.fromIso8601("2023-01-01T12:00:00Z"),
stopTime: Cesium.JulianDate.fromIso8601("2023-01-02T00:00:00Z"),
clockRange: Cesium.ClockRange.LOOP_STOP, // 循环播放
multiplier: 2.0, // 2倍速播放
clockStep: Cesium.ClockStep.SYSTEM_CLOCK,
});
// 在 Viewer 中使用
const viewer = new Cesium.Viewer("cesiumContainer", {
clock: clock,
shouldAnimate: true, // 播放
});动态控制
js
// 播放/暂停
viewer.clock.shouldAnimate = !viewer.clock.shouldAnimate;
// 调整播放速度
viewer.clock.multiplier = 4.0; // 4倍速
// 倒放
viewer.clock.multiplier = -1.0; // 倒放
// 跳转到特定时间
const targetTime = Cesium.JulianDate.fromIso8601("2025-06-04T18:00:00Z");
Cesium.JulianDate.clone(targetTime, viewer.clock.currentTime);
// 重置时钟
viewer.clock.currentTime = Cesium.JulianDate.clone(viewer.clock.startTime);