第11章 - 数据格式与数据源
第11章:数据格式与数据源
11.1 数据源概述
CesiumJS 支持多种数据格式,通过 DataSource 统一管理:
┌─────────────────────────────────────────────────────────────────┐
│ DataSource 架构 │
├─────────────────────────────────────────────────────────────────┤
│ DataSourceCollection │
│ └── DataSource │
│ ├── entities (EntityCollection) │
│ ├── clock (时钟配置) │
│ └── changedEvent / errorEvent / loadingEvent │
│ │
│ 内置数据源: │
│ ├── GeoJsonDataSource - GeoJSON/TopoJSON │
│ ├── KmlDataSource - KML/KMZ │
│ ├── CzmlDataSource - CZML │
│ └── GpxDataSource - GPX │
└─────────────────────────────────────────────────────────────────┘
11.2 GeoJSON 数据
11.2.1 加载 GeoJSON
// 基本加载
const dataSource = await Cesium.GeoJsonDataSource.load('data.geojson');
viewer.dataSources.add(dataSource);
viewer.zoomTo(dataSource);
// 带样式加载
const styledDataSource = await Cesium.GeoJsonDataSource.load('data.geojson', {
stroke: Cesium.Color.RED,
fill: Cesium.Color.RED.withAlpha(0.5),
strokeWidth: 3,
markerSymbol: '?',
markerColor: Cesium.Color.BLUE,
markerSize: 48,
clampToGround: true
});
viewer.dataSources.add(styledDataSource);
// 加载 GeoJSON 对象
const geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [116.4, 39.9]
},
properties: { name: '北京' }
}, {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[[116, 39], [117, 39], [117, 40], [116, 40], [116, 39]]]
},
properties: { name: '区域' }
}]
};
const objectDataSource = await Cesium.GeoJsonDataSource.load(geojson);
viewer.dataSources.add(objectDataSource);
11.2.2 自定义 GeoJSON 样式
// 加载后自定义样式
const dataSource = await Cesium.GeoJsonDataSource.load('data.geojson');
viewer.dataSources.add(dataSource);
// 遍历实体设置样式
const entities = dataSource.entities.values;
entities.forEach(entity => {
// 点样式
if (entity.point) {
entity.point.pixelSize = 12;
entity.point.color = Cesium.Color.RED;
}
// 多边形样式
if (entity.polygon) {
const height = entity.properties.height?.getValue() || 0;
if (height > 100) {
entity.polygon.material = Cesium.Color.RED.withAlpha(0.6);
} else if (height > 50) {
entity.polygon.material = Cesium.Color.ORANGE.withAlpha(0.6);
} else {
entity.polygon.material = Cesium.Color.YELLOW.withAlpha(0.6);
}
entity.polygon.outline = true;
entity.polygon.outlineColor = Cesium.Color.BLACK;
}
// 折线样式
if (entity.polyline) {
entity.polyline.material = Cesium.Color.BLUE;
entity.polyline.width = 3;
}
});
11.3 CZML 数据
11.3.1 CZML 基本结构
// CZML 文档结构
const czml = [
// 文档声明(必须是第一个元素)
{
id: 'document',
name: 'CZML 示例',
version: '1.0',
clock: {
interval: '2024-01-01T00:00:00Z/2024-01-02T00:00:00Z',
currentTime: '2024-01-01T00:00:00Z',
multiplier: 60
}
},
// 实体定义
{
id: 'point1',
name: '点对象',
position: {
cartographicDegrees: [116.4, 39.9, 100]
},
point: {
pixelSize: 10,
color: { rgba: [255, 0, 0, 255] }
}
}
];
// 加载 CZML
const dataSource = await Cesium.CzmlDataSource.load(czml);
viewer.dataSources.add(dataSource);
11.3.2 CZML 动态轨迹
// 动态轨迹 CZML
const trajectoryDoc = [
{
id: 'document',
name: '飞行轨迹',
version: '1.0',
clock: {
interval: '2024-01-01T00:00:00Z/2024-01-01T01:00:00Z',
currentTime: '2024-01-01T00:00:00Z',
multiplier: 60,
range: 'LOOP_STOP',
step: 'SYSTEM_CLOCK_MULTIPLIER'
}
},
{
id: 'aircraft',
name: '飞机',
availability: '2024-01-01T00:00:00Z/2024-01-01T01:00:00Z',
position: {
epoch: '2024-01-01T00:00:00Z',
cartographicDegrees: [
0, 116.0, 39.0, 10000,
1800, 117.0, 39.5, 12000,
3600, 118.0, 40.0, 10000
],
interpolationAlgorithm: 'LAGRANGE',
interpolationDegree: 5
},
orientation: {
velocityReference: '#position'
},
model: {
gltf: 'aircraft.glb',
scale: 100,
minimumPixelSize: 64
},
path: {
material: {
solidColor: { color: { rgba: [255, 255, 0, 255] } }
},
width: 2,
leadTime: 600,
trailTime: 3600,
resolution: 120
}
}
];
const trajectoryDataSource = await Cesium.CzmlDataSource.load(trajectoryDoc);
viewer.dataSources.add(trajectoryDataSource);
viewer.trackedEntity = trajectoryDataSource.entities.getById('aircraft');
11.4 KML 数据
11.4.1 加载 KML/KMZ
// 加载 KML
const kmlDataSource = await Cesium.KmlDataSource.load('data.kml', {
camera: viewer.camera,
canvas: viewer.canvas,
clampToGround: true
});
viewer.dataSources.add(kmlDataSource);
viewer.zoomTo(kmlDataSource);
// 加载 KMZ
const kmzDataSource = await Cesium.KmlDataSource.load('data.kmz', {
camera: viewer.camera,
canvas: viewer.canvas
});
viewer.dataSources.add(kmzDataSource);
11.5 glTF 模型
11.5.1 加载 glTF/GLB
// 使用 Entity API
const modelEntity = viewer.entities.add({
name: '3D模型',
position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 0),
orientation: Cesium.Transforms.headingPitchRollQuaternion(
Cesium.Cartesian3.fromDegrees(116.4, 39.9, 0),
new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(90), 0, 0)
),
model: {
uri: 'model.glb',
scale: 1.0,
minimumPixelSize: 64,
maximumScale: 20000,
silhouetteColor: Cesium.Color.RED,
silhouetteSize: 2.0
}
});
// 使用 Primitive API(更高性能)
const modelPrimitive = await Cesium.Model.fromGltfAsync({
url: 'model.glb',
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(116.4, 39.9, 0)
),
scale: 1.0,
minimumPixelSize: 64
});
viewer.scene.primitives.add(modelPrimitive);
11.6 DataSource 管理
11.6.1 DataSourceCollection 操作
const dataSources = viewer.dataSources;
// 添加
const ds = await Cesium.GeoJsonDataSource.load('data.geojson');
dataSources.add(ds);
// 获取
const count = dataSources.length;
const dsAt = dataSources.get(0);
const contains = dataSources.contains(ds);
const indexOf = dataSources.indexOf(ds);
const byName = dataSources.getByName('数据源名称');
// 移除
dataSources.remove(ds);
dataSources.remove(ds, true); // 移除并销毁
dataSources.removeAll();
// 调整顺序
dataSources.raise(ds);
dataSources.lower(ds);
dataSources.raiseToTop(ds);
dataSources.lowerToBottom(ds);
// 事件
dataSources.dataSourceAdded.addEventListener((collection, dataSource) => {
console.log('数据源添加:', dataSource.name);
});
dataSources.dataSourceRemoved.addEventListener((collection, dataSource) => {
console.log('数据源移除:', dataSource.name);
});
11.6.2 数据源管理器
class DataSourceManager {
constructor(viewer) {
this.viewer = viewer;
this.sources = new Map();
}
async addGeoJson(name, url, options = {}) {
const ds = await Cesium.GeoJsonDataSource.load(url, options);
ds.name = name;
this.viewer.dataSources.add(ds);
this.sources.set(name, { type: 'geojson', dataSource: ds });
return ds;
}
async addCzml(name, url) {
const ds = await Cesium.CzmlDataSource.load(url);
ds.name = name;
this.viewer.dataSources.add(ds);
this.sources.set(name, { type: 'czml', dataSource: ds });
return ds;
}
async addKml(name, url) {
const ds = await Cesium.KmlDataSource.load(url, {
camera: this.viewer.camera,
canvas: this.viewer.canvas
});
ds.name = name;
this.viewer.dataSources.add(ds);
this.sources.set(name, { type: 'kml', dataSource: ds });
return ds;
}
get(name) {
const info = this.sources.get(name);
return info ? info.dataSource : null;
}
show(name, visible) {
const ds = this.get(name);
if (ds) ds.show = visible;
}
remove(name) {
const info = this.sources.get(name);
if (info) {
this.viewer.dataSources.remove(info.dataSource, true);
this.sources.delete(name);
return true;
}
return false;
}
zoomTo(name) {
const ds = this.get(name);
if (ds) this.viewer.zoomTo(ds);
}
clear() {
this.sources.forEach((info, name) => {
this.viewer.dataSources.remove(info.dataSource, true);
});
this.sources.clear();
}
}
// 使用
const dsManager = new DataSourceManager(viewer);
await dsManager.addGeoJson('cities', 'cities.geojson');
await dsManager.addCzml('flights', 'flights.czml');
dsManager.zoomTo('cities');
dsManager.show('flights', false);
11.7 本章小结
本章介绍了数据格式与数据源:
- GeoJSON:加载、样式自定义
- CZML:动态轨迹、时间序列
- KML:Google Earth 格式支持
- glTF:3D 模型加载
- DataSource 管理:添加、移除、排序
在下一章中,我们将详细介绍空间分析与测量。
11.8 思考与练习
- 加载并展示 GeoJSON 行政区划数据。
- 创建 CZML 动态飞行轨迹。
- 实现数据源的动态切换功能。
- 开发 GeoJSON 数据导入工具。
- 实现基于属性的 GeoJSON 专题图。

浙公网安备 33010602011771号