cesium 实现轨迹回放

一、项目介绍

在地图上画出2条路径,无人机在轨迹上移动的效果。只需要准备路径的坐标集合和3d模型。

二、创建地图

js 复制代码
import * as Cesium from "cesium"; 
Cesium.Ion.defaultAccessToken = key; 
const viewer = new Cesium.Viewer(id);

三、添加轨迹

使用viewer.entities.add方法添加线条polyline,设置线条的颜色、宽度、样式。

js 复制代码
let positions = []; //路径集合
//路径坐标转笛卡尔坐标
points.forEach((item) => { 
    let point = Cesium.Cartesian3.fromDegrees(item[0], item[1], height);
    positions.push(point);
  });

//添加轨迹
  pathEntry = viewer.entities.add({
    polyline: {
      positions: positions,
      width: 5,
      material: new Cesium.PolylineDashMaterialProperty({
        color:  Cesium.Color.RED,
        dashLength: 16.0, // 控制虚线段的长度
      }),
      clampToGround:false, // 设置为true可使路线贴地
    },
    name: "path",
  });

四、添加模型、轨迹与时间结合

js 复制代码
// 2. 设置移动速度并计算总时间
  const totalSeconds = 300;

  const positionProperty = new Cesium.SampledPositionProperty();

  tracks = viewer.entities.add({
    name: "移动",
    position: positionProperty, //位置
    orientation: new Cesium.VelocityOrientationProperty(positionProperty), //模型的方向
    model: {
      uri: 'xx.glft', //3d模型链接
      scale: 0.2,   //缩放比例
      runAnimations: true, //播放3d模型的动画
    },
    monitoItems: {
      ...curItem,
    },
  });

//开始时间
  const start = Cesium.JulianDate.fromDate(new Date());
 //结束时间
  const stop = Cesium.JulianDate.addSeconds(
    start,
    totalSeconds,
    new Cesium.JulianDate()
  );

  // 添加路径点和时间点
  positions.forEach((position, index) => {
    const time = Cesium.JulianDate.addSeconds(
      start,
      index*10,
      new Cesium.JulianDate()
    );
    positionProperty.addSample(time, position);
  });

  // 设置时间范围
  viewer.clock.startTime = start.clone();
  viewer.clock.stopTime = stop.clone();
  viewer.clock.currentTime = start.clone();
  viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //循环播放
  viewer.clock.multiplier = 10; //时间加速倍数
  
  // 相机跟踪实体
  viewer.trackedEntity = tracks; 
  
   // 自定义相机行为
  viewer.clock.onTick.addEventListener(function(clock) {
        const currentDate = clock.currentTime.toDate(); // 转成标准 Date 对象
        console.log("当前时间:", currentDate);
   });
   
    // 后续移除
    viewer.clock.onTick.removeEventListener(listener);

五、知识点

1、Cesium.SampledPositionProperty 随时间变化的位置属性。

  • 通常与 Cesium.Clock 配合实现时间控制
  • Entity.position 属性使用
  • 可与 Cesium.PathGraphics 一起显示运动轨迹
js 复制代码
//添加时间-位置样本点:
const time = Cesium.JulianDate.fromIso8601('2023-01-01T00:00:00Z');
const position = Cesium.Cartesian3.fromDegrees(116.3, 39.9, 100);
positionProperty.addSample(time, position);

//获取指定时间点的位置:
const currentPosition = positionProperty.getValue(viewer.clock.currentTime);

//设置插值选项:
positionProperty.setInterpolationOptions({
    interpolationDegree: 5,
    interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});

2、Cesium.JulianDate 用于计算时间

js 复制代码
// 从ISO 8601字符串创建
const date1 = Cesium.JulianDate.fromIso8601("2023-01-01T12:00:00Z");

// 从JavaScript Date对象创建
const date2 = Cesium.JulianDate.fromDate(new Date());

// 从年、月、日等组件创建
const date3 = Cesium.JulianDate.fromGregorianDate({
    year: 2023, 
    month: 1, 
    day: 1,
    hour: 12,
    minute: 0,
    second: 0
});

// 创建当前时间
const now = Cesium.JulianDate.now();

// 时间加减
const newDate = Cesium.JulianDate.addSeconds(date1, 3600, new Cesium.JulianDate());
const diff = Cesium.JulianDate.secondsDifference(date2, date1);

// 比较时间
const isAfter = Cesium.JulianDate.compare(date1, date2) > 0;

// 转为JavaScript Date
const jsDate = Cesium.JulianDate.toDate(date1);

// 转为ISO 8601字符串
const isoString = Cesium.JulianDate.toIso8601(date1);

// 获取时间组件
const gregorian = Cesium.JulianDate.toGregorianDate(date1);
console.log(gregorian.year, gregorian.month, gregorian.day);

3、viewer.clock

viewer.clock是Cesium中控制时间系统的核心对象,用于管理场景中的时间流动、动画和动态数据的时间同步。

js 复制代码
//创建时钟对象
viewer.clock = new Cesium.Clock({
    // 必须参数
    startTime: Cesium.JulianDate.fromIso8601("2023-01-01T00:00:00Z"),
    stopTime: Cesium.JulianDate.fromIso8601("2023-01-02T00:00:00Z"),
    currentTime: Cesium.JulianDate.fromIso8601("2023-01-01T06:00:00Z"),
    
    // 可选参数
    multiplier: 10,                  // 时间流逝速度倍数
    clockStep: Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER, // 时间步进模式
    clockRange: Cesium.ClockRange.LOOP_STOP, // 时间范围行为
    canAnimate: true,                // 是否允许动画
    shouldAnimate: false             // 初始是否自动播放
});

ClockStep (时间步进模式)

js 复制代码
Cesium.ClockStep.SYSTEM_CLOCK          // 跟随系统时钟
Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER // 系统时钟×multiplier
Cesium.ClockStep.TICK_DEPENDENT        // 依赖渲染帧率

ClockRange (时间范围行为)

js 复制代码
Cesium.ClockRange.UNBOUNDED  // 到达终点后继续前进
Cesium.ClockRange.LOOP_STOP  // 到达终点后回到起点
Cesium.ClockRange.CLAMPED    // 到达终点后停止

时间控制方法

js 复制代码
// 播放/暂停控制
viewer.clock.shouldAnimate = true; // 开始播放
viewer.clock.shouldAnimate = false; // 暂停

// 跳转到特定时间
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601("2023-01-01T12:00:00Z");

// 调整播放速度
viewer.clock.multiplier = 60; // 60倍速播放

// 重置时间范围
viewer.clock.startTime = newStartTime;
viewer.clock.stopTime = newStopTime;

// 初始化时间轴范围
viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime);

// 更新时间轴显示
viewer.timeline.updateFromClock();

时间变化监听

js 复制代码
// 每帧时间变化事件
viewer.clock.onTick.addEventListener(function(clock) {
    console.log("当前时间:", Cesium.JulianDate.toIso8601(clock.currentTime));
});

// 时间范围变化事件
viewer.clock.onStop.addEventListener(function() {
    console.log("到达时间轴终点");
});

// 后续移除
 viewer.clock.onTick.removeEventListener(listener);
相关推荐
NeverSettle1105743 分钟前
手把手教你用nodejs + vue3 实现大文件上传、秒传、断点续传
前端·面试
用户1512905452203 分钟前
crossorigin注解添加了解决不了跨域问题_CORS与@CrossOrigin详解
前端
Silkide10 分钟前
前端数据拷贝简史
前端
码上佳人26 分钟前
Echarts如何生成没有上下两端线的箱线图
前端·echarts
tianchang34 分钟前
React Hook 解析(一):useCallback 与 useMemo
前端·react.js
炊烟行者36 分钟前
foreignObject
前端
OEC小胖胖1 小时前
组件化(一):重新思考“组件”:状态、视图和逻辑的“最佳”分离实践
前端·javascript·html5·web
拾光拾趣录1 小时前
用 Web Worker 计算大视频文件 Hash:从“页面卡死”到流畅上传
前端·javascript
伟大的兔神1 小时前
cesium绘制动态柱状图
前端·gis·cesium
前端拿破轮1 小时前
字节面试官:你对Promise很熟是吧?试一下手写所有静态方法
前端·面试·promise