538 lines
13 KiB
Vue
Raw Normal View History

2023-10-20 18:32:09 +08:00
<template>
2023-10-21 18:24:25 +08:00
<div class="main-content" v-if="!infoShow">
2023-10-20 18:32:09 +08:00
<div class="main-content-title">
<span>飞行漫游</span>
<el-icon size="16" color="#fff" @click="closeDiv"><Close /></el-icon>
</div>
<div class="btn-operate">
<el-button type="primary" @click="addRoute">新增路线</el-button>
2023-11-17 18:03:46 +08:00
<el-button type="primary" @click="saveJson">保存</el-button>
2023-10-20 18:32:09 +08:00
</div>
<div class="table-operate">
2023-11-16 18:37:50 +08:00
<el-table
:data="tableData"
rowKey="id"
:header-cell-style="{ backgroundColor: '#3359B5', color: '#fff', borderColor: '#3F5C8E' }"
>
2023-10-20 18:32:09 +08:00
<el-table-column prop="name" align="center" label="名称" />
<el-table-column align="center" label="操作">
<template #default="{ row, $index }">
2023-11-16 18:37:50 +08:00
<span style="color: white; cursor: pointer; margin-right: 10px" @click="flyToModel(row, $index)">漫游</span>
<span style="color: white; cursor: pointer" @click="deleteRoute(row, $index)">删除</span>
2023-10-20 18:32:09 +08:00
</template>
</el-table-column>
</el-table>
</div>
</div>
2023-10-21 18:24:25 +08:00
<!-- 漫游数据信息弹框 -->
<div class="fly-data" v-if="infoShow">
<div class="main-content-title">
<span>漫游路线</span>
<el-icon size="16" color="#fff" @click="infoShow = false"><Close /></el-icon>
</div>
<div class="control-btn">
<el-button type="primary" @click="stopFly">停止漫游</el-button>
</div>
<div class="item-classify">
<div class="item-classify-item">
<div>路线名称</div>
<div>{{ rowObj.name ? rowObj.name : "" }}</div>
</div>
<div class="item-classify-item">
<div>视角模式</div>
<div>
<el-select v-model="viewParams.viewModel" @change="viewChange">
<el-option v-for="item in modelOptions" :key="item.value" :label="item.name" :value="item.value" />
</el-select>
</div>
</div>
<div class="item-classify-item">
<div>视角距离</div>
<div>
<el-input-number v-model="viewParams.viewDistance" controls-position="right" @blur="viewChange" />
</div>
</div>
<div class="item-classify-item">
<div>总长度</div>
<div>{{ formState.td_alllength }}</div>
</div>
<div class="item-classify-item">
<div>已漫游长度</div>
<div>{{ formState.td_length }}</div>
</div>
<div class="item-classify-item">
<div>总时长</div>
<div>{{ formState.td_alltimes }}</div>
</div>
<div class="item-classify-item">
<div>已漫游时间</div>
<div>{{ formState.td_times }}</div>
</div>
<div class="item-classify-item">
<div>经度</div>
<div>{{ formState.td_jd }}</div>
</div>
<div class="item-classify-item">
<div>纬度</div>
<div>{{ formState.td_wd }}</div>
</div>
<div class="item-classify-item">
<div>漫游高程</div>
<div>{{ formState.td_gd }}</div>
</div>
</div>
<div class="progress-line">
<el-progress :percentage="formState.percent" :status="formState.percent == 100 ? 'success' : ''" />
</div>
</div>
2023-10-20 18:32:09 +08:00
</template>
<script lang="ts" setup>
//引入cesium基础库
import "mars3d-cesium/Build/Cesium/Widgets/widgets.css";
import * as Cesium from "mars3d-cesium";
//导入mars3d主库
import "mars3d/dist/mars3d.css";
import * as mars3d from "mars3d";
2023-10-21 18:24:25 +08:00
import { ref, watch, onMounted, onUnmounted, reactive, computed } from "vue";
import type { UnwrapRef } from "vue";
2023-10-20 18:32:09 +08:00
import { ElMessage } from "element-plus";
import { GlobalStore } from "@/stores";
2023-11-17 18:03:46 +08:00
import { getSystemConfig } from "@/api/modules/mapCommon";
const props = defineProps(["mapInstance", "graphicInstance"]);
const emits = defineEmits(["hiddenConfim", "saveJson"]);
2023-10-21 18:24:25 +08:00
const importRef = ref();
interface FormState {
td_alllength: string;
td_length: string;
td_alltimes: string;
td_times: string;
td_jd: string;
td_wd: string;
td_gd: string;
percent: number;
}
const formState: UnwrapRef<FormState> = reactive({
td_alllength: "",
td_length: "",
td_alltimes: "",
td_times: "",
td_jd: "",
td_wd: "",
td_gd: "",
percent: 0
});
const rowObj = ref<any>({});
const modelOptions = ref([
{ name: "无", value: "" },
{ name: "跟随视角", value: "gs" },
{ name: "锁定第一视角", value: "dy" },
{ name: "锁定上帝视角", value: "sd" }
]);
const viewParams = ref({
viewModel: "",
viewDistance: 500
});
const infoShow = ref(false);
const globalStore = GlobalStore();
2023-10-20 18:32:09 +08:00
const tableData = ref<any>([]);
2023-11-17 18:03:46 +08:00
const layerJson = ref<any>([]);
const clearBool = ref(true);
2023-10-20 18:32:09 +08:00
let map: any = props.mapInstance;
2023-11-17 18:03:46 +08:00
let graphicLayer: any = props.graphicInstance;
2023-10-20 18:32:09 +08:00
let dataIndex = 0 as any;
onMounted(() => {
2023-11-17 18:03:46 +08:00
getConfig();
2023-10-20 18:32:09 +08:00
});
2023-11-17 18:03:46 +08:00
// 获取配置
const getConfig = async () => {
let requestData = {
configKey: "layerConfig"
};
const { result } = await getSystemConfig(requestData);
console.log(result, "6666666");
if (result) {
layerJson.value = JSON.parse(result.configValue);
console.log(layerJson.value);
if (layerJson.value.length > 0) {
layerJson.value.map((item: any, index: number) => {
if (item.type == "fixedRoute") {
const obj = {
id: item.id,
name: item.name
};
tableData.value.unshift(obj);
++dataIndex;
2023-10-21 18:24:25 +08:00
}
});
}
}
};
2023-11-17 18:03:46 +08:00
// 保存配置的图上JSON数据
const saveJson = async () => {
// if (graphicLayer.length == 0) {
// ElMessage("当前没有任何数据,无需保存!");
// return;
// }
clearBool.value = false;
emits("saveJson", graphicLayer);
2023-10-21 18:24:25 +08:00
};
// 视角模式切换
const viewChange = () => {
2023-11-17 18:03:46 +08:00
let routeData = graphicLayer.getGraphicById(rowObj.value.id);
if (routeData.type != "fixedRoute") {
routeData = graphicLayer.getGraphicById(rowObj.value.id + "-" + (dataIndex - 1));
}
2023-10-21 18:24:25 +08:00
console.log(routeData);
routeData.setCameraOptions({
type: viewParams.value.viewModel,
radius: viewParams.value.viewDistance,
followedX: 500,
followedZ: 500
});
};
// 停止漫游
const stopFly = () => {
2023-11-17 18:03:46 +08:00
let routeData = graphicLayer.getGraphicById(rowObj.value.id);
if (routeData.type != "fixedRoute") {
routeData = graphicLayer.getGraphicById(rowObj.value.id + "-" + (dataIndex - 1));
}
2023-10-21 18:24:25 +08:00
routeData && routeData.stop();
infoShow.value = false;
};
2023-10-20 18:32:09 +08:00
// 删除漫游路线
const deleteRoute = (row: any, index: number) => {
2023-11-17 18:03:46 +08:00
let polyline = graphicLayer.getGraphicById(row.id);
let routeData = graphicLayer.getGraphicById(row.id);
console.log(polyline);
if (routeData.type != "fixedRoute") {
routeData = graphicLayer.getGraphicById(row.id + "-" + (dataIndex - 1));
}
if (polyline.type != "polyline") {
let findIndex = row.id.lastIndexOf("-");
polyline = graphicLayer.getGraphicById(row.id.substring(0, findIndex));
}
2023-10-21 18:24:25 +08:00
polyline && polyline.remove(true);
2023-10-20 18:32:09 +08:00
routeData && routeData.remove(true);
tableData.value.splice(index, 1);
2023-10-21 18:24:25 +08:00
dataIndex = tableData.value.length;
2023-10-20 18:32:09 +08:00
};
// 模型路线漫游
2023-10-21 18:24:25 +08:00
const flyToModel = (row: any, index: number) => {
2023-11-17 18:03:46 +08:00
let routeData = graphicLayer.getGraphicById(row.id);
if (routeData.type != "fixedRoute") {
routeData = graphicLayer.getGraphicById(row.id + "-" + (dataIndex - 1));
}
routeData.on(mars3d.EventType.change, (event: any) => {
console.log("漫游改变change");
showInfo(routeData.info);
});
2023-10-21 18:24:25 +08:00
rowObj.value = row;
2023-10-20 18:32:09 +08:00
// 启动漫游
routeData.flyTo();
routeData.start();
2023-10-21 18:24:25 +08:00
infoShow.value = true;
2023-10-20 18:32:09 +08:00
};
// 生成路线
const productRoute = (obj: any) => {
2023-10-21 18:24:25 +08:00
console.log(obj);
2023-10-20 18:32:09 +08:00
const item = {
id: obj.id,
name: "路线-" + dataIndex
};
tableData.value.unshift(item);
2023-10-21 18:24:25 +08:00
console.log(obj.id + "-" + dataIndex);
const newRoutePath = new mars3d.graphic.FixedRoute({
id: obj.id + "-" + dataIndex,
name: "路线-" + dataIndex,
speed: 200,
positions: obj.points || obj.positions,
2023-10-20 18:32:09 +08:00
model: {
url: "//data.mars3d.cn/gltf/mars/MQ-9-Predator.glb",
scale: 1,
minimumPixelSize: 60
},
path: {
color: "#ffff00",
opacity: 0.5,
width: 1,
leadTime: 0
},
coneTrack: {
angle: 15, // 半场角度
color: "rgba(255,0,255,0.5)"
},
updateClock: false,
point: {
color: "#ffff00",
pixelSize: 5,
distanceDisplayCondition: true,
distanceDisplayCondition_near: 80000,
distanceDisplayCondition_far: Number.MAX_VALUE
},
label: {
text: "测试",
font_size: 20,
pixelOffsetX: 0,
pixelOffsetY: -20,
scaleByDistance: true,
scaleByDistance_far: 80000,
scaleByDistance_farValue: 0.4,
distanceDisplayCondition: true,
distanceDisplayCondition_far: 80000
2023-11-17 18:03:46 +08:00
},
attr: {
classKey: "FixedRoute"
2023-10-20 18:32:09 +08:00
}
});
2023-10-21 18:24:25 +08:00
console.log(newRoutePath);
graphicLayer.addGraphic(newRoutePath);
2023-11-17 18:03:46 +08:00
// console.log(newRoutePath.info);
2023-10-21 18:24:25 +08:00
// ui面板信息展示
2023-11-17 18:03:46 +08:00
// newRoutePath.on(mars3d.EventType.change, (event: any) => {
// console.log("漫游改变change");
// showInfo(newRoutePath.info);
// });
2023-10-20 18:32:09 +08:00
dataIndex++;
};
2023-10-21 18:24:25 +08:00
// 获取漫游信息
const showInfo = (item: any) => {
const params = item;
if (!params) {
return;
}
let val = Math.ceil((item.second * 100) / item.second_all);
if (val < 1) {
val = 1;
}
if (val > 100) {
val = 100;
}
formState.percent = val;
formState.td_jd = item.point?.lng;
formState.td_wd = item.point?.lat;
formState.td_gd = mars3d.MeasureUtil.formatDistance(item.point?.alt);
formState.td_times = mars3d.Util.formatTime(item.second);
formState.td_alltimes = mars3d.Util.formatTime(item.second_all);
formState.td_length = mars3d.MeasureUtil.formatDistance(item.distance) || "0米";
formState.td_alllength = mars3d.MeasureUtil.formatDistance(item.distance_all);
};
2023-10-20 18:32:09 +08:00
// 绘制路线
const addRoute = () => {
graphicLayer.startDraw({
type: "polyline",
style: {
pixelSize: 12,
color: "#3388ff"
},
success: function (graphic: any) {
console.log(graphic);
productRoute(graphic);
// eslint-disable-next-line no-console
// console.log(JSON.stringify(graphic.coordinates));
}
});
};
const closeDiv = () => {
emits("hiddenConfim");
};
onUnmounted(() => {
map = null;
2023-11-17 18:03:46 +08:00
if (clearBool) {
graphicLayer.clear();
}
2023-10-20 18:32:09 +08:00
});
</script>
<style scoped lang="scss">
@mixin flex {
display: flex;
align-items: center;
}
// 菜单弹框出现动画
@keyframes fadeIn {
0% {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
100% {
opacity: 1;
transform: none;
}
}
.main-content {
position: absolute;
top: 60px;
right: 10px;
padding-bottom: 10px;
background-image: none !important;
border: 1px solid #008aff70;
border-radius: 2px !important;
background-color: rgba(23, 49, 71, 0.8);
width: 300px;
box-shadow: 0 4px 15px 1px #02213bb3;
animation: fadeIn 1s;
&-title {
@include flex;
width: 100%;
height: 40px;
padding: 0 5px 0 10px;
2023-11-15 11:58:29 +08:00
background-image: url("@/assets/images/Mars3DIcon/subClassTitle.png");
background-size: 100% 100%;
background-repeat: no-repeat;
2023-10-20 18:32:09 +08:00
span {
font-size: 16px;
color: #0089fe;
margin-right: auto;
}
:deep() {
.el-icon {
cursor: pointer;
}
}
}
.btn-operate {
@include flex;
justify-content: center;
margin-top: 10px;
:deep() {
.el-button {
margin-left: 10px;
}
}
}
.table-operate {
width: 95%;
margin: 0 auto;
margin-top: 10px;
}
}
2023-10-21 18:24:25 +08:00
.fly-data {
position: absolute;
bottom: 60px;
right: 10px;
padding-bottom: 10px;
background-image: none !important;
border: 1px solid #008aff70;
border-radius: 2px !important;
background-color: rgba(23, 49, 71, 0.8);
width: 300px;
box-shadow: 0 4px 15px 1px #02213bb3;
animation: fadeIn 1s;
.main-content-title {
@include flex;
width: 100%;
height: 40px;
padding: 0 5px 0 10px;
background-color: #173147;
span {
font-size: 16px;
color: #0089fe;
margin-right: auto;
}
:deep() {
.el-icon {
cursor: pointer;
}
}
}
.control-btn {
margin: 10px 0 0 10px;
}
.item-classify {
padding: 10px;
display: flex;
flex-direction: column;
&-item {
display: flex;
color: white;
margin-bottom: 5px;
> div:nth-child(1) {
width: 100px;
height: 42px;
@include flex;
justify-content: center;
border: 2px solid white;
text-align: center;
padding: 5px;
}
> div:nth-child(2) {
flex: 1;
height: 42px;
@include flex;
justify-content: center;
line-height: 30px;
border: 2px solid white;
border-left: 0;
text-align: center;
padding: 5px;
}
}
}
.progress-line {
padding: 10px;
height: 30px;
@include flex;
:deep() {
.el-progress {
width: 100%;
}
.el-progress__text {
color: white;
}
}
}
}
2023-11-16 18:37:50 +08:00
// element 组件样式
:deep() {
.el-input__wrapper {
background-color: transparent !important;
}
.el-input__inner {
color: white;
}
.el-button {
background: rgba(51, 89, 181, 0.6);
border-radius: 6px;
border: 0;
}
.el-table {
background-color: transparent;
tr {
background-color: transparent;
}
}
.el-table__border-left-patch {
background-color: #3f5c8e;
}
.el-table--border .el-table__inner-wrapper::after {
background-color: #3f5c8e;
}
.el-table--border::after {
background-color: #3f5c8e;
}
.el-table__inner-wrapper::before {
background-color: #3f5c8e;
}
.el-table td.el-table__cell {
border-color: #3f5c8e;
}
.el-table--border .el-table__cell {
border-color: #3f5c8e;
}
.cell {
color: white;
}
.el-table__row:hover {
background-color: transparent;
}
.el-table__body tr:hover > td {
// background-color: #008bff !important;
background-color: transparent !important;
}
}
2023-10-20 18:32:09 +08:00
</style>