首页  |  学习总览  |  ← 返回专题总览 进阶专题 14 · 3D 开发

CesiumJS 地理空间 3D 开发 🔥 热门

从基础地图到数字孪生,从坐标系转换到 3D Tiles,掌握 Web 地理空间开发核心技术
学习时长:约 25 小时 | 前置:JavaScript、WebGL 基础 | 产出:完整 Cesium 项目

一、CesiumJS 概述

什么是 CesiumJS?

CesiumJS 是一个开源 JavaScript 库,用于创建高性能、跨平台、跨浏览器的 3D 地球和地图应用。由 Analytical Graphics, Inc. (AGI) 开发,广泛用于 GIS、数字孪生、无人机、卫星等领域。

CesiumJS
→
WebGL 渲染
→
地理坐标系
→
3D Tiles
→
数据可视化
特性说明
开源免费Apache 2.0 协议,商用友好
WebGL 渲染基于 WebGL,GPU 加速
多数据源支持 WMS、WMTS、KML、GeoJSON、CZML 等
3D Tiles海量 3D 数据流式加载标准
坐标系支持WGS84、Web Mercator、地方坐标系
时间动态支持时间轴动画

二、环境搭建与基础

2.1 快速开始

// 安装
npm install cesium

// Vite 配置
// vite.config.js
import { defineConfig } from 'vite';
import cesium from 'cesium-vite-plugin';

export default defineConfig({
  plugins: [cesium()],
  resolve: {
    alias: {
      'cesium': 'cesium/Source/Cesium.js'
    }
  }
});

// 基础使用
import * as Cesium from 'cesium';

// 设置 Token(申请地址:https://cesium.com/ion/)
Cesium.Ion.defaultAccessToken = 'your_access_token';

// 创建 Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
  terrainProvider: Cesium.createWorldTerrain(),
  animation: false,         // 动画控件
  timeline: false,           // 时间轴
  baseLayerPicker: false,    // 图层选择
  geocoder: false,           // 地理编码
  homeButton: true,          // 主页按钮
  sceneModePicker: true,     // 场景模式
  navigationHelpButton: false,
  fullscreenButton: true,
  vrButton: false
});

// 定位到指定位置
viewer.camera.flyTo({
  destination: Cesium.Cartesian3.fromDegrees(116.397, 39.909, 15000000),
  orientation: {
    heading: Cesium.Math.toRadians(0),
    pitch: Cesium.Math.toRadians(-90),
    roll: 0
  }
});

2.2 Viewer 核心组件

组件说明
sceneScene 场景,管理 3D 世界
cameraCamera 相机,控制视角
canvasCanvas 画布,WebGL 渲染目标
clockClock 时钟,控制时间
dataSources数据源集合
entities实体集合
imageryLayers影像图层集合
terrainProvider地形提供者

三、坐标系与空间参考

3.1 常用坐标系

坐标系说明使用场景
WGS84 (EPSG:4326)经纬度坐标系GPS 定位、地理数据
Web Mercator (EPSG:3857)墨卡托投影地图瓦片、2D 地图
ECEF地心地固坐标系3D 空间计算
ENU东北天坐标系局部相对位置

3.2 坐标转换

// 经纬度 → 笛卡尔坐标
const cartesian = Cesium.Cartesian3.fromDegrees(
  116.397, // 经度
  39.909,  // 纬度
  100      // 高度(米)
);

// 经纬度数组 → 笛卡尔数组
const positions = Cesium.Cartesian3.fromDegreesArray([
  116.39, 39.90,
  116.40, 39.90,
  116.40, 39.91,
]);

// 笛卡尔坐标 → 经纬度
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;

// 屏幕坐标 → 世界坐标
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((event) => {
  const position = viewer.camera.pickEllipsoid(event.position);
  if (position) {
    const carto = Cesium.Cartographic.fromCartesian(position);
    console.log(`选中位置:${Cesium.Math.toDegrees(carto.longitude)}, ${Cesium.Math.toDegrees(carto.latitude)}`);
  }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

四、实体与数据可视化

4.1 Entity API

// 添加点
viewer.entities.add({
  name: '北京',
  position: Cesium.Cartesian3.fromDegrees(116.397, 39.909),
  point: {
    pixelSize: 10,
    color: Cesium.Color.RED,
    outlineColor: Cesium.Color.WHITE,
    outlineWidth: 2
  },
  label: {
    text: '北京',
    font: '14px sans-serif',
    fillColor: Cesium.Color.WHITE,
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth: 2,
    outlineColor: Cesium.Color.BLACK,
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    pixelOffset: new Cesium.Cartesian2(0, -10)
  }
});

// 添加线
viewer.entities.add({
  polyline: {
    positions: Cesium.Cartesian3.fromDegreesArray([
      116.39, 39.90,
      121.47, 31.23,
      113.26, 23.13
    ]),
    width: 3,
    material: Cesium.Color.BLUE
  }
});

// 添加面
viewer.entities.add({
  polygon: {
    hierarchy: Cesium.Cartesian3.fromDegreesArray([
      116.39, 39.90,
      116.40, 39.90,
      116.40, 39.91,
      116.39, 39.91
    ]),
    material: Cesium.Color.GREEN.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.BLACK
  }
});

// 添加 3D 模型
viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(116.397, 39.909, 100),
  model: {
    uri: 'models/Cesium_Air.glb',
    minimumPixelSize: 128,
    maximumScale: 20000
  }
});

4.2 数据源

GeoJSON 加载

// 加载 GeoJSON
const dataSource = await Cesium.GeoJsonDataSource.load('data/china.geojson', {
  stroke: Cesium.Color.HOTPINK,
  fill: Cesium.Color.PINK.withAlpha(0.5),
  strokeWidth: 3
});
viewer.dataSources.add(dataSource);

// 加载 KML
const kmlDataSource = await Cesium.KmlDataSource.load('data/example.kml');
viewer.dataSources.add(kmlDataSource);

// 加载 CZML(时间动态数据)
const czmlDataSource = await Cesium.CzmlDataSource.load('data/example.czml');
viewer.dataSources.add(czmlDataSource);

五、3D Tiles 大规模数据

5.1 3D Tiles 概述

3D Tiles 是 OGC 社区标准,用于流式传输大规模异构 3D 地理空间数据。

倾斜摄影
→
点云
→
BIM 模型
→
矢量数据

5.2 加载 3D Tiles

// 加载 3D Tiles
const tileset = await Cesium.Cesium3DTileset.fromUrl('https://example.com/tileset.json');
viewer.scene.primitives.add(tileset);

// 定位到模型
viewer.zoomTo(tileset);

// 设置样式
tileset.style = new Cesium.Cesium3DTileStyle({
  color: {
    conditions: [
      ["\${Height} >= 100", "color('red')"],
      ["\${Height} >= 50", "color('orange')"],
      ['true', "color('blue')"]
    ]
  }
});

// 监听加载完成
tileset.allTilesLoaded.addEventListener(() => {
  console.log('所有瓦片加载完成');
});

六、相机与飞行控制

6.1 相机控制

// 设置视角
viewer.camera.setView({
  destination: Cesium.Cartesian3.fromDegrees(116.397, 39.909, 5000),
  orientation: {
    heading: Cesium.Math.toRadians(0),   // 朝向
    pitch: Cesium.Math.toRadians(-45),    // 俯仰
    roll: 0                                 // 翻滚
  }
});

// 飞行到指定位置
viewer.camera.flyTo({
  destination: Cesium.Cartesian3.fromDegrees(116.397, 39.909, 5000),
  duration: 3, // 飞行时间(秒)
  maximumHeight: 10000,
  complete: () => { console.log('飞行完成'); }
});

// 飞行到实体
viewer.flyTo(entity, {
  duration: 2,
  offset: new Cesium.HeadingPitchRange(
    Cesium.Math.toRadians(0),
    Cesium.Math.toRadians(-45),
    1000
  )
});

// 原地旋转
viewer.clock.onTick.addEventListener(() => {
  viewer.camera.rotate(Cesium.Math.toRadians(0.1));
});

七、高级特效与场景

7.1 天气与大气

// 设置大气效果
viewer.scene.globe.enableLighting = true;  // 启用光照
viewer.scene.fog.enabled = true;             // 雾效
viewer.scene.skyAtmosphere.hueShift = -0.0;
viewer.scene.skyAtmosphere.saturationShift = 0.1;
viewer.scene.skyAtmosphere.brightnessShift = -0.1;

// 太阳位置(基于时间)
viewer.scene.globe.enableLighting = true;

7.2 后处理效果

// 高亮轮廓
const outlineBlue = new Cesium.PostProcessStageLibrary.createSilhouetteStage();
viewer.scene.postProcessStages.add(outlineBlue);

八、性能优化

优化策略

策略说明
3D Tiles使用 3D Tiles 替代普通模型,支持 LOD
实例化Primitive API 比 Entity 性能更好
视锥剔除自动剔除视野外的对象
按需加载根据相机距离加载不同精度
Web Worker复杂计算放到 Worker 中
纹理压缩使用 KTX2 等压缩格式
// 使用 Primitive API 提升性能
const instance = new Cesium.GeometryInstance({
  geometry: new Cesium.RectangleGeometry({
    rectangle: Cesium.Rectangle.fromDegrees(116.39, 39.90, 116.40, 39.91),
    vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
  }),
  attributes: {
    color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))
  }
});

viewer.scene.primitives.add(new Cesium.Primitive({
  geometryInstances: instance,
  appearance: new Cesium.PerInstanceColorAppearance()
}));

九、数字孪生实战架构

完整数字孪生系统架构

┌─────────────────────────────────────────────────┐
│                   前端展示层                       │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐            │
│  │ CesiumJS │ │ Three.js│ │  图表    │            │
│  └─────────┘ └─────────┘ └─────────┘            │
├─────────────────────────────────────────────────┤
│                   数据接入层                       │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐            │
│  │ IoT 数据 │ │ GIS 数据 │ │ 业务数据 │            │
│  └─────────┘ └─────────┘ └─────────┘            │
├─────────────────────────────────────────────────┤
│                   服务层                           │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐            │
│  │ 3D Tiles │ │ WebSocket│ │  API    │            │
│  └─────────┘ └─────────┘ └─────────┘            │
└─────────────────────────────────────────────────┘

十、面试高频问题

Q1:CesiumJS 和 Google Earth 有什么区别?
查看答案 ▼

CesiumJS 是开源库,可以嵌入网页;Google Earth 是独立应用。CesiumJS 更适合开发定制化的 3D 地理应用,支持自定义数据源和交互逻辑。

Q2:3D Tiles 和传统模型加载有什么区别?
查看答案 ▼
  • 数据量级:3D Tiles 支持 GB 级数据,传统模型通常 MB 级
  • 加载方式:3D Tiles 按需加载(LOD),传统模型一次性加载
  • 精度控制:3D Tiles 根据距离自动切换精度
  • 标准:3D Tiles 是 OGC 标准,通用性强
Q3:CesiumJS 性能优化的关键点?
查看答案 ▼
  • 使用 Primitive API 替代 Entity API
  • 3D Tiles 替代普通模型
  • 合理使用 requestRenderMode 减少渲染
  • 纹理压缩(KTX2/Basis)
  • 视锥剔除和遮挡剔除
  • Web Worker 处理数据解析