文章目录
cesium 前置说明(友情提示,关注重点代码,其他影响复现的都可以删除或者替换数值解决)
- 这里面用到了cesium的模型加载、图片加载、着色器、实时改变模型状态、模型删除等知识点,这需要你自己去观摩
- 下述会包含所有相关代码,他们的联系其实在代码中能看到(比如飞机操作类会调用时间类等),代码相对复杂,需要有一定js编码经验及vue编程经验的人去理解查看。
- 已经加载了cesium基础框架
- 没有加载好的,直接看cesium官网示例:https://sandcastle.cesium.com/
- 准备好数据基础参数(我自定义了与飞机相关的json数据,放在文末位置了,可以直接使用)
展示整体场景的结构
- 场景展示:
-
关联通讯飞机及飞机展示通讯监测范围
-
运输机释放无人机,无人机与运输机协同飞行
-
雷达开启及发射导弹
-
飞机发射干扰波
-
飞机绕环飞行
- 定义飞机操作类、飞机基础类、雷达操作类、时间类、场景类、场景绑定类、主要程序入口类
- 主要程序入口类
//加载战场
battleFieldLoading(viewer);
//加载多个交互场景
battleFieldCommunication(viewer);
// 以下定义均是引用其他类
var tt = new TimeTool(2000, 100);
radarStation.loadTimeModule(tt);
planes.loadTimeModule(tt);
//战场加载
export function battleFieldLoading(viewer: Cesium.Viewer) {
//定义全局时间
tt.setMoudule(viewer);
// 加载多个雷达:6000为扫描半径 米
radarStation.addRadarByJson(viewer, Cesium.Color.RED, 6000, [0, 1, 2, 3, 4, 5, 7, 8]);
// 加载诱饵机
planes.setLinePositions("red", "DECOYS")
planes.loadPlaneByTrajectory(viewer, "red", "DECOYS", false);
// 加载多个电子站专用飞机EW
planes.setLinePositions("red", "AIREW");
planes.loadPlaneByTrajectory(viewer, "red", "AIREW", false);
// 加载F135飞机
planes.setLinePositions("red", "F35")
planes.loadPlaneByTrajectory(viewer, "red", "F35", false);
// 加载货运机
planes.setLinePositions("red", "KINETICS")
planes.loadPlaneByTrajectory(viewer, "red", "KINETICS", false);
planes.showPlaneCommunication(viewer, "red", "KINETICS");
planes.showNonPlaneCommunication(viewer, "red", "KINETICS", "F35", [1, 3], [7, 8]);
planes.loadPlaneSector(viewer, "red", "KINETICS", [0, 1, 2, 3]);
//加载蓝方-ISR飞机
planes.setCirclePositions([116.10417676302052, 22.949787916971527, 1000], 2000, "ISRS", viewer);
planes.loadPlaneByTrajectory(viewer, "blue", "ISRS", false);
planes.loadPlaneUpgradewave(viewer, "blue", "ISRS", [0, 1], 2);
};
export function battleFieldCommunication(viewer: Cesium.Viewer) {
var lt = new ListernTool();
lt.addInterval(viewer, tt, radarStation, planes);//添加所有飞机交互的效果
// var modelIndicator = "modelIndicator";
// var modelcss = document.getElementById(modelIndicator);
// lt.addClickTrigger(modelcss); //添加飞机信息显示
}
- 飞机操作类
import * as Cesium from "cesium";
import * as variable from '@/data/aircraft.json';
import { TimeTool } from "@/libs/battlefield-show/time";
import { findModel, getPointOnCircle, removeModel } from "@/libs/battlefield-show/effect";
import { default as TrailMaterial, generateCurve } from "@/libs/materials/PolylineTrailMaterialProperty.js"
import { deepClone, getSurroundingsPoint } from "@/libs/Utils";
import { planeFactory } from "@/libs/battlefield-show/plane";
const bs = (variable as any);
export var planes = {
positions: new Array<Array<Array<number>>>,
planeFactory: planeFactory(),
// 获得线性轨迹点
setLinePositions: function (role: string, PlaneName: string): any {
let PlaneXs = bs.players[role][PlaneName];
this.positions.length = 0;
for (let i: number = 0; i < PlaneXs.length; i++) {
var startposition = Cesium.Cartesian3.fromDegrees(PlaneXs[i]["startposition"][0], PlaneXs[i]["startposition"][1], PlaneXs[i]["startposition"][2]);
var endposition = Cesium.Cartesian3.fromDegrees(PlaneXs[i]["endPosition"][0], PlaneXs[i]["endPosition"][1], PlaneXs[i]["endPosition"][2]);
let flightData: Array<Array<number>> = new Array<Array<any>>;
flightData.push([startposition.x, startposition.y, startposition.z]);
flightData.push([endposition.x, endposition.y, endposition.z]);
this.positions.push(flightData);
}
},
//加载全局时间
timeTool: new TimeTool(2000, 1),
loadTimeModule: function (TimeTool) {
this.timeTool = TimeTool;
},
// 根据轨迹加载飞机
loadPlaneByTrajectory: function (viewer: Cesium.Viewer, role: string, PlaneName: string, ishightLight: boolean) {
let totalSeconds = this.timeTool.getTotalSeconds();
let start = this.timeTool.getStart();
let stop = this.timeTool.getStop();
let PlaneXs = bs.players[role][PlaneName];
var tep = 0;
const curPostions = this.positions;
tep = Math.ceil(totalSeconds / curPostions[0].length);
for (let ai: number = 0; ai < curPostions.length; ai++) {
// 添加位置信息
const positionProperty = new Cesium.SampledPositionProperty();
const time = Cesium.JulianDate.addSeconds(start, 0, new Cesium.JulianDate());
const position = new Cesium.Cartesian3(curPostions[ai][0][0], curPostions[ai][0][1], curPostions[ai][0][2]);
positionProperty.addSample(time, position);
for (let i: number = 1; i < curPostions[ai].length; i++) {
const dataPoint = curPostions[ai][i];
// console.log("当前高度",dataPoint[2]);
const time = Cesium.JulianDate.addSeconds(start, (i + 1) * tep, new Cesium.JulianDate());
const position = new Cesium.Cartesian3(dataPoint[0], dataPoint[1], dataPoint[2]);
positionProperty.addSample(time, position);
}
// const eyeOffsetW = new Cesium.ConstantProperty(new Cesium.Cartesian3(0, 0, -100000));
if (PlaneXs[ai]["image"].search("png") != -1) {
var entity = viewer.entities.getById(PlaneXs[ai]["id"]);
if (entity == null) {
var PlaneplaneEntity = viewer.entities.add({
id: PlaneXs[ai]["id"],
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: stop })]),
label: {
font: "12px Helvetica",
text: PlaneXs[ai]["label"],
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, //垂直方向以底部来计算标签的位置
pixelOffset: new Cesium.Cartesian2(-10, 20), //偏移量
disableDepthTestDistance: Number.POSITIVE_INFINITY,
show: true
},
position: positionProperty,
billboard: {
scale: 1,//放大倍数
width: PlaneXs[ai]["width"],
height: PlaneXs[ai]["height"],
// eyeOffset: eyeOffsetW,
image: `images/${PlaneXs[ai]["image"]}`//getImageUrl(res!.image),
},
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
});
}
else {
entity.show = true;
}
} else {
var entity = viewer.entities.getById(PlaneXs[ai]["id"]);
var planeColor = Cesium.Color.RED;
if (role == "blue") {
planeColor = Cesium.Color.BLUE;
}
if (entity == null) {
const PlaneplaneUri = Cesium.IonResource.fromAssetId(1433937);
var PlaneplaneEntity = viewer.entities.add({
id: PlaneXs[ai]["id"],
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: stop })]),
label: {
font: "12px Helvetica",
text: PlaneXs[ai]["label"],
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, //垂直方向以底部来计算标签的位置
pixelOffset: new Cesium.Cartesian2(-10, 20), //偏移量
disableDepthTestDistance: Number.POSITIVE_INFINITY,
show: true
},
position: positionProperty,
// Attach the 3D model instead of the green point.
model: {
uri: `models/aircraft/${PlaneXs[ai]["image"]}`,
scale: 5000,//放大倍数
color: Cesium.Color.fromAlpha(planeColor, 0.5),//设置模型颜色与透明度
colorBlendMode: Cesium.ColorBlendMode.HIGHLIGHT //设置颜色与原纹理的混合关系
// silhouetteColor: Cesium.Color.fromAlpha(Cesium.Color.BLUE, 1),//设置模型外轮廓颜色与透明度
// silhouetteSize: Cesium.Color.fromAlpha(Cesium.Color.RED, 1),//设置模型颜色与透明度
},
orientation: new Cesium.VelocityOrientationProperty(positionProperty)
});
} else {
entity.show = true;
}
}
}
},
// loadPlaneByLineTra: function (viewer: Cesium.Viewer, role: string, planeName: string, ishightLight: boolean) {
// let planeXs = bs.players[role][planeName];
// var planeColor = Cesium.Color.RED;
// if (role == "blue") {
// planeColor = Cesium.Color.BLUE;
// }
// for (let ai: number = 0; ai < planeXs.length; ai++) {
// var plane = this.planeFactory.createPlane(planeXs[ai]["id"], planeXs[ai]["label"], planeXs[ai]["model"], planeXs[ai]["width"], planeXs[ai]["height"],
// planeXs[ai]["image"]);
// plane.setLinePositions(planeXs[ai]["startposition"], planeXs[ai]["endPosition"]);
// plane.fly(viewer, planeColor, this.timeTool);
// }
// },
loadLineEntity(viewer, deplyTime, totalSeconds, start, axPositions, _difLng, _difLat) {
// var isExist = findModel(viewer, "CSWSUR");
// if (isExist) {
// return;
// }
// removeModel(viewer, "CSWSUR");
var timdif = 0;
const comlinesEntity = viewer.entities.add({
id: "CSWSUR",
name: "Red polygon on surface",
polyline: {
positions: new Cesium.CallbackProperty((time) => {
timdif = Cesium.JulianDate.secondsDifference(time, start);
if (timdif < deplyTime) {
return null;
}
// // 超出绑定时间
// if (timdif > totalSeconds) {
// timdif = 0.0;
// }
let positions: number[] = [];
for (var i: number = 0; i < axPositions.length; i++) {
var _currentPoLng = axPositions[i][0] - _difLng * (timdif - deplyTime);
var _currentPoLat = axPositions[i][1] + _difLat * (timdif - deplyTime);
var _curentHeight = 100;
positions.push(_currentPoLng);
positions.push(_currentPoLat);
positions.push(_curentHeight);
}
return Cesium.Cartesian3.fromDegreesArrayHeights(positions);
}, false),
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.2,
taperPower: 0.5,
color: Cesium.Color.WHITE,
})
},
});
comlinesEntity.label = new Cesium.LabelGraphics({
// position:
text: 'Red polygon on surface',
style: Cesium.LabelStyle.FILL,
fillColor: Cesium.Color.WHITE,
font: 'normal 32px MicroSoft YaHei',
showBackground: true,
scale: 0.5,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: 10000.0
});
},
//加载集群多边形
showPolygonByTrajectory: function (viewer: Cesium.Viewer, role: string, PlaneName: string, positions) {
let totalSeconds = this.timeTool.getTotalSeconds();
let start = this.timeTool.getStart();
let PlaneXs = bs.players[role][PlaneName];
let height = bs.players.red.allHeight;
var axPositions = positions;
axPositions = [
PlaneXs[0]["startposition"][0],
PlaneXs[0]["startposition"][1],
height,
PlaneXs[1]["startposition"][0],
PlaneXs[1]["startposition"][1],
height,
PlaneXs[6]["startposition"][0],
PlaneXs[6]["startposition"][1],
height,
PlaneXs[7]["startposition"][0],
PlaneXs[7]["startposition"][1],
height,
PlaneXs[10]["startposition"][0],
PlaneXs[10]["startposition"][1],
height,
PlaneXs[9]["startposition"][0],
PlaneXs[9]["startposition"][1],
height,
PlaneXs[8]["startposition"][0],
PlaneXs[8]["startposition"][1],
height,
PlaneXs[3]["startposition"][0],
PlaneXs[3]["startposition"][1],
height,
PlaneXs[2]["startposition"][0],
PlaneXs[2]["startposition"][1],
height,
PlaneXs[0]["startposition"][0],
PlaneXs[0]["startposition"][1],
height
];
var _difLng = (PlaneXs[0]["startposition"][0] - PlaneXs[0]["endPosition"][0]) / totalSeconds;
var _difLat = (PlaneXs[0]["startposition"][1] - PlaneXs[0]["endPosition"][1]) / totalSeconds;
var timdif = 0.0;
this.loadLineEntity(viewer, timdif, totalSeconds, start, axPositions, _difLng, _difLat);
},
// 加载飞机
showC130ReleaseColony: function (viewer: Cesium.Viewer, releasePlane: number, initTime: number) {
let C130 = bs.players["red"]["C130"];
var startPos = C130[0]["startposition"];
var endPos = C130[0]["endPosition"];
let totalSeconds = this.timeTool.getTotalSeconds();
let start = this.timeTool.getStart();
var positions: Array<Array<number>> = [];
for (let i = 0; i < releasePlane; i++) {
var endPositionX: number = startPos[0] + 0.02 * (Math.random() * 20 - 10);
var endPositionY: number = startPos[1] + 0.04 * Math.random() * 10;
positions.push([endPositionX, endPositionY]);
// 添加集群飞机的位置信息
var CMpositionProperty = new Cesium.SampledPositionProperty();
var time = Cesium.JulianDate.addSeconds(start, 0, new Cesium.JulianDate());
var startPocCeium = Cesium.Cartesian3.fromDegrees(startPos[0], startPos[1], startPos[2]);
CMpositionProperty.addSample(time, startPocCeium);
var midTime = Cesium.JulianDate.addSeconds(start, initTime, new Cesium.JulianDate());
var midPosition = Cesium.Cartesian3.fromDegrees(endPositionX, endPositionY, startPos[2]);
CMpositionProperty.addSample(midTime, midPosition);
var endTime = Cesium.JulianDate.addSeconds(start, totalSeconds, new Cesium.JulianDate());
var endPosition = Cesium.Cartesian3.fromDegrees(endPositionX, endPositionY + 0.2, startPos[2]);
CMpositionProperty.addSample(endTime, endPosition);
// 添加C130位置信息
var C130positionProperty = new Cesium.SampledPositionProperty();
var time = Cesium.JulianDate.addSeconds(start, 0, new Cesium.JulianDate());
var startPocCeium = Cesium.Cartesian3.fromDegrees(startPos[0], startPos[1], startPos[2]);
C130positionProperty.addSample(time, startPocCeium);
var midTime = Cesium.JulianDate.addSeconds(start, initTime, new Cesium.JulianDate());
var midPosition = Cesium.Cartesian3.fromDegrees(startPos[0], startPos[1], startPos[2]);
C130positionProperty.addSample(midTime, midPosition);
var endTime = Cesium.JulianDate.addSeconds(start, totalSeconds, new Cesium.JulianDate());
var endPosition = Cesium.Cartesian3.fromDegrees(endPos[0], endPos[1], endPos[2]);
C130positionProperty.addSample(endTime, endPosition);
var entity = viewer.entities.getById("CSW-" + i);
if (entity == null) {
var CSW = viewer.entities.add({
id: "CSW-" + i,
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: endTime })]),
label: {
font: "12px Helvetica",
text: "CSW-" + i,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, //垂直方向以底部来计算标签的位置
pixelOffset: new Cesium.Cartesian2(-10, 20), //偏移量
disableDepthTestDistance: Number.POSITIVE_INFINITY,
show: true
},
position: CMpositionProperty,
// position: Cesium.Cartesian3.fromDegrees(115.52764038352255, 22.027391974778062, 100),
billboard: {
scale: 1,//放大倍数
width: 25,
height: 10,
// eyeOffset: eyeOffsetW,
image: `images/mq4.png`//getImageUrl(res!.image),
},
orientation: new Cesium.VelocityOrientationProperty(CMpositionProperty),
});
var C130Entity = viewer.entities.add({
id: "C130-" + i,
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({ start: start, stop: endTime })]),
label: {
font: "12px Helvetica",
text: "C130-" + i,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, //垂直方向以底部来计算标签的位置
pixelOffset: new Cesium.Cartesian2(-10, 20), //偏移量
disableDepthTestDistance: Number.POSITIVE_INFINITY,
show: true
},
position: C130positionProperty,
// position: Cesium.Cartesian3.fromDegrees(115.52764038352255, 22.027391974778062, 100),
billboard: {
scale: 1,//放大倍数
width: 75,
height: 30,
// eyeOffset: eyeOffsetW,
image: `images/c130.png`//getImageUrl(res!.image),
},
orientation: new Cesium.VelocityOrientationProperty(C130positionProperty),
});
// viewer.flyTo(planeEntity);
}
else {
// entity.show = true;
}
}
var position = getSurroundingsPoint(positions);
var _difLng = 0 / totalSeconds;
var _difLat = 0.2 / (totalSeconds - initTime);
console.log(position);
this.loadLineEntity(viewer, initTime, totalSeconds, start, position, _difLng, _difLat);
},
// 添加飞机线路
//加载同种飞机通讯线路
showPlaneCommunication: function (viewer: Cesium.Viewer, role: string, PlaneName: string) {
let totalSeconds = this.timeTool.getTotalSeconds();
let start = this.timeTool.getStart();
let stop = this.timeTool.getStop();
let PlaneXs = bs.players[role][PlaneName];
const latdif = (PlaneXs[0]["endPosition"][0] - PlaneXs[0]["startposition"][0]) / totalSeconds;
const lngdif = (PlaneXs[0]["endPosition"][1] - PlaneXs[0]["startposition"][1]) / totalSeconds;
var timdif = 0.0;
var startPoints = [0, 1, 0];
var endPoints = [1, 3, 2];
for (let i: number = 0; i < startPoints.length; i++) {
var correctLocI = 0;
var correctLoc = 0;
viewer.entities.add({ // 背景线
description: 'background-line',
polyline: {
width: 3,
positions: new Cesium.CallbackProperty((time) => {
if (timdif > totalSeconds) {
timdif = 0.0;
}
timdif = Cesium.JulianDate.secondsDifference(time, start);
if (correctLocI = 0) {
correctLoc = timdif;
correctLocI += 1;
}
let curstartpositLat = PlaneXs[startPoints[i]]["startposition"][0] &#