cesium点、线、面、模型
整体效果如下:


对于cesium的一些初始工作,可在前几篇博客中自行参考,本文不做过多阐述;
话不多说,直接进入正题;
点和线的添加
在cesium官网文档https://cesium.com/learn/cesiumjs/ref-doc/Entity.html中可看到一些相关属性



这里我们只取最常用的几个:
点击添加:
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 //轮廓宽度}
})
线的添加:
//起始点
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,}
})
模型的添加:
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"}})
飞行路线及飞行模型添加
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文件(包含点和线)
测试数据如下:

点线整合代码:
/*** 创建边的数据源(提取的独立函数)* @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;
};
效果如下:

