第02章 - 环境搭建与快速开始
第02章:环境搭建与快速开始
2.1 开发环境准备
2.1.1 基础环境要求
在开始 CesiumJS 开发之前,需要准备以下基础环境:
| 环境 | 要求 | 推荐版本 |
|---|---|---|
| Node.js | 16.x 或更高 | 18.x LTS |
| npm/yarn/pnpm | 包管理器 | npm 8.x+ |
| 现代浏览器 | 支持 WebGL 2.0 | Chrome 90+ |
| 代码编辑器 | 支持 JavaScript/TypeScript | VS Code |
2.1.2 检查 Node.js 环境
# 检查 Node.js 版本
node -v
# 应输出:v18.x.x 或更高
# 检查 npm 版本
npm -v
# 应输出:8.x.x 或更高
2.1.3 安装 Node.js
如果尚未安装 Node.js,可以通过以下方式安装:
Windows/macOS:
- 访问 https://nodejs.org
- 下载 LTS 版本
- 运行安装程序
使用 nvm 管理版本(推荐):
# 安装 nvm (Linux/macOS)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
# 安装 Node.js
nvm install 18
nvm use 18
2.2 项目创建方式
2.2.1 方式一:直接引入 CDN(最简单)
这是最快速的入门方式,适合学习和原型开发:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CesiumJS 快速开始</title>
<!-- 引入 Cesium 样式 -->
<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>
<!-- 引入 Cesium 库 -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Cesium.js"></script>
<script>
// 设置 Cesium ion 访问令牌
Cesium.Ion.defaultAccessToken = 'your_access_token';
// 创建 Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain()
});
// 飞到北京
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 15000)
});
</script>
</body>
</html>
2.2.2 方式二:使用 npm 创建(推荐)
这是生产环境推荐的方式:
# 创建项目目录
mkdir cesium-project
cd cesium-project
# 初始化 npm 项目
npm init -y
# 安装 CesiumJS
npm install cesium
# 安装开发依赖(可选,用于构建)
npm install --save-dev vite
项目结构:
cesium-project/
├── node_modules/
├── public/
│ └── index.html
├── src/
│ └── main.js
├── package.json
└── vite.config.js
2.2.3 方式三:使用 Vite 快速创建
# 使用 Vite 创建项目
npm create vite@latest cesium-app -- --template vanilla
cd cesium-app
# 安装依赖
npm install
npm install cesium
npm install --save-dev vite-plugin-cesium
配置 vite.config.js:
import { defineConfig } from 'vite';
import cesium from 'vite-plugin-cesium';
export default defineConfig({
plugins: [cesium()]
});
修改 main.js:
import * as Cesium from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';
// 设置访问令牌
Cesium.Ion.defaultAccessToken = 'your_access_token';
// 创建 Viewer
const viewer = new Cesium.Viewer('app', {
terrainProvider: Cesium.createWorldTerrain()
});
修改 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>CesiumJS Vite 项目</title>
<style>
html, body, #app {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.js"></script>
</body>
</html>
2.2.4 方式四:Vue 3 + CesiumJS
# 创建 Vue 3 项目
npm create vue@latest cesium-vue-app
cd cesium-vue-app
# 安装依赖
npm install
npm install cesium
npm install --save-dev vite-plugin-cesium
配置 vite.config.js:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import cesium from 'vite-plugin-cesium';
export default defineConfig({
plugins: [vue(), cesium()]
});
创建 CesiumViewer.vue 组件:
<template>
<div ref="cesiumContainer" class="cesium-container"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import * as Cesium from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';
const cesiumContainer = ref(null);
let viewer = null;
onMounted(() => {
Cesium.Ion.defaultAccessToken = 'your_access_token';
viewer = new Cesium.Viewer(cesiumContainer.value, {
terrainProvider: Cesium.createWorldTerrain()
});
// 飞到初始位置
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 15000)
});
});
onUnmounted(() => {
if (viewer) {
viewer.destroy();
}
});
</script>
<style scoped>
.cesium-container {
width: 100%;
height: 100vh;
}
</style>
2.2.5 方式五:React + CesiumJS
# 创建 React 项目
npm create vite@latest cesium-react-app -- --template react
cd cesium-react-app
# 安装依赖
npm install
npm install cesium resium
使用 Resium(React 封装):
import React from 'react';
import { Viewer, Entity, PointGraphics } from 'resium';
import * as Cesium from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';
// 设置访问令牌
Cesium.Ion.defaultAccessToken = 'your_access_token';
function App() {
return (
<Viewer full>
<Entity
name="北京"
position={Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100)}
>
<PointGraphics
pixelSize={10}
color={Cesium.Color.RED}
/>
</Entity>
</Viewer>
);
}
export default App;
2.3 获取 Cesium ion 访问令牌
2.3.1 注册 Cesium ion 账号
- 访问 https://cesium.com/ion/signup
- 填写注册信息
- 验证邮箱
- 登录账户
2.3.2 获取访问令牌
- 登录 Cesium ion
- 进入 Access Tokens 页面
- 创建新的令牌或使用默认令牌
- 复制令牌字符串
// 在代码中使用令牌
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
2.3.3 令牌管理最佳实践
// 方式一:环境变量(推荐)
// .env 文件
// VITE_CESIUM_TOKEN=your_access_token
// 代码中使用
Cesium.Ion.defaultAccessToken = import.meta.env.VITE_CESIUM_TOKEN;
// 方式二:配置文件
// config.js
export const cesiumConfig = {
accessToken: 'your_access_token'
};
// 使用
import { cesiumConfig } from './config.js';
Cesium.Ion.defaultAccessToken = cesiumConfig.accessToken;
2.4 第一个 CesiumJS 应用
2.4.1 完整示例代码
创建一个包含基本功能的完整示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的第一个 CesiumJS 应用</title>
<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;
}
#toolbar {
position: absolute;
top: 10px;
left: 10px;
z-index: 1000;
background: rgba(42, 42, 42, 0.8);
padding: 10px;
border-radius: 4px;
}
#toolbar button {
display: block;
margin: 5px 0;
padding: 8px 16px;
cursor: pointer;
background: #303030;
color: white;
border: 1px solid #444;
border-radius: 4px;
}
#toolbar button:hover {
background: #404040;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<div id="toolbar">
<button onclick="flyToBeijing()">飞到北京</button>
<button onclick="flyToShanghai()">飞到上海</button>
<button onclick="addPoint()">添加点</button>
<button onclick="addPolygon()">添加多边形</button>
<button onclick="clearEntities()">清除实体</button>
<button onclick="toggleTerrain()">切换地形</button>
</div>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Cesium.js"></script>
<script>
// 设置访问令牌
Cesium.Ion.defaultAccessToken = 'your_access_token';
// 创建 Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain(),
animation: true,
timeline: true,
fullscreenButton: true,
geocoder: true,
homeButton: true,
infoBox: true,
sceneModePicker: true,
selectionIndicator: true,
navigationHelpButton: true
});
// 启用深度测试
viewer.scene.globe.depthTestAgainstTerrain = true;
// 飞到北京
function flyToBeijing() {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 15000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-45),
roll: 0
},
duration: 2
});
}
// 飞到上海
function flyToShanghai() {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(121.47, 31.23, 15000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-45),
roll: 0
},
duration: 2
});
}
// 添加点
function addPoint() {
const longitude = 116.4 + (Math.random() - 0.5) * 2;
const latitude = 39.9 + (Math.random() - 0.5) * 2;
viewer.entities.add({
name: '随机点',
position: Cesium.Cartesian3.fromDegrees(longitude, latitude, 100),
point: {
pixelSize: 12,
color: Cesium.Color.fromRandom({ alpha: 1.0 }),
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
},
label: {
text: `点 (${longitude.toFixed(2)}, ${latitude.toFixed(2)})`,
font: '12px sans-serif',
fillColor: Cesium.Color.WHITE,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -15)
}
});
}
// 添加多边形
function addPolygon() {
const centerLon = 116.4 + (Math.random() - 0.5) * 2;
const centerLat = 39.9 + (Math.random() - 0.5) * 2;
const size = 0.1;
viewer.entities.add({
name: '随机多边形',
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
centerLon - size, centerLat - size,
centerLon + size, centerLat - size,
centerLon + size, centerLat + size,
centerLon - size, centerLat + size
]),
material: Cesium.Color.fromRandom({ alpha: 0.5 }),
outline: true,
outlineColor: Cesium.Color.BLACK,
height: 0,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}
});
}
// 清除所有实体
function clearEntities() {
viewer.entities.removeAll();
}
// 切换地形
let terrainEnabled = true;
function toggleTerrain() {
terrainEnabled = !terrainEnabled;
if (terrainEnabled) {
viewer.terrainProvider = Cesium.createWorldTerrain();
} else {
viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
}
}
// 初始飞到北京
flyToBeijing();
</script>
</body>
</html>
2.4.2 代码解析
1. 初始化配置:
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain(), // 全球地形
animation: true, // 动画控件
timeline: true, // 时间轴
fullscreenButton: true, // 全屏按钮
geocoder: true, // 地理编码搜索
homeButton: true, // 主页按钮
infoBox: true, // 信息框
sceneModePicker: true, // 场景模式选择器
selectionIndicator: true, // 选择指示器
navigationHelpButton: true // 导航帮助
});
2. 相机飞行:
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
orientation: {
heading: Cesium.Math.toRadians(0), // 朝向角度
pitch: Cesium.Math.toRadians(-45), // 俯仰角度
roll: 0 // 翻转角度
},
duration: 2 // 飞行时间(秒)
});
3. 添加实体:
viewer.entities.add({
name: '实体名称',
position: Cesium.Cartesian3.fromDegrees(lon, lat, height),
point: { /* 点样式 */ },
label: { /* 标签样式 */ }
});
2.5 项目结构最佳实践
2.5.1 推荐的项目结构
cesium-project/
├── public/
│ ├── index.html
│ └── assets/
│ ├── models/ # 3D 模型文件
│ ├── textures/ # 纹理贴图
│ └── data/ # 数据文件
├── src/
│ ├── main.js # 入口文件
│ ├── config/
│ │ └── cesium.config.js # Cesium 配置
│ ├── components/
│ │ ├── CesiumViewer.js # Viewer 组件
│ │ └── controls/ # 控制组件
│ ├── layers/
│ │ ├── ImageryLayers.js # 影像图层
│ │ ├── TerrainLayers.js # 地形图层
│ │ └── EntityLayers.js # 实体图层
│ ├── utils/
│ │ ├── coordinate.js # 坐标工具
│ │ └── camera.js # 相机工具
│ └── styles/
│ └── cesium.css # 自定义样式
├── package.json
├── vite.config.js
└── .env # 环境变量
2.5.2 配置文件示例
cesium.config.js:
export const cesiumConfig = {
// 访问令牌
accessToken: import.meta.env.VITE_CESIUM_TOKEN,
// 默认视图配置
defaultView: {
longitude: 116.4,
latitude: 39.9,
height: 15000
},
// Viewer 默认选项
viewerOptions: {
animation: true,
timeline: true,
fullscreenButton: true,
geocoder: true,
homeButton: true,
infoBox: true,
sceneModePicker: true,
selectionIndicator: true,
navigationHelpButton: false
},
// 地形配置
terrain: {
requestWaterMask: true,
requestVertexNormals: true
}
};
CesiumViewer.js:
import * as Cesium from 'cesium';
import { cesiumConfig } from '../config/cesium.config.js';
export class CesiumViewer {
constructor(containerId) {
this.containerId = containerId;
this.viewer = null;
this.init();
}
init() {
// 设置访问令牌
Cesium.Ion.defaultAccessToken = cesiumConfig.accessToken;
// 创建 Viewer
this.viewer = new Cesium.Viewer(this.containerId, {
...cesiumConfig.viewerOptions,
terrainProvider: Cesium.createWorldTerrain(cesiumConfig.terrain)
});
// 飞到默认位置
this.flyToDefault();
}
flyToDefault() {
const { longitude, latitude, height } = cesiumConfig.defaultView;
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
});
}
destroy() {
if (this.viewer) {
this.viewer.destroy();
this.viewer = null;
}
}
}
2.6 开发工具与调试
2.6.1 VS Code 扩展推荐
| 扩展名 | 用途 |
|---|---|
| ESLint | 代码质量检查 |
| Prettier | 代码格式化 |
| JavaScript (ES6) code snippets | 代码片段 |
| GitLens | Git 增强 |
| Live Server | 本地服务器 |
2.6.2 浏览器开发者工具
Chrome DevTools 使用技巧:
// 在控制台访问 viewer
window.viewer = viewer;
// 查看当前相机位置
console.log(viewer.camera.positionCartographic);
// 查看场景帧率
viewer.scene.debugShowFramesPerSecond = true;
// 查看 3D Tiles 调试信息
viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);
2.6.3 性能监控
// 启用帧率显示
viewer.scene.debugShowFramesPerSecond = true;
// 监控内存使用
setInterval(() => {
const memory = performance.memory;
console.log('内存使用:', {
usedJSHeapSize: (memory.usedJSHeapSize / 1024 / 1024).toFixed(2) + ' MB',
totalJSHeapSize: (memory.totalJSHeapSize / 1024 / 1024).toFixed(2) + ' MB'
});
}, 5000);
2.7 常见问题解决
2.7.1 跨域问题
// 如果遇到 CORS 问题,可以配置代理
// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'https://your-server.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
});
2.7.2 资源加载失败
// 检查静态资源路径
// 确保 Cesium 静态资源可访问
window.CESIUM_BASE_URL = '/node_modules/cesium/Build/Cesium/';
// 或者在 Vite 中使用插件自动处理
import cesium from 'vite-plugin-cesium';
2.7.3 WebGL 兼容性
// 检查 WebGL 支持
if (!Cesium.FeatureDetection.supportsWebGL2()) {
console.warn('您的浏览器不完全支持 WebGL 2.0');
}
// 降级配置
const viewer = new Cesium.Viewer('cesiumContainer', {
contextOptions: {
webgl: {
alpha: false,
depth: true,
stencil: false,
antialias: true,
premultipliedAlpha: true,
preserveDrawingBuffer: false,
powerPreference: 'high-performance'
}
}
});
2.8 本章小结
本章介绍了 CesiumJS 的环境搭建和快速开始:
- 开发环境:Node.js、npm、现代浏览器
- 项目创建方式:
- CDN 直接引入
- npm + Vite
- Vue 3 集成
- React 集成
- Cesium ion:注册账号、获取访问令牌
- 第一个应用:完整示例代码和解析
- 项目结构:推荐的目录组织
- 开发工具:VS Code 扩展、浏览器调试
在下一章中,我们将深入了解 CesiumJS 的核心架构与模块设计。
2.9 思考与练习
- 尝试使用不同方式创建 CesiumJS 项目,比较各自的优缺点。
- 修改示例代码,添加更多按钮和功能。
- 尝试在 Vue 或 React 项目中集成 CesiumJS。
- 探索 Cesium ion 平台,了解可用的数据资源。
- 使用浏览器开发者工具,观察 CesiumJS 的网络请求和性能指标。

浙公网安备 33010602011771号