You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

368 lines
8.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<mars-map :options="options" @onload="mapLoad"></mars-map>
</template>
<script setup>
import marsMap from "@/components/marsMap";
import PointJson from "./point.json";
import { onMounted,nextTick } from "vue";
const { proxy } = getCurrentInstance();
let options = {
scene: {
center: {
lat: 31.035216,
lng: 120.656763,
alt: 652.5,
heading: 6.3,
pitch: -23,
},
showSun: false,
showMoon: false,
showSkyBox: true,
showSkyAtmosphere: true,
fog: false,
clock: {
currentTime: "2023-11-01 12:00:00", // 固定光照时间
},
cameraController: {
zoomFactor: 1.5,
minimumZoomDistance: 0.1,
maximumZoomDistance: 200000,
enableCollisionDetection: false, // 允许进入地下
},
},
terrain: {
show: false,
},
basemaps: [
{
id: 2021,
pid: 10,
name: "天地图影像",
icon: "https://data.mars3d.cn/img/thumbnail/basemap/tdt_img.png",
type: "group",
layers: [
{
name: "底图",
type: "tdt",
layer: "img_d",
},
{
name: "注记",
type: "tdt",
layer: "img_z",
},
],
show: true,
},
],
};
const params = reactive({
lat: 31.162232,
lng: 120.734077,
altitude: 100,
heading: 0, //当前朝向
pitch: 0, //保当前俯仰角
roll: 0, //当前翻滚角
correction: 1,
speed: 500,
});
// 使用 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 = {};
const mapLoad = (mapInstance) => {
map = mapInstance;
//创建marker图层
mapLayer.markerLayer = new mars3d.layer.GraphicLayer({
allowDrillPick: true, // 如果存在坐标完全相同的图标点可以打开该属性click事件通过graphics判断
});
map.addLayer(mapLayer.markerLayer);
//创建无人机图层
mapLayer.uav = new mars3d.layer.GraphicLayer()
map.addLayer(mapLayer.uav);
map.on(mars3d.EventType.load, function (event) {
boostrapUav();
})
};
onMounted(()=>{
onAddGamepadboardListener();
})
/**
* 监听游戏手柄
*/
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
// 开始手柄操作
const renderer = () => {
startgamepad();
onAdjustAttitude();
requestAnimationFrame(renderer);
};
renderer();
});
// 监听游戏手柄拔出
window.addEventListener("gamepaddisconnected", function (e) {
clearInterval(interval);
});
};
const boostrapUav = () => {
// 绘制停机场矩形
initRectangle();
//渲染所有图标点
initMarker();
//渲染无人机
initUav();
};
const startgamepad = () => {
var gamepad = navigator.getGamepads()[0];
if (gamepad) {
//手柄方向按键
pressKey(gamepad.buttons);
// 手柄方向遥感
rocker(gamepad.axes);
}
};
// 手柄左方向遥感
const rocker = (axes) => {
const deadZone = 0.5;
const x = axes[0];
const y = axes[1];
// //机体左转
if (x < -deadZone) {
//机体左转
params.heading -= 0.115;
if (params.roll > -10) {
params.roll -= 0.115;
}
} else if (x > deadZone) {
//机体右转
params.heading += 0.115;
if (params.roll < 10) {
params.roll += 0.115;
}
}
// 检测垂直方向机体爬升
if (y < -deadZone && params.pitch <= 0.3) {
params.pitch += 0.015;
if (params.pitch > 0) {
const { speed, pitch } = params;
const temp = (params.speed / 60 / 60 / 60) * 110;
//1经纬度约等于110km
params.altitude += temp * Math.sin(pitch);
}
} else if (y > deadZone && params.pitch >= -0.3) {
//机体俯冲
params.pitch -= 0.016;
if (params.pitch < 0) {
const { speed, pitch } = params;
//1经纬度约等于110km
const temp = (params.speed / 60 / 60 / 60) * 110;
params.altitude += temp * Math.sin(pitch);
}
}
reset();
};
//左侧方向按键上下键
const pressKey = (buttons) => {
// 加速
if (buttons[12] && buttons[12].pressed) {
params.speed += 100;
}
// 减速
if (buttons[13] && buttons[13].pressed) {
if (params.speed >= 500) {
params.speed -= 100;
}
}
reset()
};
const reset = () => {
const { heading, pitch, roll } = params;
const { abs, cos } = Math;
params.correction = abs(cos(heading) * cos(pitch));
if (abs(heading) < 0.001) params.heading = 0;
if (abs(roll) < 0.001) params.roll = 0;
if (abs(pitch) < 0.001) params.pitch = 0;
//方向自动回正
// if (params.heading > 0) params.heading -= 0.0025
// if (params.heading < 0) params.heading += 0.0025
if (params.roll > 0) params.roll -= 0.003;
if (params.roll < 0) params.roll += 0.003;
if (params.pitch < 0) params.pitch += 0.005;
if (params.pitch > 0) params.pitch -= 0.003;
};
// 开启飞行姿态调整/
const onAdjustAttitude = () => {
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,
roll,
});
uav.addTimePosition(position);
};
const initUav = () => {
if (list.length == 0 && !isGamepad ) {
list = PointJson.map((item) => item.wz);
}
uav = new mars3d.graphic.FixedRoute({
id: "uav1",
name: "无人机模型",
position: {
type: "time", // 时序动态坐标
speed: 100,
list: list,
},
clockLoop: true, //是否循环播放
model: {
url: "https://data.mars3d.cn/gltf/mars/wrj.glb",
scale: 0.1,
minimumPixelSize: 0.1,
runAnimations: true,
// mergeOrientation: true,
},
polyline:{
materialType: mars3d.MaterialType.PolylineDash,//虚线
materialOptions:{
color: 'rgba(34, 232, 174, 1)',
dashLength: 8.0
}
},
camera: {
type: "gs",
},
});
mapLayer.uav.addGraphic(uav);
uav.start()
};
const initRectangle = () => {
const graphic = new mars3d.graphic.RectanglePrimitive({
positions: [
[120.657821, 31.048952],
[120.657318, 31.047691],
[120.658122, 31.047505],
[120.658591, 31.04872],
],
style: {
color: "#22E8AE",
opacity: 0.4,
outline: true,
outlineColor: "#22E8AE",
},
});
mapLayer.markerLayer.addGraphic(graphic);
};
/**
* 渲染所有点位
*/
const initMarker = () => {
console.log(imageModules)
PointJson.map((item, index) => {
//绘制名字图标
lablePoint(item, index);
// 绘制水波浪圆
circlePoint(item, index);
});
};
/**
*文字图标
*/
const lablePoint = (item, index) => {
const markerDiv = new mars3d.graphic.DivGraphic({
position: item.wz,
id: `marker${index}`,
name: item.name,
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>
`,
offsetY: -73,
clampToGround:true,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
distanceDisplayCondition: true, // 按视距距离显示
},
});
mapLayer.markerLayer.addGraphic(markerDiv);
};
/**
* 点位底部圆特效
* @param item
* @param index
*/
const circlePoint = (item, index) => {
const graphic = new mars3d.graphic.CircleEntity({
position: item.wz,
style: {
radius: 50,
height: 0,
materialType: mars3d.MaterialType.CircleWave,
materialOptions: {
color: item.type == 'school' ? '#59F9FF' : item.type == 'park' ? '#33E064' : '#22E8AE',
count: 2,
speed: 6,
},
distanceDisplayCondition: true, // 按视距距离显示
},
});
mapLayer.markerLayer.addGraphic(graphic);
};
</script>
<style scoped>
.mars3d-container {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
</style>