共计 4835 个字符,预计需要花费 13 分钟才能阅读完成。
技术背景
Cesium 是一个开源的 JavaScript 库,专门用于构建高性能的三维地理可视化应用。它基于 WebGL 技术,可以在浏览器中流畅渲染大规模的三维地形、影像和矢量数据。Cesium 的优势在于:

- 支持全球范围的高精度地形和影像数据
- 提供丰富的 API 用于创建和操作三维实体
- 跨平台,无需插件,纯浏览器运行
- 开源且社区活跃,文档完善
典型应用场景包括:
- 智慧城市数字孪生
- 军事模拟与演练
- 气象数据可视化
- 自然资源管理
环境准备
-
安装 Node.js(建议使用 LTS 版本)
# 检查安装是否成功 node -v npm -v -
创建项目目录并初始化
mkdir cesium-demo && cd cesium-demo npm init -y -
安装 Cesium
npm install cesium -
创建基础 HTML 结构
<!-- index.html --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Cesium Demo</title> <script src="node_modules/cesium/Build/Cesium/Cesium.js"></script> <link href="node_modules/cesium/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 src="app.js"></script> </body> </html>
核心实现
Viewer 初始化
在 app.js 中添加以下代码:
// 设置 Cesium ion 访问令牌(需注册获取)Cesium.Ion.defaultAccessToken = 'your_access_token';
// 初始化 Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
baseLayerPicker: true, // 显示底图选择器
terrainProvider: Cesium.createWorldTerrain(), // 使用 Cesium World Terrain
timeline: false, // 隐藏时间轴
animation: false, // 隐藏动画控件
sceneModePicker: false, // 隐藏场景模式选择器
navigationHelpButton: false, // 隐藏导航帮助按钮
infoBox: false, // 隐藏信息框
selectionIndicator: false, // 隐藏选择指示器
});
// 移除默认的版权信息(仅用于演示,生产环境请保留)viewer.cesiumWidget.creditContainer.style.display = 'none';
地形数据加载
Cesium 提供了多种地形数据源:
- Cesium World Terrain:高精度全球地形
- Ellipsoid Terrain:简单的椭球体地形
- 自定义地形服务
// 使用 Cesium World Terrain(需要 access token)viewer.terrainProvider = Cesium.createWorldTerrain({
requestWaterMask: true, // 请求水面效果
requestVertexNormals: true // 请求顶点法线用于光照
});
// 使用 Ellipsoid Terrain(无高度数据)// viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
实体添加
Cesium 提供了两种主要的实体添加方式:
- Primitive:底层 API,性能更高,适合大量静态几何体
- Entity:高层 API,更易用,支持动态属性
添加点实体(Entity 方式)
// 添加一个点
const pointEntity = viewer.entities.add({
name: '示例点',
position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100),
point: {
pixelSize: 10,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2
}
});
// 飞向该点
viewer.flyTo(pointEntity);
添加多边形(Primitive 方式)
const polygon = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(
Cesium.Cartesian3.fromDegreesArray([
116.3, 39.8,
116.5, 39.8,
116.5, 40.0,
116.3, 40.0
])
),
height: 0
}),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE.withAlpha(0.5)
)
}
}),
appearance: new Cesium.PerInstanceColorAppearance({
flat: true,
translucent: true
})
});
viewer.scene.primitives.add(polygon);
完整代码示例
以下是一个完整的简单三维地图 demo:
// app.js
Cesium.Ion.defaultAccessToken = 'your_access_token';
const viewer = new Cesium.Viewer('cesiumContainer', {
baseLayerPicker: true,
terrainProvider: Cesium.createWorldTerrain({
requestWaterMask: true,
requestVertexNormals: true
}),
timeline: false,
animation: false
});
// 添加北京的点
const beijing = viewer.entities.add({
name: '北京',
position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 0),
point: {
pixelSize: 15,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2
},
label: {
text: '北京',
font: '14pt sans-serif',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -15)
}
});
// 添加上海的点
const shanghai = viewer.entities.add({
name: '上海',
position: Cesium.Cartesian3.fromDegrees(121.47, 31.23, 0),
point: {
pixelSize: 15,
color: Cesium.Color.BLUE,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2
},
label: {
text: '上海',
font: '14pt sans-serif',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -15)
}
});
// 添加连接线
const line = viewer.entities.add({
name: '北京 - 上海连线',
polyline: {
positions: [Cesium.Cartesian3.fromDegrees(116.4, 39.9),
Cesium.Cartesian3.fromDegrees(121.47, 31.23)
],
width: 3,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.2,
color: Cesium.Color.YELLOW
})
}
});
// 初始视角
viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(118.0, 35.0, 3000000),
orientation: {heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-45),
roll: 0.0
}
});
性能优化
- 内存管理
-
及时销毁不再使用的实体
viewer.entities.remove(entity); -
相机控制
- 使用 flyTo 而不是 setView 避免突兀的视角切换
-
限制相机高度和移动速度
-
LOD(细节层次)
- 为复杂模型设置 LOD
-
使用 Cesium3DTileset 加载大规模 3D 数据
-
帧率监控
viewer.scene.postRender.addEventListener(function() { const fps = viewer.clock.multiplier / viewer.clock._lastSystemTime; console.log(` 当前帧率: ${fps.toFixed(1)}`); });
避坑指南
- 跨域问题
- 开发时使用本地服务器(如 http-server)
-
生产环境配置 CORS
-
Token 配置
- 记得设置 Cesium ion access token
-
免费账户有配额限制
-
坐标系转换
- Cesium 使用 WGS84 坐标系
- 常用转换方法:
// 经纬度转笛卡尔坐标 const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height); // 笛卡尔坐标转经纬度 const cartographic = Cesium.Cartographic.fromCartesian(position); const longitude = Cesium.Math.toDegrees(cartographic.longitude); const latitude = Cesium.Math.toDegrees(cartographic.latitude);
进阶建议
- 学习路径建议:
- 掌握基础 API 后学习 3D Tiles
- 了解 Cesium 的着色器系统
-
研究自定义地形和影像服务
-
扩展功能方向:
- 集成第三方 GIS 数据(GeoJSON, WMS 等)
- 实现地形分析功能(可视域分析、剖面分析等)
- 开发自定义着色器效果
思考与实践
- 尝试修改示例代码,添加你所在城市的标记
- 研究如何加载本地地形数据(如 DEM 数据)
- 探索 Cesium 的时间动态功能,如随时间变化的轨迹显示
通过这篇教程,你应该已经掌握了 Cesium 的基础使用方法。三维地理可视化是一个广阔的领域,Cesium 提供了强大的工具集,期待看到你创建出精彩的应用!
正文完
