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 开始。