整体效果如下:


对于cesium的一些初始工作,可在前几篇博客中自行参考,本文不做过多阐述;
点、线、模型(及运动轨道)的添加
在cesium官网文档cesium.com/learn/cesiu...中可看到一些相关属性



这里我们只取最常用的几个:
点的添加:
less
viewer.entities.add({
name: '添加点',
position: Cesium.Cartesian3.fromDegrees(lng, lat, height), //经、纬、高度
point: {
color: new Cesium.Color(0, 0, 0, 1.0), // 颜色
pixelSize: 10, // 大小
outlineColor: Cesium.Color.RED, // 轮廓颜色
outlineWidth: 5 //轮廓宽度
}
})
线的添加:
php
//起始点
const startPosition = Cesium.Cartesian3.fromDegrees(lng, lat, height);
//结束点
const endPosition = Cesium.Cartesian3.fromDegrees(lng, lat, height);
viewer.entities.add({
name: '添加线',
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([startPosition, endPosition]),
width: 2,
material: Cesium.Color.RED,
}
})
模型的添加:
php
shipEntity.value = viewer.entities.add({
id: "shipEntity",
name: "shipEntity",
position: Cesium.Cartesian3.fromDegrees(122.35782164573101, 34.12, 100),
model: {
uri: '/data/model/hwj.gltf', //模型相对路径 放在public目录下
minimumPixelSize: 100,
maximumScale: 20000,
},
properties: { //属性存放
name: "test-name",
description: "test-desc"
}
})
shipEntity2.value = viewer.entities.add({
id: "shipEntity2",
name: "shipEntity2",
position: Cesium.Cartesian3.fromDegrees(122.35782164573101, 34.9, 100),
model: {
uri: '/data/model/hm.gltf', //模型相对路径 放在public目录下
minimumPixelSize: 100,
maximumScale: 20000,
},
properties: { //属性存放
name: "test-name",
description: "test-desc"
}
})
飞行路线及飞行模型添加
ini
const createAirplane = () => {
if (!window.viewer || airplaneEntity.value) return;
// 初始化时间
startTime.value = Cesium.JulianDate.fromDate(new Date());
stopTime.value = Cesium.JulianDate.addSeconds(startTime.value, 360, new Cesium.JulianDate());
// 设置时钟
window.viewer.clock.startTime = startTime.value.clone();
window.viewer.clock.currentTime = startTime.value.clone();
window.viewer.clock.stopTime = stopTime.value.clone();
window.viewer.clock.multiplier = 5;
window.viewer.timeline.zoomTo(startTime.value, stopTime.value);
window.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
// 计算飞行路线
const property = computeFlyRoute();
const orientation = new Cesium.VelocityOrientationProperty(property);
// 设置视角偏移
const viewFrom = new Cesium.Cartesian3();
viewFrom.z = 1466.61814287398;
viewFrom.x = -3306.272590514738;
viewFrom.y = 135.03403439279646;
// 创建飞机实体
airplaneEntity.value = window.viewer.entities.add({
name: 'airplane',
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: startTime.value,
stop: stopTime.value
})
]),
position: property,
orientation: orientation,
viewFrom: viewFrom,
model: {
uri: '/data/model/feiji.glb',
minimumPixelSize: 100,
maximumScale: 2000,
},
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.GREEN.withAlpha(1),
}),
width: 9,
},
});
}
测试文件数据:
这里创建一个json文件(包含点和线)
测试数据如下:

点线整合代码:
ini
/**
* 创建边的数据源(提取的独立函数)
* @param {Object} viewer - Cesium 实例
* @param {Array} nodes - 节点数据
* @param {Array} edges - 边数据
* @param {String} dataSourceName - 数据源名称
* @param {Boolean} clampToGround - 是否贴合地面
* @param {String} color - 线条颜色
*/
const createEdgesDataSource = function (viewer, nodes = [], edges = [], dataSourceName = 'edgesDataSource', clampToGround = true, color = null) {
// 查找是否已存在同名的数据源
let dataSource = viewer.dataSources.getByName(dataSourceName);
if (dataSource.length === 0) {
// 创建新的数据源
dataSource = new Cesium.CustomDataSource(dataSourceName);
viewer.dataSources.add(dataSource);
} else {
dataSource = dataSource[0];
}
// 清空现有实体
dataSource.entities.removeAll();
// 创建边(连接线)- 使用优化后的逻辑
if (edges && edges.length > 0) {
edges.forEach((item, index) => {
const lineArr = [];
// 查找源节点和目标节点的坐标
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
const hasCoordinates = (node.hasOwnProperty('longitude') && node.hasOwnProperty('latitude')) ||
(node.hasOwnProperty('经度') && node.hasOwnProperty('纬度'));
if (hasCoordinates) {
if (item.source == node.id) {
const lng = node['经度'] !== undefined ? node['经度'] : node.longitude;
const lat = node['纬度'] !== undefined ? node['纬度'] : node.latitude;
const height = node['高度'] !== undefined ? node['高度'] : (node.height || 0);
lineArr.push(lng || 0, lat || 0, height || 0);
}
if (item.target == node.id) {
const lng = node['经度'] !== undefined ? node['经度'] : node.longitude;
const lat = node['纬度'] !== undefined ? node['纬度'] : node.latitude;
const height = node['高度'] !== undefined ? node['高度'] : (node.height || 0);
lineArr.push(lng || 0, lat || 0, height || 0);
}
}
}
// 如果成功获取了两个点的坐标,创建连线
if (lineArr.length === 6) { // 两个点,每个点有3个坐标值
const startPosition = Cesium.Cartesian3.fromDegrees(lineArr[0], lineArr[1], lineArr[2]);
const endPosition = Cesium.Cartesian3.fromDegrees(lineArr[3], lineArr[4], lineArr[5]);
let polylineColor = Cesium.Color.YELLOW;
if (color) {
polylineColor = Cesium.Color.fromCssColorString(color);
} else if (item.color) {
polylineColor = Cesium.Color.fromCssColorString(item.color);
}
dataSource.entities.add({
id: `edge_${item.source}_${item.target}_${index}`,
name: item.name || '连接线',
polyline: {
positions: [startPosition, endPosition],
width: item.width || 7,
material: new Cesium.PolylineArrowMaterialProperty(polylineColor),
clampToGround: item.clampToGround !== undefined ? item.clampToGround : clampToGround,
arcType: Cesium.ArcType.GEODESIC
}
});
} else {
console.warn(`无法创建边: 节点 ${item.source} 或 ${item.target} 的坐标不完整`);
}
});
}
return dataSource;
};
/**
* Cesium 加载点的方法(改进版,贴合地球表面)
* viewer: cesium实例
* array: 节点数据需要id,经纬度
* dataSourceName: 数据源名称,用于统一管理
* edges: 边数据,包含连接的节点id
* clampToGround: 是否贴合地面,默认为true
*/
const createNodesDataSource = function (viewer, nodes = [], height = 0, dataSourceName = 'nodesDataSource', clampToGround = true) {
// 查找是否已存在同名的数据源
let dataSource = viewer.dataSources.getByName(dataSourceName);
if (dataSource.length === 0) {
// 创建新的数据源
dataSource = new Cesium.CustomDataSource(dataSourceName);
viewer.dataSources.add(dataSource);
} else {
dataSource = dataSource[0];
}
// 清空现有实体
dataSource.entities.removeAll();
// 存储节点位置,用于边的连接
const nodePositions = {};
// 创建节点
nodes.forEach((item) => {
// 使用地形高度采样获取准确的地面高度
const longitude = item.经度 !== undefined ? item.经度 : item.longitude;
const latitude = item.纬度 !== undefined ? item.纬度 : item.latitude;
const cartographicPosition = Cesium.Cartographic.fromDegrees(longitude, latitude);
const sampledHeight = viewer.scene.globe.getHeight(cartographicPosition) || 0;
const finalHeight = clampToGround ? sampledHeight + (height || 0) : height;
const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, finalHeight);
nodePositions[item.id] = position;
dataSource.entities.add({
id: item.id,
name: item.name,
position: position,
point: {
pixelSize: 20,
color: new Cesium.Color(1, 1, 0, 1),
heightReference: clampToGround ? Cesium.HeightReference.CLAMP_TO_GROUND : Cesium.HeightReference.NONE
},
label: {
text: item.name || '暂无名称',
font: '10px',
fillColor: Cesium.Color.WHITE,
backgroundColor: Cesium.Color.SKYBLUE,
showBackground: false,
outlineWidth: 2,
pixelOffset: new Cesium.Cartesian2(1, -34),
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
heightReference: clampToGround ? Cesium.HeightReference.CLAMP_TO_GROUND : Cesium.HeightReference.NONE
},
});
});
return dataSource;
};
效果如下:


指北针添加
可参考www.npmjs.com/package/ces...


css
npm install cesium-navigation-es6 --save
ini
import { Viewer,Rectangle} from "cesium";
import 'cesium/Build/Cesium/Widgets/widgets.css';
import CesiumNavigation from "cesium-navigation-es6";
const viewer = new Viewer("cesiumContainer",{
animation:false,
timeline:false
});
const options = {};
// 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和 Cesium.Rectangle.
// options.defaultResetView = Rectangle.fromDegrees(80, 22, 130, 50)
options.defaultResetView = new Cartographic(CesiumMath.toRadians(111.50623801848565), CesiumMath.toRadians(2.8997206760441205), 8213979.400955964)
//相机方向
options.orientation = {
heading: CesiumMath.toRadians(350.94452087411315),
pitch: CesiumMath.toRadians(-66.6402342251215),
roll: CesiumMath.toRadians(360)
}
//相机延时
options.duration = 4//默认为3s
// 用于启用或禁用罗盘。true是启用罗盘,false是禁用罗盘。默认值为true。如果将选项设置为false,则罗盘将不会添加到地图中。
options.enableCompass= true;
// 用于启用或禁用缩放控件。true是启用,false是禁用。默认值为true。如果将选项设置为false,则缩放控件将不会添加到地图中。
options.enableZoomControls= true;
// 用于启用或禁用距离图例。true是启用,false是禁用。默认值为true。如果将选项设置为false,距离图例将不会添加到地图中。
options.enableDistanceLegend= true;
// 用于启用或禁用指南针外环。true是启用,false是禁用。默认值为true。如果将选项设置为false,则该环将可见但无效。
options.enableCompassOuterRing= true;
//修改重置视图的tooltip
options.resetTooltip = "重置视图";
//修改放大按钮的tooltip
options.zoomInTooltip = "放大";
//修改缩小按钮的tooltip
options.zoomOutTooltip = "缩小";
//如需自定义罗盘控件,请看下面的自定义罗盘控件
new CesiumNavigation(viewer, options);
CZML文件加载

javascript
const entitiesCzmlInit = () => {
//测试文件路径
let czmlFiles = [`1`, `2`, `3`, `4`,`5`,`6`,'7',`8`, `9`, `10`, `11`,`12`,`13`,'14',`15`, `16`, `17`, `18`,`19`,`20`,'21',`22`, `23`, `24`, `25`,`26`];
// 测试
czmlFiles.forEach((file) => {
viewer.dataSources.add(Cesium.CzmlDataSource.load(`/czmlFile/${file}.czml`));
});
};
onMounted(async () => {
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyYTNkYjhhNC04NDQ4LTRiMDItYTg4OS03YWU3ZWVjNjBiNTgiLCJpZCI6ODYyMDMsImlhdCI6MTY4MTM3ODA5M30.M1tBPd6f5Of1l2ElUqecFjv9GcZ-Ntcwm2iain-fvkk";
const viewer = new Viewer("cesiumContainer", {
infoBox: false,
animation: true, // 是否显示动画控件
homeButton: false, // 是否显示home键
geocoder: false, // 是否显示地名查找控件
baseLayerPicker: false, // 是否显示图层选择控件
timeline: true, // 是否显示时间线控件
fullscreenButton: false, // 是否全屏显示
infoBox: false, // 是否显示点击要素之后显示的信息
sceneModePicker: false, // 是否显示投影方式控件 三维/二维
navigationInstructionsInitiallyVisible: false,
navigationHelpButton: false, // 是否显示帮助信息控件
orderIndependentTranslucency: false,
shouldAnimate: true,
scene3DOnly: false, // 每个几何实例将只能以3D渲染以节省GPU内存
selectionIndicator: false, // 取消点击有绿框
// imageryProvider: false, // 不提供地图
baseLayerPicker: true, //是否显示图层选择控件
sceneMode: Cesium.SceneMode.SCENE3D, // 设置场景为3D模式
});
// 设置开始时间
viewer.clock.startTime = Cesium.JulianDate.fromDate(
new Date(2024, 10, 10, 8, 30)
); // 设置为2024年10月10日 08:30
// 控制播放状态
// viewer.clock.shouldAnimate = true; // 启用动画(时间流动)
//设置版权等信息不显示
viewer._cesiumWidget._creditContainer.style.display = "none";
cesiumViewer.value = viewer;
window.viewer = viewer;
entitiesCzmlInit();
});
声明:
本数据的发布仅为技术演示和学习目的,不对使用本数据引发的任何误用或误解负责。