|
|
|
@ -5,8 +5,11 @@
|
|
|
|
|
<script setup>
|
|
|
|
|
import marsMap from "@/components/marsMap";
|
|
|
|
|
import PointJson from "./point.json";
|
|
|
|
|
import { onMounted,nextTick } from "vue";
|
|
|
|
|
import { onMounted, ref, reactive, watch, onUnmounted } from "vue";
|
|
|
|
|
import moment from "moment";
|
|
|
|
|
|
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
|
|
|
|
|
|
let options = {
|
|
|
|
|
scene: {
|
|
|
|
|
center: {
|
|
|
|
@ -68,17 +71,44 @@ const params = reactive({
|
|
|
|
|
speed: 500,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 使用 import.meta.glob 动态导入本地图片
|
|
|
|
|
const imageModules = import.meta.glob('@/assets/images/*.png', { eager: true });
|
|
|
|
|
let currentTimestampInSeconds = ref(0);
|
|
|
|
|
let isGamepad = ref(false);
|
|
|
|
|
let animationFrameId;
|
|
|
|
|
|
|
|
|
|
let gamepad = reactive({});
|
|
|
|
|
|
|
|
|
|
// 使用 import.meta.glob 动态导入本地图片
|
|
|
|
|
const imageModules = import.meta.glob("@/assets/images/*.png", { eager: true });
|
|
|
|
|
// 获取图片路径
|
|
|
|
|
const imageUrls = Object.values(imageModules).map((module) => module.default);
|
|
|
|
|
|
|
|
|
|
let isGamepad = false;
|
|
|
|
|
let map = null;
|
|
|
|
|
let list = [];
|
|
|
|
|
let uav = null;
|
|
|
|
|
const mapLayer = {};
|
|
|
|
|
// 每隔 5 秒更新一次时间戳
|
|
|
|
|
const intervalId = setInterval(() => {
|
|
|
|
|
const currentTimestamp = moment().unix();
|
|
|
|
|
// 把时间戳转换为 moment 对象
|
|
|
|
|
const moment1 = moment.unix(currentTimestamp);
|
|
|
|
|
const moment2 = moment.unix(currentTimestampInSeconds.value);
|
|
|
|
|
// 计算时间差(以分钟为单位)
|
|
|
|
|
const diffInMinutes = Math.abs(moment1.diff(moment2, "minutes"));
|
|
|
|
|
if (diffInMinutes === 1 && isGamepad.value) {
|
|
|
|
|
isGamepad.value = false;
|
|
|
|
|
currentTimestampInSeconds.value = 0
|
|
|
|
|
params.altitude = 100
|
|
|
|
|
proxy.$modal.msgSuccess("巡航模式已启动");
|
|
|
|
|
map.flyToPoint(new mars3d.LngLatPoint(120.657967, 31.048193));
|
|
|
|
|
uav = null;
|
|
|
|
|
mapLayer.uav.clear(); //清除无人机图层
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
initUav(); //重新渲染固定航线
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
|
|
|
|
const mapLoad = (mapInstance) => {
|
|
|
|
|
map = mapInstance;
|
|
|
|
|
//创建marker图层
|
|
|
|
@ -87,53 +117,70 @@ const mapLoad = (mapInstance) => {
|
|
|
|
|
});
|
|
|
|
|
map.addLayer(mapLayer.markerLayer);
|
|
|
|
|
//创建无人机图层
|
|
|
|
|
mapLayer.uav = new mars3d.layer.GraphicLayer()
|
|
|
|
|
mapLayer.uav = new mars3d.layer.GraphicLayer();
|
|
|
|
|
map.addLayer(mapLayer.uav);
|
|
|
|
|
|
|
|
|
|
map.on(mars3d.EventType.load, function (event) {
|
|
|
|
|
onAddGamepadboardListener();
|
|
|
|
|
boostrapUav();
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onMounted(()=>{
|
|
|
|
|
onAddGamepadboardListener();
|
|
|
|
|
})
|
|
|
|
|
// 组件卸载时清除定时器
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
clearInterval(intervalId);
|
|
|
|
|
if(animationFrameId){
|
|
|
|
|
cancelAnimationFrame(animationFrameId);
|
|
|
|
|
}
|
|
|
|
|
window.removeEventListener("gamepadconnected", handleGamepadConnected);
|
|
|
|
|
window.removeEventListener("gamepaddisconnected", handleGamepadDisconnected);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 监听游戏手柄
|
|
|
|
|
*/
|
|
|
|
|
const onAddGamepadboardListener = () => {
|
|
|
|
|
window.addEventListener("gamepadconnected", function (e) {
|
|
|
|
|
// var gp = navigator.getGamepads()[e.gamepad.index];
|
|
|
|
|
proxy.$modal.msgSuccess("手柄控制已启动");
|
|
|
|
|
// 获取无人机固定航线最后的信息
|
|
|
|
|
const uavItem = mapLayer.uav.getGraphicById('uav1');
|
|
|
|
|
const {heading,pitch,roll,position } = uavItem
|
|
|
|
|
const cartographic = mars3d.LngLatPoint.fromCartesian(position)
|
|
|
|
|
params.lat =cartographic._lat
|
|
|
|
|
params.lng=cartographic._lng
|
|
|
|
|
params.heading=heading
|
|
|
|
|
params.pitch=pitch
|
|
|
|
|
params.roll=roll
|
|
|
|
|
window.addEventListener("gamepadconnected", handleGamepadConnected);
|
|
|
|
|
// 监听游戏手柄拔出
|
|
|
|
|
window.addEventListener("gamepaddisconnected", handleGamepadDisconnected);
|
|
|
|
|
};
|
|
|
|
|
const handleGamepadDisconnected = () => {
|
|
|
|
|
console.log("断开");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleGamepadConnected = (e) => {
|
|
|
|
|
|
|
|
|
|
handleUavDataLast();
|
|
|
|
|
// 开始手柄操作
|
|
|
|
|
const renderer = () => {
|
|
|
|
|
|
|
|
|
|
startgamepad();
|
|
|
|
|
|
|
|
|
|
if(isGamepad.value){
|
|
|
|
|
onAdjustAttitude();
|
|
|
|
|
requestAnimationFrame(renderer);
|
|
|
|
|
}
|
|
|
|
|
animationFrameId = requestAnimationFrame(renderer);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
renderer();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
// 监听游戏手柄拔出
|
|
|
|
|
window.addEventListener("gamepaddisconnected", function (e) {
|
|
|
|
|
clearInterval(interval);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleUavDataLast = () => {
|
|
|
|
|
proxy.$modal.msgSuccess("手柄控制已启动");
|
|
|
|
|
isGamepad.value = true;
|
|
|
|
|
// 获取无人机固定航线最后的信息
|
|
|
|
|
const uavItem = mapLayer.uav.getGraphicById("uav1");
|
|
|
|
|
const { heading, pitch, roll, position } = uavItem;
|
|
|
|
|
const cartographic = mars3d.LngLatPoint.fromCartesian(position);
|
|
|
|
|
params.lat = cartographic._lat;
|
|
|
|
|
params.lng = cartographic._lng;
|
|
|
|
|
params.heading = heading;
|
|
|
|
|
params.pitch = pitch;
|
|
|
|
|
params.roll = roll;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const boostrapUav = () => {
|
|
|
|
@ -146,27 +193,36 @@ const boostrapUav = () => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const startgamepad = () => {
|
|
|
|
|
var gamepad = navigator.getGamepads()[0];
|
|
|
|
|
gamepad = navigator.getGamepads()[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (gamepad) {
|
|
|
|
|
//手柄方向按键
|
|
|
|
|
pressKey(gamepad.buttons);
|
|
|
|
|
// pressKey(gamepad.buttons);
|
|
|
|
|
// 手柄方向遥感
|
|
|
|
|
rocker(gamepad.axes);
|
|
|
|
|
rocker();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// 手柄左方向遥感
|
|
|
|
|
const rocker = (axes) => {
|
|
|
|
|
const rocker = () => {
|
|
|
|
|
const axes = gamepad.axes;
|
|
|
|
|
const deadZone = 0.5;
|
|
|
|
|
const x = axes[0];
|
|
|
|
|
const y = axes[1];
|
|
|
|
|
// //机体左转
|
|
|
|
|
|
|
|
|
|
//机体左转
|
|
|
|
|
if (x < -deadZone) {
|
|
|
|
|
if(!isGamepad.value){
|
|
|
|
|
console.log('左')
|
|
|
|
|
}
|
|
|
|
|
handleUavTime();
|
|
|
|
|
//机体左转
|
|
|
|
|
params.heading -= 0.115;
|
|
|
|
|
if (params.roll > -10) {
|
|
|
|
|
params.roll -= 0.115;
|
|
|
|
|
}
|
|
|
|
|
} else if (x > deadZone) {
|
|
|
|
|
handleUavTime();
|
|
|
|
|
//机体右转
|
|
|
|
|
params.heading += 0.115;
|
|
|
|
|
if (params.roll < 10) {
|
|
|
|
@ -175,6 +231,7 @@ const rocker = (axes) => {
|
|
|
|
|
}
|
|
|
|
|
// 检测垂直方向机体爬升
|
|
|
|
|
if (y < -deadZone && params.pitch <= 0.3) {
|
|
|
|
|
handleUavTime();
|
|
|
|
|
params.pitch += 0.015;
|
|
|
|
|
if (params.pitch > 0) {
|
|
|
|
|
const { speed, pitch } = params;
|
|
|
|
@ -183,6 +240,7 @@ const rocker = (axes) => {
|
|
|
|
|
params.altitude += temp * Math.sin(pitch);
|
|
|
|
|
}
|
|
|
|
|
} else if (y > deadZone && params.pitch >= -0.3) {
|
|
|
|
|
handleUavTime();
|
|
|
|
|
//机体俯冲
|
|
|
|
|
params.pitch -= 0.016;
|
|
|
|
|
if (params.pitch < 0) {
|
|
|
|
@ -198,15 +256,29 @@ const rocker = (axes) => {
|
|
|
|
|
const pressKey = (buttons) => {
|
|
|
|
|
// 加速
|
|
|
|
|
if (buttons[12] && buttons[12].pressed) {
|
|
|
|
|
handleUavTime();
|
|
|
|
|
params.speed += 100;
|
|
|
|
|
}
|
|
|
|
|
// 减速
|
|
|
|
|
if (buttons[13] && buttons[13].pressed) {
|
|
|
|
|
handleUavTime();
|
|
|
|
|
if (params.speed >= 500) {
|
|
|
|
|
params.speed -= 100;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
reset()
|
|
|
|
|
reset();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//只要操作手柄就获取当前时间戳
|
|
|
|
|
const handleUavTime = () => {
|
|
|
|
|
|
|
|
|
|
if(!isGamepad.value){
|
|
|
|
|
handleUavDataLast()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentTimestampInSeconds.value = moment().unix();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const reset = () => {
|
|
|
|
@ -227,12 +299,14 @@ const reset = () => {
|
|
|
|
|
|
|
|
|
|
// 开启飞行姿态调整/
|
|
|
|
|
const onAdjustAttitude = () => {
|
|
|
|
|
if (!uav) return;
|
|
|
|
|
const temp = params.speed / 60 / 60 / 60 / 110;
|
|
|
|
|
params.lng += temp * Math.cos(Cesium.Math.toRadians(params.heading));
|
|
|
|
|
params.lat -= temp * Math.sin(Cesium.Math.toRadians(params.heading));
|
|
|
|
|
const { lng, lat, altitude, heading, pitch, roll } = params;
|
|
|
|
|
params.altitude += temp * Math.sin(pitch) * 110 * 1000 * 10;
|
|
|
|
|
const position = Cesium.Cartesian3.fromDegrees(lng, lat, altitude);
|
|
|
|
|
|
|
|
|
|
uav.model.setStyle({
|
|
|
|
|
heading,
|
|
|
|
|
pitch,
|
|
|
|
@ -242,9 +316,7 @@ const onAdjustAttitude = () => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const initUav = () => {
|
|
|
|
|
if (list.length == 0 && !isGamepad ) {
|
|
|
|
|
list = PointJson.map((item) => item.wz);
|
|
|
|
|
}
|
|
|
|
|
uav = new mars3d.graphic.FixedRoute({
|
|
|
|
|
id: "uav1",
|
|
|
|
|
name: "无人机模型",
|
|
|
|
@ -261,19 +333,19 @@ const initUav = () => {
|
|
|
|
|
runAnimations: true,
|
|
|
|
|
// mergeOrientation: true,
|
|
|
|
|
},
|
|
|
|
|
polyline:{
|
|
|
|
|
materialType: mars3d.MaterialType.PolylineDash,//虚线
|
|
|
|
|
materialOptions:{
|
|
|
|
|
color: 'rgba(34, 232, 174, 1)',
|
|
|
|
|
dashLength: 8.0
|
|
|
|
|
}
|
|
|
|
|
polyline: {
|
|
|
|
|
materialType: mars3d.MaterialType.PolylineDash, //虚线
|
|
|
|
|
materialOptions: {
|
|
|
|
|
color: "rgba(34, 232, 174, 1)",
|
|
|
|
|
dashLength: 8.0,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
camera: {
|
|
|
|
|
type: "gs",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
mapLayer.uav.addGraphic(uav);
|
|
|
|
|
uav.start()
|
|
|
|
|
uav.start();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const initRectangle = () => {
|
|
|
|
@ -298,9 +370,8 @@ const initRectangle = () => {
|
|
|
|
|
* 渲染所有点位
|
|
|
|
|
*/
|
|
|
|
|
const initMarker = () => {
|
|
|
|
|
console.log(imageModules)
|
|
|
|
|
console.log(imageModules);
|
|
|
|
|
PointJson.map((item, index) => {
|
|
|
|
|
|
|
|
|
|
//绘制名字图标
|
|
|
|
|
lablePoint(item, index);
|
|
|
|
|
// 绘制水波浪圆
|
|
|
|
@ -319,12 +390,24 @@ const lablePoint = (item, index) => {
|
|
|
|
|
style: {
|
|
|
|
|
html: `
|
|
|
|
|
<div class="div-marker">
|
|
|
|
|
<div class="marker-name ${item.type == 'school' ? 'color-school' : item.type == 'park' ? 'color-park' :'color-uav' } ">${item.name}</div>
|
|
|
|
|
<img class="marker-icon" src="${item.type == 'school' ? imageUrls[5] : item.type == 'park' ? imageUrls[4] :imageUrls[6] }" />
|
|
|
|
|
<div class="marker-name ${
|
|
|
|
|
item.type == "school"
|
|
|
|
|
? "color-school"
|
|
|
|
|
: item.type == "park"
|
|
|
|
|
? "color-park"
|
|
|
|
|
: "color-uav"
|
|
|
|
|
} ">${item.name}</div>
|
|
|
|
|
<img class="marker-icon" src="${
|
|
|
|
|
item.type == "school"
|
|
|
|
|
? imageUrls[5]
|
|
|
|
|
: item.type == "park"
|
|
|
|
|
? imageUrls[4]
|
|
|
|
|
: imageUrls[6]
|
|
|
|
|
}" />
|
|
|
|
|
</div>
|
|
|
|
|
`,
|
|
|
|
|
offsetY: -73,
|
|
|
|
|
clampToGround:true,
|
|
|
|
|
clampToGround: true,
|
|
|
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|
|
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
|
|
|
distanceDisplayCondition: true, // 按视距距离显示
|
|
|
|
@ -345,7 +428,12 @@ const circlePoint = (item, index) => {
|
|
|
|
|
height: 0,
|
|
|
|
|
materialType: mars3d.MaterialType.CircleWave,
|
|
|
|
|
materialOptions: {
|
|
|
|
|
color: item.type == 'school' ? '#59F9FF' : item.type == 'park' ? '#33E064' : '#22E8AE',
|
|
|
|
|
color:
|
|
|
|
|
item.type == "school"
|
|
|
|
|
? "#59F9FF"
|
|
|
|
|
: item.type == "park"
|
|
|
|
|
? "#33E064"
|
|
|
|
|
: "#22E8AE",
|
|
|
|
|
count: 2,
|
|
|
|
|
speed: 6,
|
|
|
|
|
},
|
|
|
|
|