本技能提供 Cesium JS 三维地球和地图可视化开发的完整指导,包括 API 参考、代码示例和实现建议。Cesium JS 是一个强大的开源 JavaScript 库,用于在 Web 浏览器中创建 3D 地球和 2D 地图。
创建 Cesium 应用的基础步骤:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cesium Application</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">
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// 设置 Cesium Ion 访问令牌
Cesium.Ion.defaultAccessToken = 'YOUR_ACCESS_TOKEN';
// 创建 Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain()
});
</script>
</body>
</html>
关键配置选项:
Cesium.Ion.defaultAccessToken - 设置访问令牌
Viewer 构造函数第二个参数可配置各种选项
CesiumWidget - 轻量级无默认控件的视图容器
Cesium 支持多种坐标系统:
| 坐标类型 | 类 | 说明 |
|---------|-----|------|
| 笛卡尔坐标2D | Cesium.Cartesian2 | 屏幕坐标 (x, y) |
| 笛卡尔坐标3D | Cesium.Cartesian3 | 世界坐标 (x, y, z) |
| 地理坐标 | Cesium.Cartographic | 经纬度坐标 (longitude, latitude, height) |
常用转换方法:
// 经纬度转笛卡尔坐标
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);
// 屏幕坐标转世界坐标
const cartesian = viewer.scene.pickPosition(windowPosition);
支持多种影像服务:
// 加载 Bing 地图(默认)
const viewer = new Cesium.Viewer('cesiumContainer');
// 加载 ArcGIS 地图服务
const arcgis = new Cesium.ArcGisMapServerImageryProvider({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
});
viewer.imageryLayers.addImageryProvider(arcgis);
// 加载 WMS 服务
const wms = new Cesium.WebMapServiceImageryProvider({
url: 'http://localhost:8080/geoserver/wms',
layers: 'layer_name'
});
// 加载自定义 XYZ 瓦片
const xyz = new Cesium.UrlTemplateImageryProvider({
url: 'http://localhost:8080/{z}/{x}/{y}.png'
});
常用影像提供商:
ArcGisMapServerImageryProvider - ArcGIS MapServer
WebMapServiceImageryProvider - WMS 服务
WebMapTileServiceImageryProvider - WMTS 服务
UrlTemplateImageryProvider - XYZ/TMS 瓦片
TileMapServiceImageryProvider - TMS 服务
SingleTileImageryProvider - 单张图片
// 加载 Cesium World Terrain
viewer.terrainProvider = await Cesium.createWorldTerrainAsync();
// 配置地形选项
const terrain = await Cesium.Terrain.fromWorldTerrain({
requestWaterMask: true, // 请求水面遮罩
requestVertexNormals: true // 请求顶点法线(用于光照)
});
// 加载自定义地形
const customTerrain = new Cesium.CesiumTerrainProvider({
url: 'http://localhost:8000/terrain'
});
// 加载 3D Tileset
const tileset = await Cesium.Cesium3DTileset.fromUrl('http://localhost:8000/tileset.json');
// 添加到场景
viewer.scene.primitives.add(tileset);
// 常用配置
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
['${Height} >= 100', 'rgba(45, 0, 75, 0.5)'],
['${Height} >= 50', 'rgba(170, 162, 204, 0.5)'],
['true', 'rgba(127, 59, 8, 0.5)']
]
}
});
// 定位到 tileset
viewer.zoomTo(tileset);
// 加载 GeoJSON
const geoJsonDataSource = await Cesium.GeoJsonDataSource.load('data.geojson', {
stroke: Cesium.Color.RED,
fill: Cesium.Color.RED.withAlpha(0.5),
strokeWidth: 3
});
viewer.dataSources.add(geoJsonDataSource);
// 加载 KML
const kmlDataSource = await Cesium.KmlDataSource.load('data.kml');
viewer.dataSources.add(kmlDataSource);
// 加载 CZML(支持动态时序)
const czmlDataSource = await Cesium.CzmlDataSource.load('data.czml');
viewer.dataSources.add(czmlDataSource);
Entity 是 Cesium 提供的高级 API,用于创建和管理可视化对象:
// 添加点
const pointEntity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0),
point: {
pixelSize: 10,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2
}
});
// 添加标签
const labelEntity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0),
label: {
text: '北京',
font: '14pt sans-serif',
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE
}
});
// 添加线
const lineEntity = viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
116.39, 39.9,
121.47, 31.23
]),
width: 3,
material: Cesium.Color.RED
}
});
// 添加面
const polygonEntity = viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
116.0, 39.5,
117.0, 39.5,
117.0, 40.0,
116.0, 40.0
]),
material: Cesium.Color.RED.withAlpha(0.5),
outline: true,
outlineColor: Cesium.Color.RED
}
});
// 添加 3D 模型
const modelEntity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0),
model: {
uri: 'model.glb',
scale: 1.0,
minimumPixelSize: 128
}
});
// 添加广告牌(图标)
const billboardEntity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0),
billboard: {
image: 'icon.png',
width: 32,
height: 32
}
});
Primitive 是底层 API,提供更高的性能和更精细的控制:
// 创建几何实例
const instance = new Cesium.GeometryInstance({
geometry: new Cesium.BoxGeometry({
vertexFormat: Cesium.VertexFormat.POSITION_AND_NORMAL,
dimensions: new Cesium.Cartesian3(100000.0, 100000.0, 100000.0)
}),
modelMatrix: Cesium.Matrix4.multiplyByTranslation(
Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(116.39, 39.9)
),
new Cesium.Cartesian3(0.0, 0.0, 50000.0),
new Cesium.Matrix4()
)
});
// 创建 Primitive
const primitive = new Cesium.Primitive({
geometryInstances: instance,
appearance: new Cesium.MaterialAppearance({
material: Cesium.Material.fromType('Color', {
color: Cesium.Color.RED
})
})
});
// 添加到场景
viewer.scene.primitives.add(primitive);
// 设置相机位置
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 1000000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-90),
roll: 0.0
}
});
// 飞行到位置
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 1000000),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-45),
roll: 0.0
},
duration: 3.0 // 飞行时间(秒)
});
// 缩放到实体
viewer.zoomTo(entity, new Cesium.HeadingPitchRange(0, -0.5, 1000));
// 相机事件
viewer.camera.moveEnd.addEventListener(function() {
console.log('Camera moved to:', viewer.camera.position);
});
// 鼠标点击事件
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(movement) {
const ray = viewer.camera.getPickRay(movement.position);
const position = viewer.scene.globe.pick(ray, viewer.scene);
if (position) {
console.log('Clicked at:', position);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 鼠标移动事件
handler.setInputAction(function(movement) {
const entity = viewer.scene.pick(movement.endPosition);
if (entity) {
viewer.scene.canvas.style.cursor = 'pointer';
} else {
viewer.scene.canvas.style.cursor = 'default';
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// 实体选择
const selectedEntity = viewer.selectedEntity;
const trackedEntity = viewer.trackedEntity; // 跟踪实体
// 下雨效果
viewer.scene.skyAtmosphere = new Cesium.SkyAtmosphere();
viewer.scene.fog = new Cesium.Fog();
viewer.scene.fog.enabled = true;
viewer.scene.fog.density = 0.001;
// 使用粒子系统创建雨雪效果
const particleSystem = new Cesium.ParticleSystem({
image: 'circle.png',
emissionRate: 100.0,
emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(100000.0, 100000.0, 100000.0)),
startScale: 1.0,
endScale: 4.0,
particleLife: 1.0,
speed: 100.0,
width: 20.0,
height: 20.0
});
viewer.scene.primitives.add(particleSystem);
// 添加泛光效果
viewer.scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createBloomStage());
// 添加景深效果
const depthOfField = Cesium.PostProcessStageLibrary.createDepthOfFieldStage();
viewer.scene.postProcessStages.add(depthOfField);
// 自定义后处理
const customStage = new Cesium.PostProcessStage({
fragmentShader: `
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
void main() {
vec4 color = texture2D(colorTexture, v_textureCoordinates);
gl_FragColor = vec4(color.rgb * 1.2, color.a);
}
`
});
viewer.scene.postProcessStages.add(customStage);
// 使用 CustomShader 实现雷达扫描
const radarMaterial = new Cesium.CustomShader({
fragmentShaderText: `
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
vec2 st = fsInput.attributes.positionMC.xy;
float angle = atan(st.y, st.x);
float time = czm_frameNumber * 0.01;
float scan = step(0.95, mod(angle + time, 6.28) / 6.28);
material.diffuse = vec3(0.0, 1.0, 0.0);
material.alpha = scan * 0.5;
}
`
});
// 使用 Viewshed 进行可视域分析
const viewshed = new Cesium.Viewshed({
viewPosition: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 100),
direction: new Cesium.Cartesian3(1, 0, 0),
horizontalAngle: Cesium.Math.toRadians(90),
verticalAngle: Cesium.Math.toRadians(60),
distance: 1000
});
viewer.scene.primitives.add(viewshed);
// 获取地形剖面
const positions = Cesium.Cartesian3.fromDegreesArrayHeights([
116.0, 39.5, 0,
117.0, 40.0, 0
]);
const terrainProfile = await Cesium.sampleTerrainMostDetailed(
viewer.terrainProvider,
positions.map(p => Cesium.Cartographic.fromCartesian(p))
);
// 创建淹没效果
const floodPolygon = viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
116.0, 39.5,
117.0, 39.5,
117.0, 40.0,
116.0, 40.0
]),
extrudedHeight: new Cesium.CallbackProperty(function() {
return floodHeight; // 动态更新水位
}, false),
material: Cesium.Color.BLUE.withAlpha(0.5)
}
});
// 设置时间范围
viewer.clock.startTime = Cesium.JulianDate.fromIso8601('2024-01-01T00:00:00Z');
viewer.clock.stopTime = Cesium.JulianDate.fromIso8601('2024-01-02T00:00:00Z');
viewer.clock.currentTime = viewer.clock.startTime;
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
viewer.clock.multiplier = 60; // 加速播放
// 创建随时间移动的实体
const movingEntity = viewer.entities.add({
position: new Cesium.SampledPositionProperty(),
model: {
uri: 'model.glb'
}
});
// 添加位置采样点
const positionProperty = movingEntity.position;
positionProperty.addSample(
Cesium.JulianDate.fromIso8601('2024-01-01T00:00:00Z'),
Cesium.Cartesian3.fromDegrees(116.0, 39.5, 0)
);
positionProperty.addSample(
Cesium.JulianDate.fromIso8601('2024-01-01T01:00:00Z'),
Cesium.Cartesian3.fromDegrees(117.0, 40.0, 0)
);
references/api_summary.md - Cesium 核心 API 摘要
技能包含了多个可直接使用的代码模板,位于 assets/templates/ 目录:
| 模板文件 | 说明 |
|---------|------|
| basic_viewer.html | 基础 HTML 模板,包含 Viewer 初始化和常用配置 |
| entity_examples.js | Entity 实体示例代码(点、线、面、标签、模型等) |
| data_loading_examples.js | 数据加载示例(影像、地形、3D Tiles、矢量数据) |
| camera_interaction_examples.js | 相机控制和交互示例(点击、绘制、测量) |
| effects_examples.js | 特效和后处理示例(粒子系统、天气、雷达扫描) |
使用这些模板的方式:
对于常见的 Cesium 开发任务,可以参考以下模板:
basic_viewer.html 模板
data_loading_examples.js
entity_examples.js
camera_interaction_examples.js
effects_examples.js
PointPrimitiveCollection 而非单个 Entity
Cesium3DTileset 的 LOD 特性加载大规模 3D 模型
viewer.entities.remove(entity)
viewer.scene.primitives.remove(primitive)
viewer.dataSources.remove(dataSource)
Cesium.Cartesian3.fromDegrees() 而非手动计算
Cesium.Math.toRadians() 和 Cesium.Math.toDegrees() 进行角度转换
try-catch 包装异步加载代码
Cesium.defined() 判断对象是否存在
fromUrl 方法提供错误处理回调
// 启用 Cesium 调试信息
Cesium.Cesium3DTileset.debugShowBoundingVolumes = true;
Cesium.Cesium3DTileset.debugShowContentBoundingVolumes = true;
// 使用 Cesium Inspector
viewer.extend(Cesium.viewerCesiumInspectorMixin);
// 性能监控
console.log('FPS:', viewer.scene.frameState.fps);
console.log('Primitives count:', viewer.scene.primitives.length);
references/api_summary.md
共 1 个版本