三维GIS开发实战!Cesium + CZML 实现火箭飞行与分离的 3D 动态模拟
CZML是一种基于JSON的数据格式,专门用于在Cesium中描述3D场景和时间动态数据。
本文将详细介绍了CZML的特点(JSON格式、时间动态性、层次结构等)和基本组件,并给出了一个火箭发射的实例。通过搭建Cesium开发环境(使用vite)、配置vite插件、加载CZML数据源(space.czml)并设置相机跟踪,实现了火箭从起飞到降落的完整动画效果。最后还提供了保持相机跟踪火箭位置的关键代码实现。
前置知识点
知识点:CZML数据格式
CZML(Cesium Language)是一种用于描述3D场景和时间动态的数据格式,最初由Cesium开发团队创建,用于在Cesium JavaScript库中呈现虚拟地球和其他三维地理空间数据。它通常用于创建可视化地球表面上的物体、飞行轨迹、传感器信息等。
CZML数据拥有以下特点:
JSON格式:CZML数据以JSON格式编写,这使得它易于创建和解析,JSON是一种轻量级的数据交换格式,易于人类阅读和编写,同时也易于机器解析和生成。
时间动态性:CZML支持时间动态性,允许您描述物体随时间变化的属性。这使得您可以创建动态的3D场景,例如模拟飞行轨迹、天体运动等。
基本组件:CZML包含了一系列基本的组件来描述场景中的对象。这些组件包括点、线、多边形、模型等。
层次结构:CZML允许您以层次结构的方式组织场景中的对象,例如可以创建父对象和子对象,这样可以更好地管理和组织复杂的场景。
事件:CZML允许您指定事件,例如单击事件、鼠标悬停事件等,这使得您可以创建与场景交互的用户体验。
插件支持:CZML可以与Cesium JavaScript库的插件集成,从而扩展其功能,例如添加地形、天气数据等。
CZML数据示例
关于czml数据规范,可以查看官方文档:
https://github.com/AnalyticalGraphicsInc/czml-writer/wiki/CZML-Structure
CZML数据是一个数组,可以看到,数组中的每一项其实都是一个实体对象的描述,这种对象,成为一个包:CZML
id:固定值
name:可自定义设置值
version:CZML版本,CZL目前只有1.0版本,固定值
完整的CZML至少包合两个packet,第一个用于标识CZML,第二个packet对应一个场景中的对象,例如一个盒子。
可以看到,box中的属性和Cesium实体中boxGraphic的属性是一致的
box.czml
{"document": {"id": "document","name": "box","version": "1.0"},"shape1": {"id": "shape1","name": "Blue box","position": {"cartographicDegrees": [-114.0,40.0,300000.0]},"box": {"dimensions": {"cartesian": [400000.0,300000.0,500000.0]},"material": {"solidColor": {"color": {"rgba": [0,0,255,255]}}}}}
}
所以这里我们就知道Cesium是如何实现火箭起飞到分体到降落的过程了,通过加载czml数据,可以快速的实现这个效果
使用到的火箭升空数据源----数据来源(火星科技)
space.czml
实现全过程
首先搭建Cesium开发环境
新建一个cesium_basic的目录,并初始化
npm init -y
安装cesium与vite的cesium插件,本教程使用的版本为1.97
npm i cesium@1.97 vite-plugin-cesium
安装vite
vite是开箱即用的下一代打包工具, 原生支持模块化开发
相比于webpack
Rollup
Parcel
更快, 更好用
将vite安装成开发时依赖, 使用vite
启动开发服务
"vite": "^5.4.9"
npm i vite -D
配置vite.config.js,主要是配置cesium插件,这样才能正常引入cesium
import { defineConfig } from'vite';
import cesium from'vite-plugin-cesium';
// https://vitejs.dev/config/
export defaultdefineConfig({plugins: [cesium()]
});
创建入口文件index.html
, 在入口文件中引入
初始化样式
reset.css
主入口文件
main.js
编辑
package.json
脚本脚本,使用vite会自动编辑index.html启动开发服务
ndex.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><!-- 引入初始化样式 --><link rel="stylesheet" href="./src/assets/styles/reset.css" /></head><body><div id="cesiumContainer"></div><!-- 使用模块化方式引入入口文件 --><script src="./src/main.js" type="module"></script></body>
</html>
功能说明
- 该代码为Cesium.js等WebGL库的基础HTML模板
reset.css
用于清除浏览器默认样式cesiumContainer
作为三维渲染的DOM容器- 模块化引入的
main.js
为应用入口文件
reset.css
* {margin: 0;padding: 0;box-sizing: border-box;
}body {background-color: skyblue;overflow: hidden;
}#cesiumContainer {width: 100vw;height: 100vh;position: relative;
}
代码说明
box-sizing: border-box
确保元素尺寸计算包含边框和内边距overflow: hidden
防止页面出现滚动条position: relative
为容器内的绝对定位元素建立定位上下文
功能增强
- 添加了视口单位(vw/vh)确保容器始终填满屏幕
- 重置了所有元素的盒模型计算方式
- 优化了背景色显示效果
main.js
import * as Cesium from "cesium";// 注册token
Cesium.Ion.defaultAccessToken = "xxx";// 使用cesium默认配置初始化viewer
const viewer = new Cesium.Viewer("cesiumContainer");
代码功能说明
导入模块
import * as Cesium from "cesium"
将整个 Cesium 库导入,并通过Cesium
对象访问其功能。设置访问令牌
Cesium.Ion.defaultAccessToken = "xxx"
用于设置 Cesium Ion 的访问令牌,替换"xxx"
为实际令牌字符串。初始化 Viewer
const viewer = new Cesium.Viewer("cesiumContainer")
创建一个 Cesium 地图实例,绑定到 HTML 中 ID 为"cesiumContainer"
的元素。
package.json
{"scripts": {"dev": "vite","build": "vite build","preview": "vite preview"}
}
功能说明
dev
命令启动开发服务器,支持热模块替换(HMR)build
命令执行生产环境构建preview
命令本地预览生产构建结果
然后开启终端运行项目
terminal
npm run dev
这样你可以看到一个椭球
然后设置一下viewer,将不需要的控件隐藏起来,并去Cesium ion注册一个token(具体流程可以自行百度),然后将token写入到Cesium.Ion.defaultAccessToken上。
这里需要注意将shouldAnimate设置为true,这样才会有动画效果
import * as Cesium from "cesium";
import * as dat from "dat.gui";const gui = new dat.GUI();
Cesium.Ion.defaultAccessToken = import.meta.env.VITE_CESIUM_TOKEN;// 使用cesium默认配置初始化viewer
const viewer = new Cesium.Viewer("cesiumContainer", {timeline: true, // 设置默认的时间轴不显示animation: false, // 隐藏动画控件baseLayerPicker: false, // 隐藏底图切换geocoder: false, // 隐藏导航功能homeButton: false, // 复位按钮sceneModePicker: false, // 二三维切换按钮navigationHelpButton: false, // 隐藏帮助按钮scene3DOnly: true, // 如果是三维的系统,最好加上这个配置shouldAnimate: true // 最好设置动画为true,这样火箭才能有动画效果
});
代码说明
- 代码格式已调整为标准的JavaScript语法,包含适当的缩进和换行
- 注释保持原样,但增加了与代码的对齐
- 配置项使用一致的缩进方式,便于阅读
- 对象字面量的属性使用逗号分隔,最后一个属性不加逗号(符合ESLint推荐风格)
- 保留了原有的功能实现,未做逻辑修改
接着调用Cesium中加载Czml数据的方法,将space.czml接入,就可以让火箭起飞了,在加载完成的回调函数中,还可以调用viewer.trackedEntity,让相机一直锁定火箭的位置
// CZML 是 Cesium 的数据源格式,用于快速加载动态实体场景
new Cesium.CzmlDataSource().load('/src/assets/dataSource/space.czml').then(dataSource => {// 添加数据源到场景viewer.dataSources.add(dataSource);// 自动缩放到数据源范围viewer.zoomTo(dataSource);// 设置相机跟踪数据源中的第二个实体(索引为1)viewer.trackedEntity = dataSource.entities.values[1];});
代码说明
- CZML 加载:通过
CzmlDataSource.load()
方法异步加载指定的 CZML 文件(路径为/src/assets/dataSource/space.czml
)。 - 数据源处理:加载完成后,将数据源添加到
viewer
的dataSources
集合中,并通过zoomTo
自动调整视角至数据范围。 - 实体跟踪:将相机的跟踪目标设为数据源中的第二个实体(
values[1]
),通常用于跟踪动态对象如火箭。
注意事项
- 确保 Cesium 库已正确引入,且
viewer
为有效的Cesium.Viewer
实例。 - CZML 文件路径需根据实际项目结构调整。
- 实体索引(如
values[1]
)需根据具体 CZML 内容确认,通常索引 0 为文档定义,实体从索引 1 开始。