第18章 - 实战案例与项目应用
第18章:实战案例与项目应用
18.1 智慧城市可视化
18.1.1 项目架构
// 智慧城市应用框架
class SmartCityApp {
constructor(containerId) {
this.viewer = null;
this.layerManager = null;
this.toolManager = null;
this.init(containerId);
}
async init(containerId) {
// 初始化 Viewer
Cesium.Ion.defaultAccessToken = 'your_token';
this.viewer = new Cesium.Viewer(containerId, {
terrainProvider: Cesium.createWorldTerrain(),
animation: false,
timeline: false,
baseLayerPicker: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
navigationHelpButton: false,
infoBox: true,
selectionIndicator: true
});
// 初始化管理器
this.layerManager = new LayerManager(this.viewer);
this.toolManager = new ToolManager(this.viewer);
// 加载城市数据
await this.loadCityData();
// 初始化交互
this.initInteraction();
}
async loadCityData() {
// 加载建筑 3D Tiles
const buildings = await this.layerManager.add3DTiles('buildings',
'https://city-server/buildings/tileset.json',
{
style: new Cesium.Cesium3DTileStyle({
color: {
conditions: [
['${height} > 100', 'color("#FF4444")'],
['${height} > 50', 'color("#FF8844")'],
['true', 'color("#AAAAAA")']
]
}
})
}
);
// 加载道路数据
await this.layerManager.addGeoJson('roads', 'data/roads.geojson', {
stroke: Cesium.Color.WHITE,
strokeWidth: 2,
clampToGround: true
});
// 加载 POI 数据
await this.layerManager.addGeoJson('poi', 'data/poi.geojson');
}
initInteraction() {
// 点击建筑显示信息
const handler = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas);
handler.setInputAction((click) => {
const picked = this.viewer.scene.pick(click.position);
if (Cesium.defined(picked) && picked.primitive instanceof Cesium.Cesium3DTileset) {
this.showBuildingInfo(picked);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
showBuildingInfo(picked) {
if (picked.getPropertyIds) {
const info = {};
picked.getPropertyIds().forEach(id => {
info[id] = picked.getProperty(id);
});
console.log('建筑信息:', info);
// 显示信息面板
this.showInfoPanel(info);
}
}
showInfoPanel(info) {
let panel = document.getElementById('info-panel');
if (!panel) {
panel = document.createElement('div');
panel.id = 'info-panel';
panel.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
background: rgba(0,0,0,0.8);
color: white;
padding: 15px;
border-radius: 5px;
z-index: 1000;
`;
this.viewer.container.appendChild(panel);
}
panel.innerHTML = `
<h3>建筑信息</h3>
${Object.entries(info).map(([k, v]) => `<p>${k}: ${v}</p>`).join('')}
`;
}
flyTo(lon, lat, height = 1000) {
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(lon, lat, height),
orientation: {
heading: 0,
pitch: Cesium.Math.toRadians(-45),
roll: 0
}
});
}
}
// 使用
const app = new SmartCityApp('cesiumContainer');
app.flyTo(116.4, 39.9, 5000);
18.2 飞行轨迹追踪
18.2.1 航班追踪系统
class FlightTracker {
constructor(viewer) {
this.viewer = viewer;
this.flights = new Map();
this.dataSource = new Cesium.CustomDataSource('flights');
viewer.dataSources.add(this.dataSource);
}
addFlight(flightData) {
const { id, positions, model } = flightData;
// 创建位置属性
const positionProperty = new Cesium.SampledPositionProperty();
positions.forEach(p => {
positionProperty.addSample(
Cesium.JulianDate.fromIso8601(p.time),
Cesium.Cartesian3.fromDegrees(p.lon, p.lat, p.altitude)
);
});
positionProperty.setInterpolationOptions({
interpolationDegree: 5,
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
});
// 创建实体
const entity = this.dataSource.entities.add({
id: id,
name: flightData.name || id,
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: Cesium.JulianDate.fromIso8601(positions[0].time),
stop: Cesium.JulianDate.fromIso8601(positions[positions.length - 1].time)
})
]),
position: positionProperty,
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
model: {
uri: model || 'models/aircraft.glb',
scale: 1.0,
minimumPixelSize: 64
},
path: {
material: Cesium.Color.YELLOW,
width: 2,
leadTime: 0,
trailTime: 3600
},
label: {
text: flightData.name || id,
font: '14px sans-serif',
fillColor: Cesium.Color.WHITE,
showBackground: true,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -40)
}
});
this.flights.set(id, entity);
return entity;
}
trackFlight(id) {
const entity = this.flights.get(id);
if (entity) {
this.viewer.trackedEntity = entity;
}
}
removeFlight(id) {
const entity = this.flights.get(id);
if (entity) {
this.dataSource.entities.remove(entity);
this.flights.delete(id);
}
}
updateFlightPosition(id, position) {
const entity = this.flights.get(id);
if (entity && entity.position) {
entity.position.addSample(
Cesium.JulianDate.now(),
Cesium.Cartesian3.fromDegrees(position.lon, position.lat, position.altitude)
);
}
}
}
// 使用示例
const tracker = new FlightTracker(viewer);
tracker.addFlight({
id: 'CA123',
name: '国航 CA123',
positions: [
{ time: '2024-01-01T00:00:00Z', lon: 116.4, lat: 39.9, altitude: 10000 },
{ time: '2024-01-01T01:00:00Z', lon: 118.0, lat: 38.0, altitude: 11000 },
{ time: '2024-01-01T02:00:00Z', lon: 121.5, lat: 31.2, altitude: 10000 }
]
});
tracker.trackFlight('CA123');
18.3 地质灾害预警
18.3.1 灾害监测系统
class DisasterMonitoringSystem {
constructor(viewer) {
this.viewer = viewer;
this.monitorPoints = [];
this.warningAreas = [];
}
// 添加监测点
addMonitorPoint(data) {
const entity = this.viewer.entities.add({
name: data.name,
position: Cesium.Cartesian3.fromDegrees(data.lon, data.lat, data.height || 0),
point: {
pixelSize: 12,
color: this.getStatusColor(data.status),
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
},
label: {
text: data.name,
font: '12px sans-serif',
fillColor: Cesium.Color.WHITE,
showBackground: true,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -15)
},
properties: data
});
this.monitorPoints.push(entity);
return entity;
}
getStatusColor(status) {
switch (status) {
case 'danger': return Cesium.Color.RED;
case 'warning': return Cesium.Color.ORANGE;
case 'attention': return Cesium.Color.YELLOW;
default: return Cesium.Color.GREEN;
}
}
// 添加预警区域
addWarningArea(data) {
const entity = this.viewer.entities.add({
name: data.name,
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray(data.coordinates.flat()),
material: this.getWarningMaterial(data.level),
outline: true,
outlineColor: Cesium.Color.RED,
outlineWidth: 2,
classificationType: Cesium.ClassificationType.TERRAIN
},
properties: data
});
this.warningAreas.push(entity);
return entity;
}
getWarningMaterial(level) {
switch (level) {
case 4: return Cesium.Color.RED.withAlpha(0.5); // 一级
case 3: return Cesium.Color.ORANGE.withAlpha(0.5); // 二级
case 2: return Cesium.Color.YELLOW.withAlpha(0.5); // 三级
default: return Cesium.Color.BLUE.withAlpha(0.3); // 四级
}
}
// 更新监测点状态
updatePointStatus(name, newStatus) {
const entity = this.monitorPoints.find(e => e.name === name);
if (entity) {
entity.point.color = this.getStatusColor(newStatus);
entity.properties.status = newStatus;
// 触发预警
if (newStatus === 'danger') {
this.triggerWarning(entity);
}
}
}
// 触发预警
triggerWarning(entity) {
// 闪烁效果
let visible = true;
const interval = setInterval(() => {
entity.show = visible;
visible = !visible;
}, 500);
// 5秒后停止闪烁
setTimeout(() => {
clearInterval(interval);
entity.show = true;
}, 5000);
// 飞到预警点
this.viewer.flyTo(entity);
}
}
// 使用
const disasterSystem = new DisasterMonitoringSystem(viewer);
// 添加监测点
disasterSystem.addMonitorPoint({
name: '滑坡监测点1',
lon: 104.5,
lat: 31.2,
status: 'normal'
});
// 添加预警区域
disasterSystem.addWarningArea({
name: '高风险区域A',
level: 4,
coordinates: [
104.4, 31.1, 104.6, 31.1, 104.6, 31.3, 104.4, 31.3
]
});
// 模拟状态更新
setTimeout(() => {
disasterSystem.updatePointStatus('滑坡监测点1', 'danger');
}, 3000);
18.4 项目部署
18.4.1 构建优化
// vite.config.js
import { defineConfig } from 'vite';
import cesium from 'vite-plugin-cesium';
export default defineConfig({
plugins: [cesium()],
build: {
rollupOptions: {
output: {
manualChunks: {
cesium: ['cesium']
}
}
},
chunkSizeWarningLimit: 2000
},
server: {
host: true,
port: 3000
}
});
18.4.2 部署配置
# nginx 配置示例
server {
listen 80;
server_name your-domain.com;
root /var/www/cesium-app;
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# 3D Tiles 缓存
location /tiles/ {
expires 7d;
add_header Cache-Control "public";
}
# SPA 路由
location / {
try_files $uri $uri/ /index.html;
}
# Gzip 压缩
gzip on;
gzip_types application/javascript text/css application/json;
}
18.5 本章小结
本章通过实战案例展示了 CesiumJS 的综合应用:
- 智慧城市:建筑可视化、信息展示
- 飞行追踪:轨迹动画、实时更新
- 灾害预警:监测点、预警区域
- 项目部署:构建优化、服务器配置
18.6 教程总结
通过本教程的学习,您已经掌握了:
- CesiumJS 核心概念和架构
- Viewer、Camera、Entity、Primitive
- 影像、地形、3D Tiles 数据处理
- 交互事件与绘图工具
- 动画与时间系统
- 样式效果与粒子系统
- 性能优化与最佳实践
- 实际项目应用
继续深入学习建议:
- 阅读 CesiumJS 源码
- 参与社区讨论
- 尝试更复杂的项目
- 关注官方更新
祝您在三维地理信息可视化领域取得更大成就!

浙公网安备 33010602011771号