CZML路径动态改变

文档转载来自:cesium编程中级(七)CZML路径动态改变 | cesium中文网

 整理思路为4步

1. 创建三维球
2. 创建czml文件
3. 动态添加点到czml的路径中
4. 添加czml到三维球上

 第一步:创建三维球并且设置一下地球的图片和颜色

import url from '../../../public/img/worldimage.jpg';
const viewer = new Cesium.Viewer(cesiumRef.current, {
  infoBox: false, // 关闭信息框,不关闭控制台会有报错
  baseLayerPicker: false,
});

// 从异步图像提供商创建一个新的图像层。该层将处理任何异步负载或错误,并在准备就绪后开始呈现图层。
const imageryLayer = Cesium.ImageryLayer.fromProviderAsync(
  // 创建一个单张图片影像提供者
  Cesium.SingleTileImageryProvider.fromUrl(url),
);
viewer.imageryLayers.add(imageryLayer);

 上边的图片是这个,下载这张图片

第二步:创建czml文件

/**
 * interval:设置一个时间范围,所有的动画都是在这个时间范围内显示、有效
 * */
const czml = [
  {
    id: 'document',
    name: 'polygon',
    version: '1.0',
    clock: {
      interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
      currentTime: '2025-02-17T13:00:00Z',
      multiplier: 10,
    },
  },
  {
    id: 'shape2',
    name: 'Red box with black outline',
    availability: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
    box: {
      dimensions: {
        cartesian: [10.0, 10.0],
      },
      material: {
        stripe: {
          orientation: 'VERTICAL',
          evenColor: {
            rgba: [10, 21, 10, 0],
          },
          oddColor: {
            rgba: [10, 2, 250, 255],
          },
          offset: {
            number: 1,
          },
          repeat: 0.5,
        },
      },
    },
    path: {
      material: {
        solidColor: {
          color: {
            interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
            rgba: [255, 0, 0, 128],
          },
        },
      },
      width: [
        {
          interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
          number: 1.0,
        },
      ],
      show: [
        {
          interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
          boolean: true,
        },
      ],
    },
    position: {
      interpolationAlgorithm: 'LAGRANGE',
      interpolationDegree: 1,
      epoch: '2025-02-17T13:00:00Z',
      cartographicDegrees: [
        0.0, 118.87841653400005, 30.95679870500004, 0.0, 10.0, 118.87826541800007,
        30.95680770900003, 0.0, 20.0, 118.8774481050001, 30.956860625000047, 0.0, 30.0,
        118.87660414600009, 30.956910105000077, 0.0, 40.0, 118.8759846580001, 30.95694296000005,
        0.0, 50.0, 118.87542502500003, 30.956978761000073, 0.0, 60.0, 118.87473380100005,
        30.957024103000037, 0.0,
      ],
    },
  },
];

 第三步;动态添加点到czml的路径中

let dataSourcePromise;
let i = 30.957024;
let a = 60;
// 为日期创建一个新的实例
const epoch = Cesium.JulianDate.fromIso8601('2025-02-17T13:00:00Z');
const updateCZML = async () => {
  i += 0.0001;
  a += 10;
  // 更新路径数据
  czml[1].position.cartographicDegrees.push(a, 118.8747338, i, 0);
  // 计算新的时间戳
  /**
   * Cesium.JulianDate.addSeconds(julianDate, seconds, result) → JulianDate
   *  将所提供的秒数添加到所提供的日期实例中。
   *  想要图形随着轨迹移动而移动,就得修改clock的currentTime这个字段
   * */
  const newTime = Cesium.JulianDate.addSeconds(epoch, a, new Cesium.JulianDate());
  // 创建所提供的日期的ISO8601表示形式。
  const newTimeString = Cesium.JulianDate.toIso8601(newTime);
  if (czml[0]?.clock) {
    // 上一次移动的时间 viewer.clockViewModel.clock.currentTime.toString();
    // czml[0].clock.currentTime = viewer.clockViewModel.clock.currentTime.toString();
    czml[0].clock.currentTime = newTimeString;
    viewer.entities.removeAll();
    /**
     * 添加czml到三维球上
     * add(dataSource) → Promise.<DataSource>
     *   创建对加载所提供的CZML数据的新实例的承诺
     *   add 是异步函数,所以要用await/async  try/catch
     * */
    try {
      await viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));
    } catch (err) {}
  }
};

setInterval(updateCZML, 1000);

// 动态添加
const loadInitialData = async () => {
  try {
    dataSourcePromise = await viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));
    viewer.zoomTo(dataSourcePromise);
  } catch (err) {}
};
loadInitialData();

完整的代码

import * as Cesium from 'cesium';
import React, { useEffect, useRef } from 'react';
import url from '../../../public/img/worldimage.jpg';
import '../../../public/Widgets/widgets.css';

// 扩展 Window 接口
declare global {
  interface Window {
    CESIUM_BASE_URL: string;
  }
}

window.CESIUM_BASE_URL = '/';

// 设置token
Cesium.Ion.defaultAccessToken = '改成自己的token';

// 设置cesium默认视角
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
  89.5, // 西边的经度
  20.4, // 南边的经度
  110.4, // 东边的经度
  61.2, // 北边的经度
);

/**
 * interval:设置一个时间范围,所有的动画都是在这个时间范围内显示、有效
 * */
const czml = [
  {
    id: 'document',
    name: 'polygon',
    version: '1.0',
    clock: {
      interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
      currentTime: '2025-02-17T13:00:00Z',
      multiplier: 10,
    },
  },
  {
    id: 'shape2',
    name: 'Red box with black outline',
    availability: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
    box: {
      dimensions: {
        cartesian: [10.0, 10.0],
      },
      material: {
        stripe: {
          orientation: 'VERTICAL',
          evenColor: {
            rgba: [10, 21, 10, 0],
          },
          oddColor: {
            rgba: [10, 2, 250, 255],
          },
          offset: {
            number: 1,
          },
          repeat: 0.5,
        },
      },
    },
    path: {
      material: {
        solidColor: {
          color: {
            interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
            rgba: [255, 0, 0, 128],
          },
        },
      },
      width: [
        {
          interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
          number: 1.0,
        },
      ],
      show: [
        {
          interval: '2025-02-17T13:00:00Z/2025-02-17T15:01:00Z',
          boolean: true,
        },
      ],
    },
    position: {
      interpolationAlgorithm: 'LAGRANGE',
      interpolationDegree: 1,
      epoch: '2025-02-17T13:00:00Z',
      /**
        * 4个数为一组
        *  0.0, 118.87841653400005, 30.95679870500004, 0.0
        *  第0秒的时候,在经纬度118.87841653400005, 30.95679870500004的位置,高度是0.0
        *  10.0, 118.87826541800007,30.95680770900003, 0.0
        *  第10秒的时候,在经纬度118.87826541800007,30.95680770900003的位置,高度是0.0
      */
      cartographicDegrees: [
        0.0, 118.87841653400005, 30.95679870500004, 0.0, 10.0, 118.87826541800007,
        30.95680770900003, 0.0, 20.0, 118.8774481050001, 30.956860625000047, 0.0, 30.0,
        118.87660414600009, 30.956910105000077, 0.0, 40.0, 118.8759846580001, 30.95694296000005,
        0.0, 50.0, 118.87542502500003, 30.956978761000073, 0.0, 60.0, 118.87473380100005,
        30.957024103000037, 0.0,
      ],
    },
  },
];

const CesiumCreate: React.FC = () => {
  const cesiumRef = useRef<HTMLDivElement>(null);

  // 初始化调用
  useEffect(() => {
    if (cesiumRef.current) {
      // 创建实例
      const viewer = new Cesium.Viewer(cesiumRef.current, {
        infoBox: false, // 关闭信息框,不关闭控制台会有报错
        baseLayerPicker: false,
      });
      // 隐藏logo
      viewer.cesiumWidget.creditContainer.style.display = 'none';

      // 从异步图像提供商创建一个新的图像层。该层将处理任何异步负载或错误,并在准备就绪后开始呈现图层。
      const imageryLayer = Cesium.ImageryLayer.fromProviderAsync(
        Cesium.SingleTileImageryProvider.fromUrl(url),
      );
      imageryLayer.alpha = 0.5;
      viewer.imageryLayers.add(imageryLayer);

      let dataSourcePromise;
      let i = 30.957024;
      let a = 60;
      // 为日期创建一个新的实例
      const epoch = Cesium.JulianDate.fromIso8601('2025-02-17T13:00:00Z');
      const updateCZML = async () => {
        i += 0.0001;
        a += 10;
        // 更新路径数据
        czml[1].position.cartographicDegrees.push(a, 118.8747338, i, 0);
        // 计算新的时间戳
        /**
         * Cesium.JulianDate.addSeconds(julianDate, seconds, result) → JulianDate
         *  将所提供的秒数添加到所提供的日期实例中。
         *  想要图形随着轨迹移动而移动,就得修改clock的currentTime这个字段
         * */
        const newTime = Cesium.JulianDate.addSeconds(epoch, a, new Cesium.JulianDate());
        // 创建所提供的日期的ISO8601表示形式。
        const newTimeString = Cesium.JulianDate.toIso8601(newTime);
        if (czml[0]?.clock) {
          // 上一次移动的时间 viewer.clockViewModel.clock.currentTime.toString();
          // czml[0].clock.currentTime = viewer.clockViewModel.clock.currentTime.toString();
          czml[0].clock.currentTime = newTimeString;
          viewer.entities.removeAll();
          /**
           * add(dataSource) → Promise.<DataSource>
           *   创建对加载所提供的CZML数据的新实例的承诺
           *   add 是异步函数,所以要用await/async  try/catch
           * */
          try {
            await viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));
          } catch (err) {}
        }
      };

      setInterval(updateCZML, 1000);

      const loadInitialData = async () => {
        try {
          dataSourcePromise = await viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));
          viewer.zoomTo(dataSourcePromise);
        } catch (err) {}
      };
      loadInitialData();

      return () => {
        if (!viewer.isDestroyed()) {
          viewer.destroy();
        }
      };
    }
  }, []);

  return (
    <div id={'cesiumContainer'} ref={cesiumRef} style={{ height: '100vh', width: '100vw' }}></div>
  );
};

export default CesiumCreate;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值