文档转载来自: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;