Cesium.js:构建三维数字地球
Cesium.js:构建三维数字地球
Cesium.js 是一个开源的 JavaScript 库,用于创建基于 Web 的三维地球和二维地图。它无需任何插件,利用 WebGL 进行硬件加速渲染,支持高精度全球可视化、时间动态数据展示以及与多种地理空间数据格式的无缝集成。本教程将带你从零开始,掌握用 Cesium.js 搭建可交互三维地球的核心技能。
1. 环境准备
在开始之前,你需要一个简单的 Web 开发环境。推荐使用 VS Code 作为编辑器,并确保本地已安装 Node.js(用于快速启动本地服务器)。
获取 Cesium.js
Cesium 提供多种引入方式:
- CDN 引入(最简单):直接在 HTML 中通过
<script>和<link>标签加载。 - npm 安装:
npm install cesium,适合工程化项目。 - 官方下载包:包含完整文档和示例。
本教程采用 CDN 方式,让你快速看到效果。创建一个 index.html 文件,写入基础结构:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cesium 三维地球入门</title>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<style>
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// 初始化代码将写在这里
</script>
</body>
</html>
提示:版本号
1.111可替换为最新版本。使用 CDN 时需要网络连接。
2. 创建第一个三维地球
在 <script> 标签内写入初始化代码,实例化 Cesium Viewer。
// 设置 Cesium 的静态资源路径(CDN 引入时必须指定)
Cesium.Ion.defaultAccessToken = '你的访问令牌'; // 可选,无令牌也能基础渲染
const viewer = new Cesium.Viewer('cesiumContainer', {
animation: false, // 隐藏动画控件
timeline: false, // 隐藏时间轴
baseLayerPicker: false, // 隐藏基础图层选择器
fullscreenButton: false,// 隐藏全屏按钮
geocoder: false, // 隐藏地理编码搜索框
homeButton: false, // 隐藏 Home 按钮
sceneModePicker: false, // 隐藏二三维切换按钮
navigationHelpButton: false,
});
保存文件并用本地服务器打开(推荐使用 VS Code 的 Live Server 插件)。你会看到一个没有 UI 控件的纯净三维地球,可以用鼠标拖拽旋转、缩放。
参数说明:通过配置项可以控制 Viewer 的界面控件显示/隐藏。animation 和 timeline 常用于时间序列数据展示,在静态场景中建议关闭以简化界面。
3. 更换底图与地形
默认使用的是 Bing Maps 影像,你可以轻松替换为其他影像服务或矢量地图。
3.1 更换影像图层
Cesium 支持多种影像提供者,例如 ArcGIS、OpenStreetMap、天地图等。下面演示添加 OpenStreetMap 底图并移除默认图层:
// 移除默认影像图层
viewer.imageryLayers.remove(viewer.imageryLayers.get(0));
// 添加 OpenStreetMap
viewer.imageryLayers.addImageryProvider(
new Cesium.OpenStreetMapImageryProvider({
url: 'https://a.tile.openstreetmap.org/'
})
);
你也可以尝试高德、谷歌等,需要遵循对应服务的切片 URL 规范。例如使用 UrlTemplateImageryProvider:
viewer.imageryLayers.addImageryProvider(
new Cesium.UrlTemplateImageryProvider({
url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
subdomains: ['1', '2', '3', '4'],
maximumLevel: 18
})
);
3.2 添加地形数据
Cesium 默认的地形是平滑的球体,为展示真实高程,需要添加地形提供者。最便捷的方式是使用 Cesium ion 提供的全球地形(需注册获取 token),或自行部署地形服务。
使用 Cesium World Terrain(需在 Cesium.Ion.defaultAccessToken 中设置有效 token):
viewer.terrainProvider = Cesium.createWorldTerrain({
requestWaterMask: true, // 显示水面效果
requestVertexNormals: true // 请求法线以增强光照
});
若没有 ion token,可使用 Cesium.CesiumTerrainProvider 从其他 URL 加载,但初学者建议先跳过地形,保持基础效果。
4. 添加三维实体(Entity)
Cesium 中的实体(Entity)是向场景中添加点、线、面、模型、标签等图形的高层 API,使用简单。所有实体都通过 viewer.entities 集合管理。
4.1 添加一个标记点
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.397428, 39.90923, 100), // 经度, 纬度, 高度(米)
point: {
pixelSize: 10,
color: Cesium.Color.RED
},
label: {
text: '北京',
font: '16px sans-serif',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -12)
}
});
fromDegrees 将经纬度转为世界坐标。第三个参数为高度(单位米),设置为 100 可使点浮于地表之上。
4.2 绘制折线
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
116.38, 39.90, // 北京
121.47, 31.23 // 上海
]),
width: 3,
material: Cesium.Color.CYAN
}
});
fromDegreesArray 接受 [经度, 纬度, 经度, 纬度, ...] 的平铺数组,高度默认 0。
4.3 添加多边形
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
116.0, 39.8,
117.0, 39.8,
117.0, 40.2,
116.0, 40.2
]),
material: Cesium.Color.YELLOW.withAlpha(0.5),
outline: true,
outlineColor: Cesium.Color.BLACK
}
});
4.4 加载 3D 模型(glTF)
Cesium 原生支持 glTF 和 3D Tiles 格式。下面加载一个简单的飞行器模型(使用 Cesium 官方示例模型):
const modelEntity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(122.0, 39.5, 500),
model: {
uri: 'https://cesium.com/public/SampleData/models/CesiumAir/Cesium_Air.glb',
minimumPixelSize: 128,
maximumScale: 20000
}
});
// 将相机飞向该模型
viewer.flyTo(modelEntity);
5. 相机控制与飞行
控制观察视角是三维场景交互的核心。viewer.camera 提供了丰富的飞行方法。
- 飞行到指定位置:
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 50000), // 经度, 纬度, 高度
orientation: {
heading: Cesium.Math.toRadians(0.0), // 偏航角
pitch: Cesium.Math.toRadians(-25.0), // 俯仰角(负值向下看)
roll: 0.0
},
duration: 3 // 飞行持续秒数
});
- 飞往实体:可直接使用
viewer.flyTo(entity)。 - 设置默认视角:在 Viewer 初始化参数中使用
homeButton或使用setView方法。
6. 用户交互事件
Cesium 提供了基于屏幕空间的事件处理,可以拾取点击位置的实体或获取坐标。
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(click) {
const pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
// pickedObject.id 即被点击的实体
console.log('点击了实体:', pickedObject.id);
} else {
// 获取点击位置的地球表面坐标
const cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(click.position), viewer.scene);
if (cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
console.log(`点击位置: 经度 ${longitude.toFixed(5)}, 纬度 ${latitude.toFixed(5)}`);
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
注意:在移动端,触摸事件应使用
Cesium.ScreenSpaceEventType.LEFT_CLICK,Cesium 会自动适配。
7. 添加基础的图层控制
即使隐藏了图层选择器,也可以自己编写按钮来切换影像图层。简单示例:添加两个图层并控制可见性。
const imageryLayers = viewer.imageryLayers;
// 添加两个图层并默认显示第一个
const layer1 = imageryLayers.addImageryProvider(new Cesium.OpenStreetMapImageryProvider({ url: 'https://a.tile.openstreetmap.org/' }));
const layer2 = imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
subdomains: ['1','2','3','4']
}));
layer2.show = false; // 隐藏高德图层
// HTML 中添加两个按钮,调用切换函数
function switchToOSM() {
layer1.show = true;
layer2.show = false;
}
function switchToAMap() {
layer1.show = false;
layer2.show = true;
}
在 <body> 中放置按钮并绑定点击事件即可实现简单的图层切换。
8. 常见问题与优化
- 跨域问题:加载本地地形或切片数据时,需通过服务器环境运行 HTML,避免 file 协议。
- 性能优化:避免同时加载大量高精度模型;合理使用
minimumPixelSize控制模型显示尺寸;加载 3D Tiles 时开启skipLevelOfDetail等。 - 移动端适配:为提升移动端体验,关闭不必要控件,降低几何密度,并测试触摸交互。
- Cesium ion Token:生产项目中建议申请免费 Token,以获得更好的影像和地形服务稳定性。
9. 下一步学习方向
掌握以上基础后,你可以继续探索:
- 3D Tiles 加载:展示城市级倾斜摄影、BIM 模型等海量三维数据。
- CZML 动态数据:按时间轴播放轨迹动画。
- 几何体(Primitive)编程:获取更高性能的自定义渲染。
- 与 Vue / React 集成:将 Cesium 封装为组件,嵌入现代前端框架。
- 地形切片发布:学习使用 Cesium Terrain Builder 制作自定义高程数据。
本教程已涵盖 Cesium.js 最核心的 80% 日常操作,动手实践是加深理解的最佳方式。现在,打开你的编辑器,创建属于自己的三维地球应用吧!