Cesium.js:构建三维数字地球

FreeGuideOnline 最新 2026-06-18

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 的界面控件显示/隐藏。animationtimeline 常用于时间序列数据展示,在静态场景中建议关闭以简化界面。

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% 日常操作,动手实践是加深理解的最佳方式。现在,打开你的编辑器,创建属于自己的三维地球应用吧!