feat: 部分功能新增
This commit is contained in:
parent
90015511b6
commit
e5f598725d
@ -1,20 +1,30 @@
|
||||
<template>
|
||||
<div class="main-content">
|
||||
<div class="main-content" v-if="!infoShow">
|
||||
<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>
|
||||
<el-button type="primary">导入</el-button>
|
||||
<el-button type="primary">导出</el-button>
|
||||
<el-upload
|
||||
ref="importRef"
|
||||
:auto-upload="false"
|
||||
:headers="headers"
|
||||
:on-change="uploadFileChange"
|
||||
multiple
|
||||
:limit="1"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<el-button type="primary">导入</el-button>
|
||||
</el-upload>
|
||||
<el-button type="primary" @click="expJSONFile">导出</el-button>
|
||||
</div>
|
||||
<div class="table-operate">
|
||||
<el-table :data="tableData" rowKey="id">
|
||||
<el-table-column prop="name" align="center" label="名称" />
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button link type="primary" @click="flyToModel(row)">漫游</el-button>
|
||||
<el-button link type="primary" @click="flyToModel(row, $index)">漫游</el-button>
|
||||
<!-- <el-button link type="primary">编辑</el-button> -->
|
||||
<el-button link type="primary" @click="deleteRoute(row, $index)">删除</el-button>
|
||||
</template>
|
||||
@ -22,6 +32,68 @@
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 漫游数据信息弹框 -->
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -31,27 +103,51 @@ import * as Cesium from "mars3d-cesium";
|
||||
//导入mars3d主库
|
||||
import "mars3d/dist/mars3d.css";
|
||||
import * as mars3d from "mars3d";
|
||||
import { ref, watch, onMounted, onUnmounted } from "vue";
|
||||
import { ref, watch, onMounted, onUnmounted, reactive, computed } from "vue";
|
||||
import type { UnwrapRef } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { GlobalStore } from "@/stores";
|
||||
const globalStore = GlobalStore();
|
||||
const props = defineProps(["mapInstance"]);
|
||||
const emits = defineEmits(["hiddenConfim"]);
|
||||
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();
|
||||
const headers = ref({ Authorization: "Bearer " + globalStore.token });
|
||||
const tableData = ref<any>([]);
|
||||
let map: any = props.mapInstance;
|
||||
let graphicLayer: any;
|
||||
let dataIndex = 0 as any;
|
||||
const colors = [
|
||||
"rgb(40, 40, 255)",
|
||||
"rgb(0, 88, 176)",
|
||||
"rgb(0, 128, 255)",
|
||||
"rgb(0, 217, 0)",
|
||||
"rgb(0, 151, 0)",
|
||||
"rgb(255, 199, 83)",
|
||||
"rgb(255, 144, 30)",
|
||||
"rgb(202, 101, 0)",
|
||||
"rgb(255, 0, 0)"
|
||||
];
|
||||
onMounted(() => {
|
||||
graphicLayer = new mars3d.layer.GraphicLayer({
|
||||
hasEdit: false,
|
||||
@ -59,33 +155,128 @@ onMounted(() => {
|
||||
});
|
||||
map.addLayer(graphicLayer);
|
||||
});
|
||||
// 打开JSON文件
|
||||
const uploadFileChange = (response: any) => {
|
||||
console.log(response);
|
||||
|
||||
const item = response.raw;
|
||||
const fileName = item.name;
|
||||
const fileType = fileName?.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase();
|
||||
try {
|
||||
if (fileType === "json" || fileType === "geojson") {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(item, "UTF-8");
|
||||
reader.onloadend = function (e) {
|
||||
const geojson = JSON.parse(this.result as string);
|
||||
console.log("打开了json文件", geojson);
|
||||
if (geojson.type === "graphic" && geojson.data) {
|
||||
// graphicLayer.addGraphic(geojson.data);
|
||||
if (geojson.data.length > 0) {
|
||||
geojson.data.map((item: any, index: number) => {
|
||||
if (item.type == "polyline") {
|
||||
graphicLayer.addGraphic(item);
|
||||
console.log("111111111111111");
|
||||
productRoute(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
// graphicLayer.flyTo();
|
||||
} else {
|
||||
graphicLayer.loadGeoJSON(geojson, { flyTo: true });
|
||||
// initGraphicableData(graphicLayer)
|
||||
}
|
||||
};
|
||||
} else if (fileType === "kml") {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(item, "UTF-8");
|
||||
reader.onloadend = function (e) {
|
||||
const strkml = this.result;
|
||||
|
||||
map.kgUtil.toGeoJSON(strkml).then((geojson: any) => {
|
||||
console.log("kml2geojson转换结果为", geojson);
|
||||
|
||||
graphicLayer.loadGeoJSON(geojson, {
|
||||
flyTo: true
|
||||
});
|
||||
});
|
||||
};
|
||||
} else if (fileType === "kmz") {
|
||||
// 加载input文件控件的二进制流
|
||||
|
||||
map.kgUtil.toGeoJSON(item).then((geojson: any) => {
|
||||
console.log("kmz2geojson", geojson);
|
||||
|
||||
graphicLayer.loadGeoJSON(geojson, {
|
||||
flyTo: true
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ElMessage("暂不支持 " + fileType + " 文件类型的数据!");
|
||||
}
|
||||
importRef.value.clearFiles();
|
||||
} catch (error) {
|
||||
ElMessage("有相同数据");
|
||||
}
|
||||
};
|
||||
// 导出JSON文件
|
||||
const expJSONFile = () => {
|
||||
if (graphicLayer.length == 0) {
|
||||
ElMessage("当前没有任何路线数据,无需保存!");
|
||||
return;
|
||||
}
|
||||
const geojson = graphicLayer.toJSON();
|
||||
mars3d.Util.downloadFile("矢量数据JSON.json", JSON.stringify(geojson));
|
||||
};
|
||||
// 视角模式切换
|
||||
const viewChange = () => {
|
||||
const routeData = graphicLayer.getGraphicById(rowObj.value.id + "-" + (dataIndex - 1));
|
||||
console.log(routeData);
|
||||
routeData.setCameraOptions({
|
||||
type: viewParams.value.viewModel,
|
||||
radius: viewParams.value.viewDistance,
|
||||
followedX: 500,
|
||||
followedZ: 500
|
||||
});
|
||||
};
|
||||
// 停止漫游
|
||||
const stopFly = () => {
|
||||
const routeData = graphicLayer.getGraphicById(rowObj.value.id + "-" + (dataIndex - 1));
|
||||
routeData && routeData.stop();
|
||||
infoShow.value = false;
|
||||
};
|
||||
// 删除漫游路线
|
||||
const deleteRoute = (row: any, index: number) => {
|
||||
const routeData = graphicLayer.getGraphicById(row.id);
|
||||
const polyline = graphicLayer.getGraphicById(row.id);
|
||||
const routeData = graphicLayer.getGraphicById(row.id + "-" + index);
|
||||
polyline && polyline.remove(true);
|
||||
routeData && routeData.remove(true);
|
||||
tableData.value.splice(index, 1);
|
||||
dataIndex = tableData.value.length;
|
||||
};
|
||||
// 模型路线漫游
|
||||
const flyToModel = (row: any) => {
|
||||
const routeData = graphicLayer.getGraphicById("0");
|
||||
console.log(routeData);
|
||||
const flyToModel = (row: any, index: number) => {
|
||||
const polyline = graphicLayer.getGraphicById(row.id);
|
||||
const routeData = graphicLayer.getGraphicById(row.id + "-" + index);
|
||||
rowObj.value = row;
|
||||
// 启动漫游
|
||||
routeData.flyTo();
|
||||
routeData.start();
|
||||
infoShow.value = true;
|
||||
};
|
||||
// 生成路线
|
||||
const productRoute = (obj: any) => {
|
||||
console.log(obj.id);
|
||||
console.log(obj);
|
||||
const item = {
|
||||
id: obj.id,
|
||||
name: "路线-" + dataIndex
|
||||
};
|
||||
tableData.value.unshift(item);
|
||||
const routePath = new mars3d.graphic.FixedRoute({
|
||||
id: dataIndex + "",
|
||||
name: "111",
|
||||
speed: 10000,
|
||||
positions: obj.points,
|
||||
console.log(obj.id + "-" + dataIndex);
|
||||
const newRoutePath = new mars3d.graphic.FixedRoute({
|
||||
id: obj.id + "-" + dataIndex,
|
||||
name: "路线-" + dataIndex,
|
||||
speed: 200,
|
||||
positions: obj.points || obj.positions,
|
||||
model: {
|
||||
url: "//data.mars3d.cn/gltf/mars/MQ-9-Predator.glb",
|
||||
scale: 1,
|
||||
@ -121,9 +312,39 @@ const productRoute = (obj: any) => {
|
||||
distanceDisplayCondition_far: 80000
|
||||
}
|
||||
});
|
||||
graphicLayer.addGraphic(routePath);
|
||||
console.log(newRoutePath);
|
||||
graphicLayer.addGraphic(newRoutePath);
|
||||
console.log(newRoutePath.info);
|
||||
// ui面板信息展示
|
||||
newRoutePath.on(mars3d.EventType.change, (event: any) => {
|
||||
console.log("漫游改变change");
|
||||
showInfo(newRoutePath.info);
|
||||
});
|
||||
dataIndex++;
|
||||
};
|
||||
// 获取漫游信息
|
||||
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);
|
||||
};
|
||||
// 绘制路线
|
||||
const addRoute = () => {
|
||||
graphicLayer.startDraw({
|
||||
@ -210,4 +431,80 @@ onUnmounted(() => {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
700
src/views/goverment/largeScreen/components/mapMark.vue
Normal file
700
src/views/goverment/largeScreen/components/mapMark.vue
Normal file
@ -0,0 +1,700 @@
|
||||
<template>
|
||||
<div class="main-content" v-if="!infoShow">
|
||||
<div class="main-content-title">
|
||||
<span>图上标绘</span>
|
||||
<el-icon size="16" color="#fff" @click="closeDiv"><Close /></el-icon>
|
||||
</div>
|
||||
<div class="item-classify">
|
||||
<div class="item-classify-item">
|
||||
<span>图层管理:</span>
|
||||
<div class="operate-menu">
|
||||
<el-checkbox v-model="btnOperate.check1" @change="onChangePopup">Popup绑定</el-checkbox>
|
||||
<el-checkbox v-model="btnOperate.check2" @change="onChangeHasEdit">是否编辑</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-classify-item">
|
||||
<span>数据管理:</span>
|
||||
<div class="operate-menu">
|
||||
<el-button type="primary" @click="onClickClear">清除</el-button>
|
||||
<el-upload
|
||||
ref="importRef"
|
||||
:auto-upload="false"
|
||||
:headers="headers"
|
||||
:on-change="uploadFileChange"
|
||||
multiple
|
||||
:limit="1"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<el-button type="primary">打开</el-button>
|
||||
</el-upload>
|
||||
<el-button type="primary" @click="onClickSaveJson">保存GeoJSON</el-button>
|
||||
<!-- <el-button type="primary" @click="onClickSaveKml">另存KML</el-button>
|
||||
<el-button type="primary">另存WKT</el-button> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-classify-item">
|
||||
<span>单个点类:</span>
|
||||
<div class="operate-menu">
|
||||
<el-button type="primary" @click="drawPoint">点</el-button>
|
||||
<el-button type="primary" @click="drawLabel">文字</el-button>
|
||||
<el-button type="primary" @click="drawMarker">图标点</el-button>
|
||||
<el-button type="primary" @click="onClickStartDarw">小模型</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-classify-item">
|
||||
<span>二维空间:</span>
|
||||
<div class="operate-menu">
|
||||
<el-button type="primary" @click="drawPolyline(false)">线</el-button>
|
||||
<el-button type="primary" @click="drawBrushLine(false)">自由线</el-button>
|
||||
<el-button type="primary" @click="drawPolygon(false)">面</el-button>
|
||||
<el-button type="primary" @click="drawEllipse(false)">圆</el-button>
|
||||
<el-button type="primary" @click="drawRectangle(false)">矩形</el-button>
|
||||
<el-button type="primary" @click="draPlane">平面</el-button>
|
||||
<el-button type="primary" @click="drawCurve(false)">曲线</el-button>
|
||||
<el-button type="primary" @click="drawCorridor(false)">走廊</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-classify-item">
|
||||
<span>二维贴地:</span>
|
||||
<div class="operate-menu">
|
||||
<el-button type="primary" @click="drawPolyline(true)">线</el-button>
|
||||
<el-button type="primary" @click="drawBrushLine(true)">自由线</el-button>
|
||||
<el-button type="primary" @click="drawPolygon(true)">面</el-button>
|
||||
<el-button type="primary" @click="drawEllipse(true)">圆</el-button>
|
||||
<el-button type="primary" @click="drawCurve(true)">曲线</el-button>
|
||||
<el-button type="primary" @click="drawCorridor(true)">走廊</el-button>
|
||||
<el-button type="primary" @click="drawRectangle(true)">矩形</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-classify-item">
|
||||
<span>三维空间:</span>
|
||||
<div class="operate-menu">
|
||||
<el-button type="primary" @click="drawEllipsoid">球</el-button>
|
||||
<el-button type="primary" @click="draWall(false)">墙</el-button>
|
||||
<el-button type="primary" @click="drawBox">盒子</el-button>
|
||||
<el-button type="primary" @click="drawExtrudedCircle">圆柱</el-button>
|
||||
<el-button type="primary" @click="drawCylinder">圆锥</el-button>
|
||||
<el-button type="primary" @click="draWall(true)">闭合墙</el-button>
|
||||
<el-button type="primary" @click="drawExtrudedPolygon">面立体</el-button>
|
||||
<el-button type="primary" @click="drawExtrudedRectangle">矩形立体</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 漫游数据信息弹框 -->
|
||||
<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>
|
||||
</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";
|
||||
import { ref, watch, onMounted, onUnmounted, reactive, computed } from "vue";
|
||||
import type { UnwrapRef } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { GlobalStore } from "@/stores";
|
||||
const props = defineProps(["mapInstance"]);
|
||||
const emits = defineEmits(["hiddenConfim"]);
|
||||
const btnOperate = ref({
|
||||
check1: false,
|
||||
check2: false
|
||||
});
|
||||
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();
|
||||
const headers = ref({ Authorization: "Bearer " + globalStore.token });
|
||||
const tableData = ref<any>([]);
|
||||
let map: any = props.mapInstance;
|
||||
let graphicLayer: any;
|
||||
let dataIndex = 0 as any;
|
||||
onMounted(() => {
|
||||
graphicLayer = new mars3d.layer.GraphicLayer({
|
||||
hasEdit: false,
|
||||
isAutoEditing: false // 绘制完成后是否自动激活编辑
|
||||
});
|
||||
map.addLayer(graphicLayer);
|
||||
});
|
||||
// 绘制矩形立体
|
||||
const drawExtrudedRectangle = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "rectangle",
|
||||
style: {
|
||||
color: "#00ff00",
|
||||
opacity: 0.6,
|
||||
diffHeight: 300
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制面立体
|
||||
const drawExtrudedPolygon = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "polygon",
|
||||
style: {
|
||||
color: "#00ff00",
|
||||
opacity: 0.6,
|
||||
diffHeight: 300
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制圆锥
|
||||
const drawCylinder = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "cylinder",
|
||||
style: {
|
||||
fill: true,
|
||||
color: "#00ff00",
|
||||
opacity: 0.6,
|
||||
length: 1000
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制圆柱
|
||||
const drawExtrudedCircle = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "circle",
|
||||
style: {
|
||||
color: "#00ff00",
|
||||
opacity: 0.6,
|
||||
diffHeight: 300
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制盒子
|
||||
const drawBox = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "box",
|
||||
style: {
|
||||
color: "#00ff00",
|
||||
opacity: 0.6,
|
||||
dimensions_x: 1000.0,
|
||||
dimensions_y: 1000.0,
|
||||
dimensions_z: 1000.0
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制墙
|
||||
const draWall = (closure: boolean) => {
|
||||
graphicLayer.startDraw({
|
||||
type: "wall",
|
||||
style: {
|
||||
color: "#00ff00",
|
||||
opacity: 0.8,
|
||||
diffHeight: 400,
|
||||
closure: closure // 是否闭合
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制球
|
||||
const drawEllipsoid = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "ellipsoid",
|
||||
style: {
|
||||
fill: true,
|
||||
color: "#00ff00",
|
||||
opacity: 0.6
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制矩形
|
||||
const drawRectangle = (clampToGround: boolean) => {
|
||||
graphicLayer.startDraw({
|
||||
type: "rectangle",
|
||||
style: {
|
||||
color: clampToGround ? "#ffff00" : "#3388ff",
|
||||
opacity: 0.6,
|
||||
outline: true,
|
||||
outlineColor: "#ffffff",
|
||||
outlineWidth: 2.0,
|
||||
clampToGround: clampToGround
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制走廊
|
||||
const drawCorridor = (clampToGround: boolean) => {
|
||||
graphicLayer.startDraw({
|
||||
type: "corridor",
|
||||
style: {
|
||||
color: clampToGround ? "#ffff00" : "#3388ff",
|
||||
opacity: 0.6,
|
||||
width: 500,
|
||||
clampToGround: clampToGround
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制曲线
|
||||
const drawCurve = (clampToGround: boolean) => {
|
||||
graphicLayer.startDraw({
|
||||
type: "curve",
|
||||
style: {
|
||||
color: clampToGround ? "#ffff00" : "#3388ff",
|
||||
width: 3,
|
||||
clampToGround: clampToGround
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制平面
|
||||
const draPlane = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "plane",
|
||||
style: {
|
||||
color: "#00ff00",
|
||||
opacity: 0.8,
|
||||
plane_normal: "x",
|
||||
dimensions_x: 1000.0,
|
||||
dimensions_y: 1000.0
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制圆
|
||||
const drawEllipse = (clampToGround: boolean) => {
|
||||
graphicLayer.startDraw({
|
||||
type: "circle",
|
||||
style: {
|
||||
color: clampToGround ? "#ffff00" : "#3388ff",
|
||||
opacity: 0.6,
|
||||
outline: true,
|
||||
outlineColor: "#ffffff",
|
||||
outlineWidth: 2.0,
|
||||
clampToGround: clampToGround
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制面
|
||||
const drawPolygon = (clampToGround: boolean) => {
|
||||
// clampToGround 为true代表贴地,false为不贴地
|
||||
graphicLayer.startDraw({
|
||||
type: "polygon",
|
||||
style: {
|
||||
color: clampToGround ? "#ffff00" : "#3388ff",
|
||||
opacity: 0.5,
|
||||
outline: true,
|
||||
outlineColor: "#ffffff",
|
||||
outlineWidth: 2.0,
|
||||
clampToGround: clampToGround
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制自由线
|
||||
const drawBrushLine = (clampToGround: boolean) => {
|
||||
// clampToGround 为true代表贴地,false为不贴地
|
||||
graphicLayer.startDraw({
|
||||
type: "brushLine",
|
||||
style: {
|
||||
color: clampToGround ? "#ffff00" : "#3388ff",
|
||||
width: 3,
|
||||
clampToGround: clampToGround
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制线
|
||||
const drawPolyline = (clampToGround: boolean) => {
|
||||
// clampToGround 为true代表贴地,false为不贴地
|
||||
graphicLayer.startDraw({
|
||||
type: "polyline",
|
||||
style: {
|
||||
color: clampToGround ? "#ffff00" : "#3388ff",
|
||||
width: 3,
|
||||
clampToGround: clampToGround
|
||||
}
|
||||
// 外部自定义校验坐标,return false 时坐标无效,不参与绘制
|
||||
// validDrawPosition: function (position, graphic) {
|
||||
// const point = mars3d.LngLatPoint.fromCartesian(position)
|
||||
// return (point.lng > 115 && point.lng < 117)
|
||||
// }
|
||||
});
|
||||
};
|
||||
// 绘制小模型
|
||||
const onClickStartDarw = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "model",
|
||||
style: {
|
||||
scale: 10,
|
||||
url: "//data.mars3d.cn/gltf/mars/firedrill/xiaofangche.gltf"
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制图标点
|
||||
const drawMarker = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "billboard",
|
||||
style: {
|
||||
image: "src/assets/images/Mars3DImg/marker/mark-red.png",
|
||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
label: {
|
||||
// 不需要文字时,去掉label配置即可
|
||||
text: "可以同时支持文字",
|
||||
font_size: 26,
|
||||
color: "#ffffff",
|
||||
outline: true,
|
||||
outlineColor: "#000000",
|
||||
pixelOffsetY: -60
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制文字
|
||||
const drawLabel = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "label",
|
||||
style: {
|
||||
text: "火星科技三维地球",
|
||||
color: "#0081c2",
|
||||
font_size: 50,
|
||||
outline: true,
|
||||
outlineColor: "#ffffff",
|
||||
outlineWidth: 2
|
||||
}
|
||||
});
|
||||
};
|
||||
// 绘制点
|
||||
const drawPoint = () => {
|
||||
graphicLayer.startDraw({
|
||||
type: "point",
|
||||
style: {
|
||||
pixelSize: 12,
|
||||
color: "#3388ff",
|
||||
label: {
|
||||
// 不需要文字时,去掉label配置即可
|
||||
text: "可以同时支持文字",
|
||||
font_size: 20,
|
||||
color: "#ffffff",
|
||||
outline: true,
|
||||
outlineColor: "#000000",
|
||||
pixelOffsetY: -20
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
// 点击保存GeoJSON
|
||||
const onClickSaveJson = () => {
|
||||
if (graphicLayer.length === 0) {
|
||||
ElMessage("当前没有标注任何数据,无需保存!");
|
||||
return;
|
||||
}
|
||||
const geojson = graphicLayer.toGeoJSON();
|
||||
mars3d.Util.downloadFile("我的标注.json", JSON.stringify(geojson));
|
||||
};
|
||||
// 打开JSON文件
|
||||
const uploadFileChange = (response: any) => {
|
||||
const item = response.raw;
|
||||
const fileName = item.name;
|
||||
const fileType = fileName?.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase();
|
||||
try {
|
||||
if (fileType === "json" || fileType === "geojson") {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(item, "UTF-8");
|
||||
reader.onloadend = function (e) {
|
||||
const geojson = JSON.parse(this.result as string);
|
||||
console.log("打开了json文件", geojson);
|
||||
if (geojson.type === "graphic" && geojson.data) {
|
||||
graphicLayer.addGraphic(geojson.data);
|
||||
// graphicLayer.flyTo();
|
||||
} else {
|
||||
graphicLayer.loadGeoJSON(geojson, { flyTo: true });
|
||||
// initGraphicableData(graphicLayer)
|
||||
}
|
||||
};
|
||||
} else if (fileType === "kml") {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(item, "UTF-8");
|
||||
reader.onloadend = function (e) {
|
||||
const strkml = this.result;
|
||||
|
||||
map.kgUtil.toGeoJSON(strkml).then((geojson: any) => {
|
||||
console.log("kml2geojson转换结果为", geojson);
|
||||
|
||||
graphicLayer.loadGeoJSON(geojson, {
|
||||
flyTo: true
|
||||
});
|
||||
});
|
||||
};
|
||||
} else if (fileType === "kmz") {
|
||||
// 加载input文件控件的二进制流
|
||||
|
||||
map.kgUtil.toGeoJSON(item).then((geojson: any) => {
|
||||
console.log("kmz2geojson", geojson);
|
||||
|
||||
graphicLayer.loadGeoJSON(geojson, {
|
||||
flyTo: true
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ElMessage("暂不支持 " + fileType + " 文件类型的数据!");
|
||||
}
|
||||
importRef.value.clearFiles();
|
||||
} catch (error) {
|
||||
ElMessage("有相同数据");
|
||||
}
|
||||
};
|
||||
// 点击清除按钮
|
||||
const onClickClear = () => {
|
||||
graphicLayer.clear();
|
||||
};
|
||||
// 是否可编辑
|
||||
const onChangeHasEdit = () => {
|
||||
graphicLayer.hasEdit = btnOperate.value.check2;
|
||||
};
|
||||
// 是否绑定Popup
|
||||
const onChangePopup = () => {
|
||||
if (btnOperate.value.check1) {
|
||||
graphicLayer.bindPopup(function (event: any) {
|
||||
const attr = event.graphic.attr || {};
|
||||
attr["类型"] = event.graphic.type;
|
||||
attr["来源"] = "我是layer上绑定的Popup";
|
||||
attr["备注"] = "我支持鼠标交互";
|
||||
|
||||
return mars3d.Util.getTemplateHtml({ title: "矢量图层", template: "all", attr: attr });
|
||||
});
|
||||
} else {
|
||||
map.graphicLayer.unbindPopup();
|
||||
}
|
||||
};
|
||||
const closeDiv = () => {
|
||||
emits("hiddenConfim");
|
||||
};
|
||||
onUnmounted(() => {
|
||||
map = null;
|
||||
});
|
||||
</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;
|
||||
background-color: #173147;
|
||||
span {
|
||||
font-size: 16px;
|
||||
color: #0089fe;
|
||||
margin-right: auto;
|
||||
}
|
||||
:deep() {
|
||||
.el-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-classify {
|
||||
width: 95%;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&-item {
|
||||
display: flex;
|
||||
color: white;
|
||||
margin-bottom: 10px;
|
||||
> span {
|
||||
margin-right: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.operate-menu {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
:deep() {
|
||||
.el-input {
|
||||
width: 80%;
|
||||
}
|
||||
.el-checkbox {
|
||||
height: auto;
|
||||
}
|
||||
.el-checkbox__inner,
|
||||
.el-radio__inner {
|
||||
background-color: transparent;
|
||||
}
|
||||
.el-checkbox__label,
|
||||
.el-radio__label {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -73,7 +73,7 @@ onMounted(() => {
|
||||
bindLayerContextMenu(); // 在图层绑定右键菜单,对所有加到这个图层的矢量数据都生效
|
||||
});
|
||||
|
||||
// 打卡JSON文件
|
||||
// 打开JSON文件
|
||||
const uploadFileChange = (response: any) => {
|
||||
console.log(response);
|
||||
|
||||
|
||||
@ -89,11 +89,13 @@
|
||||
<!-- 我的标记弹框 -->
|
||||
<MyTags :mapInstance="map" v-if="myTagsShow" @hiddenConfim="myTagsShow = false" />
|
||||
<!-- 视角书签弹框 -->
|
||||
<ViewBookmark :mapInstance="map" v-if="ViewBookmarkShow" @hiddenConfim="ViewBookmarkShow = false" />
|
||||
<ViewBookmark :mapInstance="map" v-if="viewBookmarkShow" @hiddenConfim="viewBookmarkShow = false" />
|
||||
<!-- 地图打印弹框 -->
|
||||
<MapPrint :mapInstance="map" v-if="MapPrintShow" @hiddenConfim="MapPrintShow = false" />
|
||||
<MapPrint :mapInstance="map" v-if="mapPrintShow" @hiddenConfim="mapPrintShow = false" />
|
||||
<!-- 飞行漫游弹框 -->
|
||||
<FlyRoam :mapInstance="map" v-if="FlyRoamShow" @hiddenConfim="FlyRoamShow = false" />
|
||||
<FlyRoam :mapInstance="map" v-if="flyRoamShow" @hiddenConfim="flyRoamShow = false" />
|
||||
<!-- 图上标绘弹框 -->
|
||||
<MapMark :mapInstance="map" v-if="mapMarkShow" @hiddenConfim="mapMarkShow = false" />
|
||||
</div>
|
||||
|
||||
<!-- <div class="option-list">
|
||||
@ -206,9 +208,11 @@ import MyTags from "./components/myTags.vue";
|
||||
import ViewBookmark from "./components/viewBookmark.vue";
|
||||
import MapPrint from "./components/mapPrint.vue";
|
||||
import FlyRoam from "./components/flyRoam.vue";
|
||||
const FlyRoamShow = ref(false); // 飞行漫游弹框
|
||||
const MapPrintShow = ref(false); // 地图打印弹框
|
||||
const ViewBookmarkShow = ref(false); // 视角书签弹框
|
||||
import MapMark from "./components/mapMark.vue";
|
||||
const mapMarkShow = ref(false); // 图上标绘弹框
|
||||
const flyRoamShow = ref(false); // 飞行漫游弹框
|
||||
const mapPrintShow = ref(false); // 地图打印弹框
|
||||
const viewBookmarkShow = ref(false); // 视角书签弹框
|
||||
const myTagsShow = ref(false); // 我的标记弹框
|
||||
const regionalNavigationShow = ref(false); // 地区导航弹框
|
||||
const pickingShow = ref(false); // 坐标定位弹框
|
||||
@ -333,7 +337,7 @@ const data = [
|
||||
{ name: "视角书签", icon: "bookmark", widget: "bookmark" },
|
||||
{ name: "地图打印", icon: "printer", widget: "print" },
|
||||
{ name: "飞行漫游", icon: "take-off", widget: "roamLine-list" },
|
||||
// { name: "图上标绘", icon: "hand-painted-plate", widget: "plot" },
|
||||
{ name: "图上标绘", icon: "hand-painted-plate", widget: "plot" },
|
||||
// { name: "路线导航", icon: "connection", widget: "query-route" },
|
||||
// { name: "卷帘对比", icon: "switch-contrast", widget: "map-split" },
|
||||
// { name: "分屏对比", icon: "full-screen-play", widget: "map-compare" }
|
||||
@ -373,11 +377,13 @@ const clickMenu = (name: any) => {
|
||||
} else if (name == "我的标记") {
|
||||
myTagsShow.value = true;
|
||||
} else if (name == "视角书签") {
|
||||
ViewBookmarkShow.value = true;
|
||||
viewBookmarkShow.value = true;
|
||||
} else if (name == "地图打印") {
|
||||
MapPrintShow.value = true;
|
||||
mapPrintShow.value = true;
|
||||
} else if (name == "飞行漫游") {
|
||||
FlyRoamShow.value = true;
|
||||
flyRoamShow.value = true;
|
||||
} else if(name == "图上标绘"){
|
||||
mapMarkShow.value = true;
|
||||
}
|
||||
};
|
||||
// 获取Canvas对象
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user