WebGIS开发入门教程九: 三维地图咋做?Cesium怎么跑?

GIS基础理论
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

在这篇《WebGIS开发入门教程九: 三维地图咋做?Cesium怎么跑?》里,我们把问题说具体:你已经会做二维 WebGIS,想把地图变成三维地球、加载影像底图、叠加点线面数据,并在本地把 Cesium 项目跑起来。本文不追求一次讲完所有三维 GIS 概念,而是先帮你完成一个可运行、可验证、可继续扩展的 Cesium 入门工程。

WebGIS开发入门教程 Cesium三维地图运行流程
Cesium 三维地图的基本运行链路:浏览器加载 CesiumJS,再叠加影像、地形、三维模型和业务数据。

引言:三维 WebGIS 到底解决什么问题

二维 WebGIS 更适合看行政区、道路、地块、POI 和专题图;三维 WebGIS 更适合表达建筑、地形起伏、地下管线、倾斜摄影、城市空间关系和飞行浏览。Cesium 是目前 WebGIS 三维地图开发中常用的开源框架之一,它可以在浏览器中渲染三维地球,并支持影像、地形、3D Tiles、GeoJSON、CZML 等数据。

对 GIS 初学者来说,最容易卡住的不是“Cesium 能做什么”,而是下面几个问题:

  • Cesium 怎么安装,是否必须使用复杂前端框架?
  • 为什么直接双击 HTML 文件打不开三维地图?
  • 影像底图、地形、三维模型分别是什么数据?
  • 自己的点线面数据如何叠加到 Cesium 里?
  • 开发时常见黑屏、跨域、Token 报错该怎么排查?

背景:Cesium 在 WebGIS 三维地图中的位置

CesiumJS 是运行在浏览器中的三维地理空间可视化库。它依赖 WebGL 进行图形渲染,因此用户不需要安装桌面 GIS 软件,只要浏览器支持 WebGL,就可以打开三维地图应用。

在一个常见的 WebGIS 三维项目中,Cesium 通常负责前端地图渲染,后端或数据服务负责提供空间数据。典型结构如下:

  • 前端:HTML、CSS、JavaScript、CesiumJS,用于创建三维地球、控制相机、加载图层。
  • 影像服务:XYZ、WMTS、TMS 或 ArcGIS MapServer,用于提供底图瓦片。
  • 地形服务:Cesium Terrain 或其他地形切片,用于表现高程起伏。
  • 三维数据:3D Tiles、glTF、倾斜摄影模型、BIM 转换结果。
  • 业务数据:GeoJSON、CZML、KML、后端接口返回的点线面数据。

如果你熟悉 Leaflet 或 OpenLayers,可以把 Cesium 理解为“更偏三维场景的 WebGIS 渲染引擎”。它不是完整的 GIS 平台,也不负责帮你自动清洗数据、建库、发布服务;这些工作仍然需要 QGIS、ArcGIS Pro、GDAL、PostGIS、GeoServer 或其他工具配合完成。

原理:Cesium 怎么把三维地图跑起来

Cesium 三维地图的运行逻辑可以拆成三层:场景、图层和相机。

1. 场景:Viewer 是入口

Cesium 中最常用的入口对象是 Cesium.Viewer。它会在指定的网页容器中创建三维地球,并默认带有时间轴、图层选择器、全屏按钮、动画控件等界面组件。

const viewer = new Cesium.Viewer('cesiumContainer');

这行代码的意思是:在页面中 id 为 cesiumContainer 的元素里创建一个 Cesium 三维地图。

2. 图层:影像、地形和数据不是一回事

很多初学者会把“底图”“地形”“三维模型”混在一起。它们在 Cesium 中对应不同类型的数据:

  • 影像图层:贴在地球表面的图片瓦片,例如卫星影像、电子地图、遥感影像。
  • 地形数据:表示地表高低起伏,让山地、谷地有真实高度。
  • 矢量数据:点、线、面,例如监测点、路线、行政区。
  • 3D Tiles:大规模三维模型数据,例如倾斜摄影、城市建筑、BIM 场景。

如果只加载影像,没有地形,地图看起来仍是一个光滑椭球;如果加载了地形但没有影像,就有高低起伏但缺少可读底图;如果加载 3D Tiles,则可以看到真实建筑或模型。

3. 相机:三维地图的浏览方式

二维地图主要是缩放和平移,三维地图还涉及视角、俯仰角、航向角和高度。Cesium 中可以通过 viewer.camera.flyTo 把相机飞到指定位置。

viewer.camera.flyTo({
  destination: Cesium.Cartesian3.fromDegrees(116.391, 39.907, 15000)
});

这里的经纬度示例定位到北京附近,高度为 15000 米。注意 Cesium 默认使用 WGS84 经纬度坐标,这是 WebGIS 三维开发中非常重要的前提。

步骤:从零跑起一个 Cesium 三维地图

步骤一:准备开发环境

最简单的 Cesium 入门方式是使用本地静态服务器运行 HTML 页面。建议准备:

  • 一个现代浏览器,例如 Chrome、Edge 或 Firefox。
  • Node.js,用于启动本地开发服务。
  • 一个代码编辑器,例如 VS Code。
  • 稳定网络,用于访问在线 Cesium 资源或地图服务。

不要直接双击打开 HTML 文件。Cesium 加载资源时经常涉及模块文件、静态资源、字体、图片和接口请求,直接使用 file:// 路径容易出现资源加载失败。

步骤二:创建项目目录

新建一个目录,例如:

cesium-demo/
  index.html
  package.json

在项目目录下初始化 npm:

npm init -y

安装一个轻量级本地服务器:

npm install vite --save-dev

package.json 中添加启动命令:

{
  "scripts": {
    "dev": "vite --host 0.0.0.0"
  },
  "devDependencies": {
    "vite": "^5.0.0"
  }
}

如果你的 Vite 版本不同,不影响本文核心流程。实际项目中以当前安装版本为准。

步骤三:写一个最小 Cesium 页面

index.html 中写入以下内容:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <title>Cesium 三维地图入门</title>
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Cesium.js"></script>
  <link href="https://cesium.com/downloads/cesiumjs/releases/1.120/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>
    const viewer = new Cesium.Viewer('cesiumContainer', {
      animation: false,
      timeline: false,
      baseLayerPicker: true
    });

    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(116.391, 39.907, 15000)
    });
  </script>
</body>
</html>

启动项目:

npm run dev

浏览器打开终端提示的本地地址,例如:

http://localhost:5173/

如果页面出现三维地球,并且镜头飞到北京附近,说明 Cesium 已经跑起来了。

步骤四:配置 Cesium Ion Token

Cesium 默认的一些在线影像、地形或资源可能需要 Cesium Ion Token。你可以在 Cesium Ion 官网注册账号,创建 Access Token,然后在代码中加入:

Cesium.Ion.defaultAccessToken = '你的CesiumIonToken';

完整位置通常放在创建 Viewer 之前:

Cesium.Ion.defaultAccessToken = '你的CesiumIonToken';

const viewer = new Cesium.Viewer('cesiumContainer', {
  animation: false,
  timeline: false
});

如果你使用的是自有影像服务、自有地形服务或离线数据,可以根据项目情况减少对 Cesium Ion 的依赖。但入门阶段,先用官方在线资源验证环境会更省事。

步骤五:叠加一个 GeoJSON 点数据

WebGIS 开发入门不应只停留在显示地球,还要能加载自己的业务数据。下面示例在 Cesium 中添加一个点位:

const point = viewer.entities.add({
  name: '示例监测点',
  position: Cesium.Cartesian3.fromDegrees(116.391, 39.907, 100),
  point: {
    pixelSize: 12,
    color: Cesium.Color.RED,
    outlineColor: Cesium.Color.WHITE,
    outlineWidth: 2
  },
  label: {
    text: '监测点',
    font: '16px sans-serif',
    fillColor: Cesium.Color.WHITE,
    outlineColor: Cesium.Color.BLACK,
    outlineWidth: 2,
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    pixelOffset: new Cesium.Cartesian2(0, -16)
  }
});

viewer.zoomTo(point);

如果你已经有 GeoJSON 文件,可以这样加载:

Cesium.GeoJsonDataSource.load('/data/sample.geojson', {
  stroke: Cesium.Color.YELLOW,
  fill: Cesium.Color.YELLOW.withAlpha(0.3),
  strokeWidth: 2,
  clampToGround: true
}).then(function(dataSource) {
  viewer.dataSources.add(dataSource);
  viewer.zoomTo(dataSource);
});

这里的 clampToGround 表示贴地显示。对于道路、地块、行政区等二维矢量数据,贴地通常更符合直觉;对于飞行轨迹、气象探空、塔吊监测等三维数据,则需要保留高度值。

步骤六:加载 3D Tiles 三维模型

Cesium 真正适合三维 WebGIS 的一个关键能力是加载 3D Tiles。3D Tiles 常用于倾斜摄影、城市建筑模型、BIM 转换场景和大规模点云。

const tileset = await Cesium.Cesium3DTileset.fromUrl('/tileset/tileset.json');

viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset);

如果你的浏览器控制台提示 await 相关错误,可以把代码放到异步函数里:

async function loadTileset() {
  const tileset = await Cesium.Cesium3DTileset.fromUrl('/tileset/tileset.json');
  viewer.scene.primitives.add(tileset);
  viewer.zoomTo(tileset);
}

loadTileset();

注意,3D Tiles 不是一个单独模型文件,而通常是一组目录和瓦片文件。部署时必须保持目录结构完整,不能只复制 tileset.json

常见坑:Cesium 跑不起来时先查这些问题

1. 页面黑屏或只有控件没有地球

先打开浏览器开发者工具,看 Console 和 Network。常见原因包括:

  • Cesium.js 或 widgets.css 地址写错。
  • 网络无法访问 CDN。
  • 浏览器不支持 WebGL,或 WebGL 被禁用。
  • 容器没有高度,导致地图实际高度为 0。

尤其要检查 CSS 中是否给 htmlbody#cesiumContainer 设置了 height: 100%

2. 直接打开 HTML 文件导致资源加载失败

不要使用双击方式打开页面。请通过 Vite、Nginx、Apache、Python http.server 或其他本地服务访问。WebGIS 开发中,大多数地图资源都应通过 HTTP 或 HTTPS 请求加载。

3. Token 报错或默认底图加载失败

如果控制台提示 Cesium Ion Token 无效、过期或无权限,请检查:

  • Token 是否复制完整。
  • 是否在创建 Viewer 之前设置 Token。
  • Token 权限是否包含你要访问的资源。
  • 当前网络是否可以访问 Cesium Ion 服务。

如果项目要求内网部署或离线运行,应改用自有影像、地形和三维服务,不要把核心能力完全依赖外部在线服务。

4. 坐标偏移或数据位置不对

Cesium 默认使用 WGS84 经纬度坐标。很多国内数据可能来自 CGCS2000、高斯投影、Web Mercator、地方坐标或经过加密偏移的互联网地图坐标。数据位置不对时,优先检查坐标系,而不是盲目调经纬度。

  • GeoJSON 通常应使用 WGS84 经纬度。
  • 从 QGIS 或 ArcGIS Pro 导出前,确认图层坐标系和导出坐标系。
  • 如果数据是投影坐标,需要先转换为经纬度再加载。
  • 互联网底图存在坐标偏移时,要确认使用的是哪一种坐标体系。

5. 3D Tiles 加载很慢或浏览器卡顿

三维模型不是越精细越好。倾斜摄影、BIM 和点云数据量很大,必须做瓦片化、层级细节和压缩优化。常见排查方向:

  • 模型是否已经转换为 3D Tiles,而不是直接加载超大 glTF。
  • 瓦片层级是否合理,根节点是否过大。
  • 纹理是否过大,是否存在大量无用细节。
  • 服务器是否支持压缩和缓存。
  • 浏览器显卡性能是否满足场景规模。

方法比较:Cesium、Leaflet、OpenLayers 怎么选

工具 适合场景 优势 限制
Cesium 三维地球、三维城市、地形、倾斜摄影、3D Tiles 三维能力强,适合大范围地理空间可视化 学习曲线高于二维库,对数据优化和浏览器性能更敏感
Leaflet 轻量二维地图、点位展示、移动端简单地图 简单、插件多、入门快 原生三维能力弱,不适合复杂三维场景
OpenLayers 专业二维 WebGIS、复杂图层、投影和交互 二维 GIS 能力强,适合严肃地图应用 三维不是主要方向,复杂三维需配合其他方案

如果你的需求是“做一个二维业务地图”,Leaflet 或 OpenLayers 往往更直接;如果需求是“做三维地球、加载倾斜摄影、展示城市建筑和地形”,Cesium 更合适。很多项目也会采用二维和三维联动:二维负责查询统计,三维负责空间展示和场景浏览。

检查清单:Cesium 三维地图开发前后都要核对

  • 运行方式:是否通过 HTTP 服务访问,而不是 file 路径直接打开。
  • 浏览器能力:是否支持 WebGL,显卡驱动是否正常。
  • 容器样式:地图容器是否有明确宽高。
  • 资源路径:Cesium 静态资源、CSS、图片、模型路径是否正确。
  • Token 权限:使用 Cesium Ion 时,Token 是否有效且权限足够。
  • 坐标系统:业务数据是否转换到 Cesium 可正确识别的经纬度坐标。
  • 数据体量:GeoJSON、3D Tiles、影像瓦片是否经过合理切片和压缩。
  • 网络请求:是否存在跨域、404、403、证书错误或加载超时。
  • 相机定位:数据加载成功后,是否使用 zoomToflyTo 定位到数据范围。
  • 部署环境:生产环境是否准备好静态资源目录、地图服务地址和缓存策略。

FAQ:Cesium 入门常见问题

Q1:Cesium 必须配合 Vue 或 React 才能用吗?

不必须。Cesium 本身是 JavaScript 库,一个 HTML 页面就能跑起来。Vue、React、Vite 等只是工程化工具,适合中大型项目管理组件、状态和构建流程。入门阶段建议先用原生 HTML 和 JavaScript 理解 Viewer、图层、相机和数据加载。

Q2:Cesium 能不能加载 Shapefile?

Cesium 前端不适合直接加载 Shapefile。通常做法是先用 QGIS、ArcGIS Pro、GDAL 或后端服务把 Shapefile 转成 GeoJSON、CZML、矢量瓦片或接口数据,再在 Cesium 中加载。对于大数据量矢量图层,不建议直接把超大 GeoJSON 扔给浏览器。

Q3:Cesium 和 3D Tiles 是什么关系?

Cesium 是三维地图渲染库,3D Tiles 是面向大规模三维地理空间数据的瓦片格式。Cesium 可以加载 3D Tiles,但 Cesium 不等于 3D Tiles。你可以用 Cesium 显示影像、地形、点线面,也可以加载 3D Tiles 显示倾斜摄影、建筑模型和点云。

Q4:为什么我的 GeoJSON 在 Cesium 中位置偏了?

优先检查坐标系。Cesium 中 GeoJSON 通常应为 WGS84 经纬度。如果你的数据来自投影坐标、地方坐标、互联网地图坐标或未定义坐标系,都会造成偏移。建议先在 QGIS 或 ArcGIS Pro 中确认图层坐标系,再导出为 WGS84 经纬度 GeoJSON。

Q5:Cesium 可以做离线三维地图吗?

可以,但需要准备离线数据和本地服务。影像瓦片、地形瓦片、3D Tiles、业务数据和 Cesium 静态资源都要部署在内网或本机服务中。离线场景下不要依赖在线 Token、在线底图或外部 CDN。

Q6:初学 Cesium 应该先学哪些内容?

建议按顺序学习:Viewer 创建、相机控制、影像图层、GeoJSON 加载、Entity 点线面、地形、3D Tiles、交互拾取、性能优化、工程化部署。不要一开始就直接做大型数字孪生平台,否则容易被模型转换、坐标系统和前端框架同时卡住。

结论:先跑通,再叠加数据,最后优化三维场景

Cesium 三维地图入门的关键不是背 API,而是先建立正确工作流:用本地服务跑起页面,创建 Viewer,确认影像和地球正常显示,再逐步叠加点线面、地形和 3D Tiles。只要这个最小闭环打通,后续做三维城市、倾斜摄影展示、轨迹回放和 WebGIS 三维分析就有了基础。

对于 GIS 读者来说,学习 Cesium 时要特别关注坐标系、数据格式、服务部署和浏览器性能。二维 WebGIS 主要解决“平面地图怎么展示”,三维 WebGIS 还要解决“高度、视角、模型和大数据量怎么组织”。这也是 Cesium 开发比普通网页地图更容易踩坑的原因。

建议你把本文的最小示例先完整跑通,然后替换为自己的影像服务、GeoJSON 数据和 3D Tiles 模型。能加载自己的数据,才算真正进入 WebGIS 三维地图开发。