1457 lines
39 KiB
Vue
Raw Normal View History

2023-10-10 09:31:35 +08:00
<template>
<layoutTop></layoutTop>
<div class="map-content">
<div id="mars3dContainer" class="mars3d-container"></div>
2023-10-16 19:09:06 +08:00
<!-- 搜索框 -->
<div class="input-search">
2023-10-16 19:09:06 +08:00
<el-input v-model="inputVal" @blur="closeSearch" clearable @focus="showHistoryList" @input="searchInput">
<template #append>
2023-10-16 19:09:06 +08:00
<el-icon size="18" @click="searchInput"><Search /></el-icon> </template
></el-input>
2023-10-16 19:09:06 +08:00
<div class="search-list" v-if="searchListShow && dataSource.length > 0">
<div v-for="(item, i) in dataSource" :key="i" class="search-list-item" @click="selectPoint(item)">
{{ item.value }}
</div>
</div>
</div>
<!-- 菜单操作 -->
<div class="menu-operate">
<div class="menu-operate-item" v-for="(item, i) in data" :key="i">
2023-10-17 18:34:40 +08:00
<div v-if="item.widget && !item.children" class="toolbar-item" @click="showWidget(item.name)">
2023-10-16 19:09:06 +08:00
<el-icon size="18" color="#fff" v-if="i == 0"><PictureRounded /></el-icon>
<el-icon size="18" color="#fff" v-else-if="i == 1"><DocumentCopy /></el-icon>
<span class="title">{{ item.name }}</span>
</div>
<el-dropdown v-if="item.children && !item.widget" trigger="click">
<div class="toolbar-item">
<el-icon size="18" color="#fff"><Operation /></el-icon>
<span class="title">{{ item.name }}</span>
<el-icon size="14" color="#fff"><ArrowDown /></el-icon>
</div>
<template #dropdown>
<el-dropdown-menu class="dropdown">
2023-10-17 18:34:40 +08:00
<el-dropdown-item v-for="child in item.children" :key="child.name" @click="clickMenu(child.name)"
><el-icon size="16"><PictureRounded /></el-icon> <span>{{ child.name }}</span></el-dropdown-item
2023-10-16 19:09:06 +08:00
>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
2023-10-17 18:34:40 +08:00
<!-- 底图菜单操作页面 -->
<div class="basic-map" v-if="basicMapShow">
<div class="basic-title">
<span>底图</span>
<el-icon size="16" color="#fff" @click="basicMapShow = false"><Close /></el-icon>
</div>
<div class="basemap">
<div
v-for="(item, i) in baseMaps"
:key="i"
class="basemap-card"
:class="{ 'active-card': active === item.id }"
@click="changeBaseMaps(item.id)"
>
<div><img class="icon" :src="`${item.options.icon || 'src/assets/images/Mars3DImg/basemaps/bingAerial.png'}`" /></div>
<div>{{ item.name }}</div>
</div>
</div>
<div class="terrain-show">
<span>显示地形</span>
<el-switch v-model="chkHasTerrain" @change="terrainOperate" />
</div>
</div>
<!-- 图层添加 -->
<div class="layer-add" v-if="layersShow">
<div class="layer-add-title">
<span>图层</span>
<el-icon size="16" color="#fff" @click="layersShow = false"><Close /></el-icon>
</div>
<div class="layer-add-tree">
<el-tree
:default-expanded-keys="expandedKeys"
:default-checked-keys="checkedKeys"
:data="treeData"
:props="props"
show-checkbox
@check-change="handleCheckChange"
/>
</div>
</div>
<!-- 图上量算弹框 -->
<MapMeasurement :mapInstance="map" v-if="measurementShow" @hiddenConfim="measurementShow = false" />
2023-10-18 18:35:30 +08:00
<!-- 空间分析弹框 -->
2023-10-19 18:29:15 +08:00
<SpaceAnalysis :mapInstance="map" v-if="analysisShow" @hiddenConfim="analysisShow = false" />
<!-- 坐标定位弹框 -->
<CoordinatePicking :mapInstance="map" v-if="pickingShow" @hiddenConfim="pickingShow = false" />
<!-- 地区导航弹框 -->
<RegionalNavigation :mapInstance="map" v-if="regionalNavigationShow" @hiddenConfim="regionalNavigationShow = false" />
<!-- 我的标记弹框 -->
<MyTags :mapInstance="map" v-if="myTagsShow" @hiddenConfim="myTagsShow = false" />
2023-10-20 18:32:09 +08:00
<!-- 视角书签弹框 -->
2023-10-21 18:24:25 +08:00
<ViewBookmark :mapInstance="map" v-if="viewBookmarkShow" @hiddenConfim="viewBookmarkShow = false" />
2023-10-20 18:32:09 +08:00
<!-- 地图打印弹框 -->
2023-10-21 18:24:25 +08:00
<MapPrint :mapInstance="map" v-if="mapPrintShow" @hiddenConfim="mapPrintShow = false" />
2023-10-20 18:32:09 +08:00
<!-- 飞行漫游弹框 -->
2023-10-21 18:24:25 +08:00
<FlyRoam :mapInstance="map" v-if="flyRoamShow" @hiddenConfim="flyRoamShow = false" />
<!-- 图上标绘弹框 -->
<MapMark :mapInstance="map" v-if="mapMarkShow" @hiddenConfim="mapMarkShow = false" />
</div>
2023-10-17 18:34:40 +08:00
<!-- <div class="option-list">
2023-10-12 18:45:45 +08:00
<span class="option-list-title">功能选择</span>
<el-scrollbar style="margin-top: 10px" :style="{ height: title ? `calc(100% - 95px)` : `calc(100% - 56px)` }">
<div class="option-list-item">
<span>雨天气</span>
<div class="item-classify">
<div class="item-classify-item">
<span>是否开启</span>
<el-switch v-model="yuProperty.enabled" @change="e => yuOperate(e, 'enabled')" />
</div>
<div class="item-classify-item">
<span>粒子速度</span>
<el-slider v-model="yuProperty.speed" @change="e => yuOperate(e, 'speed')" />
</div>
<div class="item-classify-item">
<span>粒子大小</span>
<el-slider v-model="yuProperty.size" @change="e => yuOperate(e, 'size')" />
</div>
<div class="item-classify-item">
<span>粒子方向</span>
<el-slider v-model="yuProperty.direction" @change="e => yuOperate(e, 'direction')" />
</div>
</div>
</div>
<div class="option-list-item">
<span>雾天气</span>
<div class="item-classify">
<div class="item-classify-item">
<span>是否开启</span>
<el-switch v-model="wuProperty.enabled" @change="e => wuOperate(e, 'enabled')" />
</div>
<div class="item-classify-item">
<span>雾颜色</span>
<el-color-picker v-model="wuProperty.color" @change="e => wuOperate(e, 'color')" />
</div>
<div class="item-classify-item">
<span>近距离</span>
<el-slider v-model="wuProperty.fogByDistanceX" @change="e => wuOperate(e, 'fogByDistanceX')" />
</div>
<div class="item-classify-item">
<span>远距离</span>
<el-slider v-model="wuProperty.fogByDistanceZ" @change="e => wuOperate(e, 'fogByDistanceZ')" />
</div>
</div>
</div>
<div class="option-list-item">
<span>雪天气</span>
<div class="item-classify">
<div class="item-classify-item">
<span>是否开启</span>
<el-switch v-model="xueProperty.enabledSnow" @change="e => xueOperate(e, 'enabled')" />
</div>
<div class="item-classify-item">
<span>下雪速度</span>
<el-slider v-model="xueProperty.speed" @change="e => xueOperate(e, 'speed')" />
</div>
</div>
</div>
<div class="option-list-item">
<span>积雪效果</span>
<div class="item-classify">
<div class="item-classify-item">
<span>是否开启</span>
<el-switch v-model="xueProperty.enabledCover" @change="e => jxOperate(e, 'enabled')" />
</div>
<div class="item-classify-item">
<span>积雪程度</span>
<el-slider v-model="xueProperty.alpha" :step="0.1" :max="1" @change="e => jxOperate(e, 'alpha')" />
</div>
</div>
</div>
2023-10-13 15:23:55 +08:00
<div class="option-list-item">
<span>近地天空盒</span>
<div class="item-classify">
<div class="item-classify-item">
<el-radio-group v-model="skyProperty.boxVal" size="small" style="margin-top: 10px" @change="boxChange">
<el-radio-button :label="1" border>晴天</el-radio-button>
<el-radio-button :label="2" border>晚霞</el-radio-button>
<el-radio-button :label="3" border>蓝天</el-radio-button>
<el-radio-button :label="4" border>默认</el-radio-button>
</el-radio-group>
</div>
</div>
</div>
2023-10-12 18:45:45 +08:00
</el-scrollbar>
</div> -->
2023-10-10 09:31:35 +08:00
</template>
<script lang="ts" setup>
2023-10-17 18:34:40 +08:00
import { ref, onMounted, onUnmounted, computed, markRaw } from "vue";
2023-10-12 18:45:45 +08:00
//引入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 ConfigJson from "@/views/goverment/largeScreen/config.json";
import layoutTop from "@/components/layoutTop/index.vue";
2023-10-16 19:09:06 +08:00
import { ElMessage } from "element-plus";
import { datas } from "@/enums/company/SetpsEnum";
import { initVue3Popup } from "@/utils/file-util";
import QueryPopup from "./components/query-popup.vue";
2023-10-17 18:34:40 +08:00
import MapMeasurement from "./components/mapMeasurement.vue";
2023-10-18 18:35:30 +08:00
import SpaceAnalysis from "./components/spaceAnalysis.vue";
2023-10-19 18:29:15 +08:00
import CoordinatePicking from "./components/coordinatePicking.vue";
import RegionalNavigation from "./components/regionalNavigation.vue";
import MyTags from "./components/myTags.vue";
2023-10-20 18:32:09 +08:00
import ViewBookmark from "./components/viewBookmark.vue";
import MapPrint from "./components/mapPrint.vue";
import FlyRoam from "./components/flyRoam.vue";
2023-10-21 18:24:25 +08:00
import MapMark from "./components/mapMark.vue";
const mapMarkShow = ref(false); // 图上标绘弹框
const flyRoamShow = ref(false); // 飞行漫游弹框
const mapPrintShow = ref(false); // 地图打印弹框
const viewBookmarkShow = ref(false); // 视角书签弹框
2023-10-19 18:29:15 +08:00
const myTagsShow = ref(false); // 我的标记弹框
const regionalNavigationShow = ref(false); // 地区导航弹框
const pickingShow = ref(false); // 坐标定位弹框
2023-10-18 18:35:30 +08:00
const analysisShow = ref(false); // 空间分析弹框
2023-10-17 18:34:40 +08:00
const measurementShow = ref(false); // 图上量算弹框
const layersShow = ref(false); // 图层弹框
const basicMapShow = ref(false); // 底图弹框
const chkHasTerrain = ref(false);
const active = ref("");
const baseMaps = ref([]);
2023-10-16 19:09:06 +08:00
const storageName = "mars3d_queryGaodePOI";
const inputVal = ref();
const dataSource = ref<any>([]);
const searchListShow = ref(false);
2023-10-12 18:45:45 +08:00
const title = ref("");
const yuProperty = ref({
enabled: false,
speed: 10,
size: 20,
direction: 10
});
const wuProperty = ref({
enabled: false,
color: "#ffffff",
fogByDistanceX: 100,
fogByDistanceZ: 9000
});
const xueProperty = ref({
enabledSnow: false,
enabledCover: false,
speed: 20,
alpha: 0.6
});
const sunProperty = ref({
timeVal: null,
currDate: 420
});
2023-10-13 15:23:55 +08:00
const skyProperty = ref({
boxVal: 4
});
2023-10-12 18:45:45 +08:00
const checkedKeys = ref<any[]>([]);
const expandedKeys = ref<any>([]);
const layersObj: any = {};
const treeData = ref<any>([]);
const props = {
label: "title",
children: "children"
2023-10-10 09:31:35 +08:00
};
2023-10-12 18:45:45 +08:00
const hours = computed(() => Math.floor(sunProperty.value.currDate / 60));
const minutes = computed(() => Math.floor(sunProperty.value.currDate / 60));
2023-10-16 19:09:06 +08:00
let map: any;
let queryPoi: any; // GaodePOI
let address: any = ""; // 选中的地址
let rainEffect: any; // 雨天气
let fogEffect: any; // 雾天气
let snowEffect: any; // 雪天气
let snowCover: any; // 积雪
let currSkyBox: any; // 当前生效的Skybox
let defaultSkybox: any; // cesium自带的Skybox
let graphicLayer: any; // 覆盖物
let imgArr = [] as any; // canvas 图标数组
let timer: any; // 延时器
2023-10-12 18:45:45 +08:00
onMounted(async () => {
// const configUrl = "http://182.90.224.147:6080/file/config/config.json";
// const configUrl = "../config.json";
// mars3d.Util.fetchJson({ url: configUrl }).then(data => {
// console.log(data);
// initMars3d(data.map3d);
// });
2023-10-16 19:09:06 +08:00
for (let i = 0; i < 6; i++) {
const img = await getCanvas(i + 1);
imgArr.push(img);
}
2023-10-12 18:45:45 +08:00
await initMars3d(ConfigJson.map3d);
await initTree();
});
2023-10-13 15:23:55 +08:00
const qingtianSkybox = new mars3d.GroundSkyBox({
// 晴天天空盒
sources: {
positiveX: new URL("@/assets/images/skybox_near/qingtian/rightav9.jpg", import.meta.url).href,
negativeX: new URL("@/assets/images/skybox_near/qingtian/leftav9.jpg", import.meta.url).href,
positiveY: new URL("@/assets/images/skybox_near/qingtian/frontav9.jpg", import.meta.url).href,
negativeY: new URL("@/assets/images/skybox_near/qingtian/backav9.jpg", import.meta.url).href,
positiveZ: new URL("@/assets/images/skybox_near/qingtian/topav9.jpg", import.meta.url).href,
negativeZ: new URL("@/assets/images/skybox_near/qingtian/bottomav9.jpg", import.meta.url).href
}
});
const wanxiaSkybox = new mars3d.GroundSkyBox({
// 晚霞天空盒
sources: {
positiveX: new URL("@/assets/images/skybox_near/wanxia/SunSetRight.png", import.meta.url).href,
negativeX: new URL("@/assets/images/skybox_near/wanxia/SunSetLeft.png", import.meta.url).href,
positiveY: new URL("@/assets/images/skybox_near/wanxia/SunSetFront.png", import.meta.url).href,
negativeY: new URL("@/assets/images/skybox_near/wanxia/SunSetBack.png", import.meta.url).href,
positiveZ: new URL("@/assets/images/skybox_near/wanxia/SunSetUp.png", import.meta.url).href,
negativeZ: new URL("@/assets/images/skybox_near/wanxia/SunSetDown.png", import.meta.url).href
}
});
const lantianSkybox = new mars3d.GroundSkyBox({
// 晴天天空盒
sources: {
positiveX: new URL("@/assets/images/skybox_near/lantian/Right.jpg", import.meta.url).href,
negativeX: new URL("@/assets/images/skybox_near/lantian/Left.jpg", import.meta.url).href,
positiveY: new URL("@/assets/images/skybox_near/lantian/Front.jpg", import.meta.url).href,
negativeY: new URL("@/assets/images/skybox_near/lantian/Back.jpg", import.meta.url).href,
positiveZ: new URL("@/assets/images/skybox_near/lantian/Up.jpg", import.meta.url).href,
negativeZ: new URL("@/assets/images/skybox_near/lantian/Down.jpg", import.meta.url).href
}
});
2023-10-16 19:09:06 +08:00
const data = [
{ name: "底图", icon: "PictureRounded", widget: "manage-basemap" },
{ name: "图层", icon: "PictureRounded", widget: "manage-layers" },
{
name: "工具",
icon: "tool",
children: [
2023-10-17 18:34:40 +08:00
{ name: "图上量算", icon: "ruler", widget: "measure" },
2023-10-19 18:29:15 +08:00
{ name: "空间分析", icon: "analysis", widget: "analysis" },
{ name: "坐标定位", icon: "local", widget: "location-point" },
{ name: "地区导航", icon: "navigation", widget: "location-region" },
2023-10-20 18:32:09 +08:00
{ name: "我的标记", icon: "mark", widget: "addmarker" },
{ name: "视角书签", icon: "bookmark", widget: "bookmark" },
{ name: "地图打印", icon: "printer", widget: "print" },
{ name: "飞行漫游", icon: "take-off", widget: "roamLine-list" },
2023-10-21 18:24:25 +08:00
{ name: "图上标绘", icon: "hand-painted-plate", widget: "plot" },
2023-10-16 19:09:06 +08:00
// { name: "路线导航", icon: "connection", widget: "query-route" },
// { name: "卷帘对比", icon: "switch-contrast", widget: "map-split" },
// { name: "分屏对比", icon: "full-screen-play", widget: "map-compare" }
// { name: "百度街景", icon: h(City, { theme: "outline", size: "18" }), widget: "street-view" }
]
}
];
2023-10-17 18:34:40 +08:00
// 显示地形
const terrainOperate = (e: any) => {
map.hasTerrain = chkHasTerrain.value;
};
// 改变底图
const changeBaseMaps = (id: string) => {
map.basemap = active.value = id;
};
const showWidget = (name: string) => {
if (name == "底图") {
basicMapShow.value = true;
layersShow.value = false;
} else if (name == "图层") {
basicMapShow.value = false;
layersShow.value = true;
}
2023-10-16 19:09:06 +08:00
console.log(666);
};
2023-10-17 18:34:40 +08:00
const clickMenu = (name: any) => {
console.log(name);
if (name == "图上量算") {
measurementShow.value = true;
2023-10-18 18:35:30 +08:00
} else if (name == "空间分析") {
analysisShow.value = true;
2023-10-19 18:29:15 +08:00
} else if (name == "坐标定位") {
pickingShow.value = true;
} else if (name == "地区导航") {
regionalNavigationShow.value = true;
} else if (name == "我的标记") {
myTagsShow.value = true;
2023-10-20 18:32:09 +08:00
} else if (name == "视角书签") {
2023-10-21 18:24:25 +08:00
viewBookmarkShow.value = true;
2023-10-20 18:32:09 +08:00
} else if (name == "地图打印") {
2023-10-21 18:24:25 +08:00
mapPrintShow.value = true;
2023-10-20 18:32:09 +08:00
} else if (name == "飞行漫游") {
2023-10-21 18:24:25 +08:00
flyRoamShow.value = true;
} else if(name == "图上标绘"){
mapMarkShow.value = true;
2023-10-17 18:34:40 +08:00
}
2023-10-16 19:09:06 +08:00
};
// 获取Canvas对象
const getCanvas = (text: any) => {
return new Promise(resolve => {
const img = new Image(19, 25);
img.crossOrigin = "Anonymous";
img.src = "src/assets/images/Mars3DImg/poi/indexMark.png";
img.onload = () => {
const canvas = document.createElement("canvas");
canvas.width = 19;
canvas.height = 25;
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制图片
ctx.drawImage(img, 0, 0);
// 绘制文字
ctx.fillStyle = "#ffffff";
ctx.font = "22px 楷体";
ctx.textBaseline = "middle";
ctx.fillText(text, 4, 10);
// 将图片赋予给矢量对象进行显示this.image是父类的属性
resolve(canvas.toDataURL("image/png"));
};
});
};
// 相机切换,定位点切换
const cameraChanged = () => {
queryPoi.getAddress({
location: map.getCenter(),
success: (result: any) => {
address = result;
}
});
};
// 将需要搜查的关键字记录进历史数据中
const addHistory = (data: any) => {
try {
const arrHistory = JSON.parse(localStorage.getItem(storageName)!) || [];
let isExist = false;
isExist = arrHistory.some((item: any) => item.id == data.id);
if (!isExist) {
arrHistory.unshift(data);
}
// if (!arrHistory.includes(data)) {
// arrHistory.unshift(data);
// }
localStorage.setItem(storageName, JSON.stringify(arrHistory.slice(0, 10)));
} catch (err: any) {
throw new Error(err);
}
};
// 开始查询并加载数据
const selectPoint = async (item: any) => {
inputVal.value = item.value;
addHistory(item);
searchListShow.value = false;
showPOIArr([item] || []);
};
const showPOIArr = (arr: any) => {
graphicLayer.closePopup();
graphicLayer.clear();
arr.forEach(async (item: any, index: number) => {
const jd = Number(item.lng);
const wd = Number(item.lat);
if (isNaN(jd) || isNaN(wd)) {
return;
}
item.lng = jd;
item.lat = wd;
// 添加图标实体
const graphic = new mars3d.graphic.BillboardEntity({
position: Cesium.Cartesian3.fromDegrees(jd, wd),
style: {
pixelSize: 10,
color: "#ffffff",
outline: true,
outlineColor: "#ffffff",
outlineWidth: 2,
scaleByDistance: new Cesium.NearFarScalar(1000, 1, 1000000, 0.1),
clampToGround: true, // 贴地
visibleDepth: false, // 是否被遮挡
label: {
text: item.name,
font_size: 20,
color: "#ffffff",
outline: true,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffsetY: -10, // 偏移量
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 200000),
clampToGround: true, // 贴地
visibleDepth: false // 是否被遮挡
},
image: imgArr[index]
},
attr: item
});
graphicLayer.addGraphic(graphic);
item._graphic = graphic;
});
if (arr.length > 0) {
graphicLayer.flyTo({ radius: 5000, pitch: -90 });
}
};
// 输入框输入值时
const searchInput = async () => {
if (!inputVal.value) {
showHistoryList();
graphicLayer.closePopup();
graphicLayer.clear();
return;
}
if (inputVal.value) {
let result: any;
result = await queryPoi.queryText({
text: inputVal.value,
// city: address?.city,
page: 1,
count: 10
});
if (!result || !result.list || result.list.length <= 0) {
ElMessage("暂无数据");
return;
}
// const result = await queryPoi.autoTip({
// text: inputVal.value,
// city: address?.city,
// location: map.getCenter()
// });
const list = [] as any;
result.list.forEach((item: any) => {
if (list.every(l => l.value !== item.name)) {
list.push({
...item,
value: item.name
});
}
});
dataSource.value = list;
searchListShow.value = true;
}
};
// 输入框获取焦点时,先展示历史记录
const showHistoryList = () => {
if (inputVal.value) {
return;
}
const history = JSON.parse(localStorage.getItem(storageName)!);
if (history) {
// dataSource.value = (history || []).map((item: any) => ({ ...item, value: item }));
dataSource.value = history || [];
searchListShow.value = true;
}
if (timer) {
clearTimeout(timer);
}
};
// 输入框失去焦点时
const closeSearch = () => {
timer = setTimeout(function () {
searchListShow.value = false;
clearTimeout(timer);
timer = null;
}, 500); // 时间太短会导致点击获取失效
};
2023-10-12 18:45:45 +08:00
const initMars3d = (option: any) => {
map = new mars3d.Map("mars3dContainer", option);
2023-10-13 15:23:55 +08:00
// 加载石化工厂模型
2023-10-16 19:09:06 +08:00
// const tiles3dLayer = new mars3d.layer.TilesetLayer({
// name: "石油化工厂",
// url: "http://data.mars3d.cn/3dtiles/max-shihua/tileset.json",
// position: { lng: 117.077158, lat: 31.659116, alt: -2.0 },
// maximumScreenSpaceError: 1,
// popup: "all"
// });
// map.addLayer(tiles3dLayer);
// tiles3dLayer.flyTo();
// 创建查询api
queryPoi = new mars3d.query.GaodePOI({
key: ["ad31e514e7e740179d6d8f182720bcf5"]
// city: '深圳市',
});
map.on(mars3d.EventType.cameraChanged, cameraChanged);
// 创建覆盖物数据图层
graphicLayer = new mars3d.layer.GraphicLayer({
name: "POI查询",
pid: 99 // 图层父级ID一般图层管理中使用
});
graphicLayer.bindPopup((event: any) => {
const attr = event.graphic.attr || {};
if (!attr) {
return;
}
const dom = initVue3Popup(QueryPopup, attr);
return dom;
2023-10-13 15:23:55 +08:00
});
map.addLayer(graphicLayer);
2023-10-17 18:34:40 +08:00
// 获取配置文件底图数据
getBasicMaps();
2023-10-13 15:23:55 +08:00
// 添加数据
2023-10-16 19:09:06 +08:00
// addRandomGraphicByCount(graphicLayer, [117.080397, 31.656139, 33.3]);
// addRandomGraphicByCount(graphicLayer, [117.078006, 31.65649, 49.4]);
// addRandomGraphicByCount(graphicLayer, [117.080571, 31.657898, 50.2]);
// addRandomGraphicByCount(graphicLayer, [117.078331, 31.660016, 47.2]);
2023-10-12 18:45:45 +08:00
// map.scene.moon.show = true; // 太阳
// map.scene.sun.show = true; // 月亮
2023-10-13 15:23:55 +08:00
// rainEffect = new mars3d.effect.RainEffect({
// speed: 10,
// size: 20,
// direction: 10,
// enabled: false
// });
// fogEffect = new mars3d.effect.FogEffect({
// color: Cesium.Color.WHITE,
// fogByDistance: new Cesium.Cartesian4(100, 0.0, 9000, 0.9),
// enabled: false
// });
// snowEffect = new mars3d.effect.SnowEffect({
// enabled: false,
// speed: 10
// });
// snowCover = new mars3d.effect.SnowCoverEffect({
// enabled: false,
// // layer: tiles3dLayer, // 如果传值3dtiles图层只对该模型生效
// alpha: 0.6,
// maxHeight: 8000 // 大于此高度后不显示
// });
// defaultSkybox = map.scene.skyBox;
// currSkyBox = qingtianSkybox;
// map.on(mars3d.EventType.postRender, function () {
// const position = map.camera.position;
// const height = Cesium.Cartographic.fromCartesian(position).height;
// if (height < 230000) {
// if (currSkyBox) {
// map.scene.skyBox = currSkyBox;
// }
// map.scene.skyAtmosphere.show = false;
// } else {
// if (defaultSkybox) {
// map.scene.skyBox = defaultSkybox;
// }
// map.scene.skyAtmosphere.show = true;
// }
// });
// map.addEffect(rainEffect);
// map.addEffect(fogEffect);
// map.addEffect(snowEffect);
// map.addEffect(snowCover);
};
2023-10-17 18:34:40 +08:00
// 获取config.json中的底图配置
const getBasicMaps = () => {
const layers = {
baseMaps: map.getBasemaps(true),
hasTerrain: map.hasTerrain
};
console.log(layers.baseMaps);
baseMaps.value = layers.baseMaps.map((m: any) => {
if (m.isAdded && m.show) {
active.value = m.id;
}
return {
name: m.name,
id: m.id,
options: markRaw(m.options)
};
});
chkHasTerrain.value = layers.hasTerrain || false;
};
2023-10-13 15:23:55 +08:00
const addRandomGraphicByCount = (graphicLayer: any, position: any) => {
const graphicImg = new mars3d.graphic.DivGraphic({
position: position,
style: {
2023-10-16 19:09:06 +08:00
html: ` <div class="mars3d-camera-content">
2023-10-13 15:23:55 +08:00
<img class="mars3d-camera-img" src="src/assets/images/icon/camera.svg" >
</div>
<div class="mars3d-camera-line" ></div>
<div class="mars3d-camera-point"></div>
`,
offsetX: -16,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 100000)
},
popup: `<video src='http://data.mars3d.cn/file/video/lukou.mp4' controls autoplay style="width: 300px;" ></video>`,
popupOptions: {
offsetY: -170, // 显示Popup的偏移值,是DivGraphic本身的像素高度值
template: `<div class="marsBlackPanel animation-spaceInDown">
<div class="marsBlackPanel-text">{content}</div>
<span class="mars3d-popup-close-button closeButton" >×</span>
</div>`,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.CENTER
}
2023-10-12 18:45:45 +08:00
});
2023-10-13 15:23:55 +08:00
graphicLayer.addGraphic(graphicImg);
2023-10-12 18:45:45 +08:00
};
const handleCheckChange = (e: any, isCheck: any) => {
const layer = layersObj[e.key];
if (layer) {
if (!layer.isAdded) {
map.addLayer(layer);
}
// 处理子节点
if (e.children && e.children.length) {
renderChildNode(isCheck, e.children);
}
if (isCheck) {
layer.show = true;
layer.flyTo();
} else {
layer.show = false;
}
2023-10-10 09:31:35 +08:00
}
};
2023-10-12 18:45:45 +08:00
const renderChildNode = (isCheck: any, children: any[]) => {
children.forEach(child => {
const layer = layersObj[child.key];
if (layer) {
if (!layer.isAdded) {
map.addLayer(layer);
}
if (isCheck) {
layer.show = true;
} else {
layer.show = false;
}
if (child.children) {
renderChildNode(isCheck, child.children);
}
}
});
};
// 初始化树结构
const initTree = () => {
const layers = map.getLayers({
basemaps: true, // 是否取config.json中的basempas
layers: true // 是否取config.json中的layers
});
// 遍历出config.json中所有的basempas和layers
for (let i = layers.length - 1; i >= 0; i--) {
const layer = layers[i];
if (layer && layer.pid === -1) {
const node: any = {
title: layer.name,
key: layer.id,
id: layer.id,
pId: layer.pid,
group: layer.type === "group"
};
node.children = findChild(node, layers);
treeData.value.push(node);
layersObj[layer.id] = layer;
expandedKeys.value.push(node.key);
}
2023-10-10 09:31:35 +08:00
}
2023-10-12 18:45:45 +08:00
};
const findChild = (parent: any, list: any[]) => {
return list
.filter((item: any) => item.pid === parent.id)
.map((item: any) => {
const node: any = {
title: item.name,
key: item.id,
id: item.id,
pId: item.pid,
group: item.type === "group"
};
layersObj[item.id] = item;
expandedKeys.value.push(node.key);
if (item.hasEmptyGroup || item.hasChildLayer) {
node.children = findChild(node, list);
}
if (item.isAdded && item.show) {
checkedKeys.value.push(node.key);
}
return node;
});
};
// 雨天气操作
const yuOperate = (e: any, label: any) => {
console.log(e, label);
rainEffect[label] = e;
};
// 雾天气操作
const wuOperate = (e: any, label: any) => {
console.log(e, label);
switch (label) {
case "enabled":
fogEffect[label] = e;
break;
case "color":
fogEffect.color = Cesium.Color.fromCssColorString(e);
break;
case "fogByDistanceX":
fogEffect.fogByDistance.x = e;
break;
case "fogByDistanceZ":
fogEffect.fogByDistance.z = e;
break;
}
};
// 雪天气操作
const xueOperate = (e: any, label: any) => {
console.log(e, label);
snowEffect[label] = e;
};
// 积雪操作
const jxOperate = (e: any, label: any) => {
console.log(e, label);
snowCover[label] = e;
};
2023-10-13 15:23:55 +08:00
// 天空盒操作
const boxChange = (e: any) => {
switch (e) {
case 1:
currSkyBox = qingtianSkybox;
break;
case 2:
currSkyBox = wanxiaSkybox;
break;
case 3:
currSkyBox = lantianSkybox;
break;
case 4:
currSkyBox = defaultSkybox;
break;
}
};
2023-10-16 19:09:06 +08:00
onUnmounted(() => {
map.removeLayer(graphicLayer);
map.off(mars3d.EventType.cameraChanged, cameraChanged);
queryPoi = null;
address = null;
map = null;
});
2023-10-10 09:31:35 +08:00
</script>
<style lang="scss" scoped>
2023-10-17 18:34:40 +08:00
@mixin flex {
display: flex;
align-items: center;
}
.map-content {
height: calc(100% - 72px);
2023-10-12 18:45:45 +08:00
width: 100%;
position: relative;
2023-10-16 19:09:06 +08:00
background-color: #ccc;
2023-10-17 18:34:40 +08:00
overflow: hidden;
.mars3d-container {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
border: none;
overflow: hidden;
}
.input-search {
2023-10-16 19:09:06 +08:00
width: 260px;
position: absolute;
top: 10px;
left: 10px;
2023-10-16 19:09:06 +08:00
box-shadow: 0 4px 15px 1px #02213bb3;
:deep() {
.el-input {
border: 1px solid rgba(0, 138, 255, 0.9);
}
.el-input__wrapper {
box-shadow: none;
background-color: rgba(23, 49, 71, 0.8);
}
.el-input__inner {
color: white;
}
.el-input-group__append {
box-shadow: none;
border: none;
background-color: rgba(0, 138, 255, 0.5);
}
}
.search-list {
width: 100%;
height: max-content;
background-color: rgba(23, 49, 71, 0.8);
border: 1px solid rgba(0, 138, 255, 0.9);
position: absolute;
top: 32px;
left: 0;
&-item {
width: 100%;
height: 40px;
line-height: 40px;
text-indent: 0.5em;
color: white;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
&-item:hover {
background-color: rgba(0, 138, 255, 0.5);
}
}
}
.menu-operate {
2023-10-17 18:34:40 +08:00
@include flex;
2023-10-16 19:09:06 +08:00
position: absolute;
top: 10px;
right: 10px;
padding: 0 !important;
background-image: none !important;
border: 1px solid #008aff70;
border-radius: 2px !important;
background-color: rgba(23, 49, 71, 0.8);
height: 40px;
box-shadow: 0 4px 15px 1px #02213bb3;
&-item {
.toolbar-item {
2023-10-17 18:34:40 +08:00
@include flex;
2023-10-16 19:09:06 +08:00
padding: 6px 12px;
height: 100%;
font-size: 15px;
2023-10-17 18:34:40 +08:00
cursor: pointer;
2023-10-16 19:09:06 +08:00
.title {
color: white;
margin-left: 5px;
}
&:hover {
background-color: rgba(0, 138, 255, 0.5);
}
}
}
}
2023-10-17 18:34:40 +08:00
// 菜单弹框出现动画
@keyframes fadeIn {
0% {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
100% {
opacity: 1;
transform: none;
}
}
.basic-map {
position: absolute;
top: 60px;
right: 10px;
padding: 0 !important;
background-image: none !important;
border: 1px solid #008aff70;
border-radius: 2px !important;
background-color: rgba(23, 49, 71, 0.8);
width: 380px;
height: 500px;
box-shadow: 0 4px 15px 1px #02213bb3;
animation: fadeIn 1s;
.basic-title {
@include flex;
width: 100%;
height: 40px;
padding: 0 5px 0 10px;
background-color: #173147;
span {
font-size: 16px;
color: white;
margin-right: auto;
}
:deep() {
.el-icon {
cursor: pointer;
}
}
}
.basemap {
width: 95%;
height: calc(100% - 80px);
margin: 0 auto;
overflow-y: scroll;
.basemap-card {
display: inline-block;
width: 75px;
margin-top: 10px;
margin-left: 10px;
vertical-align: top;
text-align: center;
cursor: pointer;
font-size: 12px;
color: white;
&:hover {
color: #337fe5 !important;
.icon {
border-color: #337fe5;
}
}
.icon {
border: 1px solid #4db3ff78;
width: 75px;
height: 70px;
padding: 1px;
}
}
.active-card {
color: #337fe5 !important;
.icon {
border-color: #337fe5;
}
}
}
.terrain-show {
@include flex;
width: 100%;
height: 40px;
span {
color: white;
margin: 0 5px 0 10px;
}
}
}
.layer-add {
position: absolute;
top: 60px;
right: 10px;
padding: 0 !important;
background-image: none !important;
border: 1px solid #008aff70;
border-radius: 2px !important;
background-color: rgba(23, 49, 71, 0.8);
width: 300px;
height: 500px;
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: white;
margin-right: auto;
}
:deep() {
.el-icon {
cursor: pointer;
}
}
}
&-tree {
height: calc(100% - 40px);
overflow-y: scroll;
:deep() {
.el-tree {
background-color: rgba(23, 49, 71, 0.8);
color: white;
}
.el-tree-node__content:hover {
background-color: rgba(0, 138, 255, 0.5);
}
.el-tree-node:focus > .el-tree-node__content {
background-color: rgba(0, 138, 255, 0.5);
}
.el-checkbox__inner {
background-color: transparent;
}
}
}
}
2023-10-12 18:45:45 +08:00
}
2023-10-16 19:09:06 +08:00
// .dropdown {
// background-color: rgba(23, 49, 71, 0.8) !important;
// // border: 1px solid rgba(23, 49, 71, 0.8) !important;
// :deep() {
// .el-dropdown-menu__item {
// color: white;
// }
// .el-dropdown-menu__item:not(.is-disabled):hover {
// background-color: rgba(0, 138, 255, 0.5);
// }
// }
// }
2023-10-12 18:45:45 +08:00
.option-list {
width: 200px;
height: 350px;
position: absolute;
right: 20px;
top: 450px;
background-color: white;
padding: 20px;
display: flex;
flex-direction: column;
&-title {
font-size: 16px;
font-weight: 700;
}
&-item {
display: flex;
flex-direction: column;
margin-bottom: 10px;
> span {
font-size: 14px;
font-weight: 700;
2023-10-10 09:31:35 +08:00
}
2023-10-12 18:45:45 +08:00
.item-classify {
2023-10-10 09:31:35 +08:00
display: flex;
2023-10-12 18:45:45 +08:00
flex-direction: column;
&-item {
display: flex;
align-items: center;
:deep() {
.el-slider,
.el-date-editor {
width: 60% !important;
}
}
2023-10-10 09:31:35 +08:00
}
}
}
}
2023-10-13 15:23:55 +08:00
// 视频监控点位样式
:deep() {
.mars3d-camera-content {
height: 30px;
}
.mars3d-camera-img {
width: 30px;
height: 30px;
animation: cameraMove 1s linear infinite alternate;
-webkit-animation: cameraMove 1s linear infinite alternate;
}
@keyframes cameraMove {
from {
margin-top: 20px;
}
to {
margin-top: 0px;
}
}
@-webkit-keyframes cameraMove {
from {
margin-top: 20px;
}
to {
margin-top: 0px;
}
}
.mars3d-camera-line {
height: 120px;
width: 5px;
margin-top: 20px;
border-left: 3px dashed #5b8fee;
margin-left: calc(50% - 1px);
}
.mars3d-camera-point {
border-radius: 50%;
width: 8px;
height: 8px;
margin-left: calc(50% - 3px);
background-color: #5b8fee;
}
.animation-spaceInDown {
animation-duration: 1s;
animation-fill-mode: both;
animation-name: spaceInDown;
}
@keyframes spaceInDown {
0% {
opacity: 0;
transform-origin: 0% 100%;
transform: scale(0.2) translate(0, 200%);
}
100% {
opacity: 1;
transform-origin: 0% 100%;
transform: scale(1) translate(0, 0);
}
}
.marsBlackPanel {
min-width: 90px;
min-height: 35px;
position: absolute;
left: 16px;
bottom: 31px;
cursor: default;
border-radius: 4px;
opacity: 0.96;
border: 1px solid #14171c;
box-shadow: 0px 2px 21px 0px rgba(33, 34, 39, 0.55);
border-radius: 4px;
box-sizing: border-box;
background: linear-gradient(0deg, #1e202a 0%, #0d1013 100%);
}
.marsBlackPanel::before {
content: "";
width: calc(100% + 22px);
height: 39px;
position: absolute;
bottom: -39px;
left: -22px;
background: url("src/assets/images/icon/popupLbl.png") 0px 0px no-repeat;
background-position: 0px 0px;
}
.marsBlackPanel-text {
width: 100%;
height: 100%;
min-height: 33px;
text-align: center;
padding: 10px 5px 0 5px;
margin: 0;
font-size: 14px;
font-weight: 400;
color: #ffffff;
border: 1px solid #ffffff4f;
-webkit-box-sizing: border-box;
box-sizing: border-box;
white-space: nowrap;
}
.marsBlackPanel-highlight {
border: 2px solid yellow;
}
.mars3d-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
text-align: center;
width: 20px;
height: 20px;
font: 16px/14px Tahoma, Verdana, sans-serif;
text-decoration: none;
font-weight: bold;
background: transparent;
z-index: 20170825;
cursor: pointer;
color: #fff;
}
}
// 全局基础样式
2023-10-12 18:45:45 +08:00
:deep() {
.cesium-viewer-toolbar {
top: auto;
bottom: 35px;
left: 12px;
right: auto;
}
.cesium-toolbar-button img {
height: 100%;
vertical-align: middle;
}
.cesium-viewer-toolbar > .cesium-toolbar-button,
.cesium-navigationHelpButton-wrapper,
.cesium-viewer-geocoderContainer {
margin-bottom: 5px;
float: left;
clear: both;
text-align: center;
}
.cesium-button {
background-color: rgba(23, 49, 71, 0.7);
border: none;
color: #ffffff;
fill: #e6e6e6;
line-height: 32px;
}
.cesium-button:hover {
background-color: rgba(0, 138, 255, 0.7);
box-shadow: none;
border: none;
}
/**cesium 底图切换面板*/
.cesium-baseLayerPicker-dropDown {
bottom: 0;
left: 40px;
max-height: 700px;
margin-bottom: 5px;
background-color: rgba(23, 49, 71, 0.7);
}
/**cesium 帮助面板*/
.cesium-navigation-help {
top: auto;
bottom: 0;
left: 40px;
transform-origin: left bottom;
}
.cesium-navigation-help-instructions,
.cesium-navigation-button {
background-color: rgba(23, 49, 71, 0.8);
}
.cesium-navigation-button-selected,
.cesium-navigation-button-unselected:hover {
background-color: rgba(23, 49, 71, 1);
}
/**cesium 二维三维切换*/
.cesium-sceneModePicker-wrapper {
width: auto;
}
.cesium-sceneModePicker-wrapper .cesium-sceneModePicker-dropDown-icon {
float: right;
margin: 0 3px;
}
/**cesium POI查询输入框*/
.cesium-viewer-geocoderContainer .search-results {
left: 0;
right: 40px;
width: auto;
z-index: 9999;
}
.cesium-geocoder-searchButton {
background-color: rgba(23, 49, 71, 0.8);
}
.cesium-viewer-geocoderContainer .cesium-geocoder-input {
background-color: rgba(63, 72, 84, 0.7);
}
.cesium-viewer-geocoderContainer .cesium-geocoder-input:focus {
background-color: var(--mars-bg-base, rgba(63, 72, 84, 0.9));
}
.cesium-viewer-geocoderContainer .search-results {
background-color: rgba(23, 49, 71, 0.8);
}
/**cesium info信息框*/
.cesium-infoBox {
top: 50px;
background: var(--mars-bg-base, rgba(63, 72, 84, 0.9));
}
.cesium-infoBox-title {
background-color: rgba(23, 49, 71, 0.8);
}
/**cesium 任务栏的FPS信息*/
.cesium-performanceDisplay-defaultContainer {
top: auto;
bottom: 35px;
right: 50px;
}
.cesium-performanceDisplay-ms,
.cesium-performanceDisplay-fps {
color: #fff;
}
/**cesium tileset调试信息面板*/
.cesium-viewer-cesiumInspectorContainer {
top: 10px;
left: 10px;
right: auto;
}
.cesium-cesiumInspector {
background-color: rgba(23, 49, 71, 0.8);
}
/**覆çmars3d内部控件的颜色等样式*/
.mars3d-compass .mars3d-compass-outer {
fill: rgba(23, 49, 71, 0.8);
}
.mars3d-contextmenu-ul,
.mars3d-sub-menu {
background-color: rgba(23, 49, 71, 0.8);
}
.mars3d-contextmenu-ul > li > a:hover,
.mars3d-sub-menu > li > a:hover,
.mars3d-contextmenu-ul > li > a:focus,
.mars3d-sub-menu > li > a:focus,
.mars3d-contextmenu-ul > li > .active,
.mars3d-sub-menu > li > .active {
background-color: var(--mars-hover-btn-bg, #3ea6ff);
}
.mars3d-contextmenu-ul > .active > a,
.mars3d-sub-menu > .active > a,
.mars3d-contextmenu-ul > .active > a:hover,
.mars3d-sub-menu > .active > a:hover,
.mars3d-contextmenu-ul > .active > a:focus,
.mars3d-sub-menu > .active > a:focus {
background-color: var(--mars-hover-btn-bg, #3ea6ff);
}
/* Popup样式*/
.mars3d-popup-color {
color: var(--mars-text-color, #ffffff);
}
.mars3d-popup-background {
background: var(--mars-bg-base, rgba(63, 72, 84, 0.9));
}
.mars3d-tooltip {
color: var(--mars-text-color, #ffffff);
background: var(--mars-bg-base, rgba(63, 72, 84, 0.9));
border: 1px solid var(--mars-bg-base, rgba(63, 72, 84, 0.9));
}
.mars3d-tooltip-top:before {
border-top-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));
}
.mars3d-tooltip-bottom:before {
border-bottom-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));
}
.mars3d-tooltip-left:before {
border-left-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));
}
.mars3d-tooltip-right:before {
border-right-color: var(--mars-bg-base, rgba(23, 49, 71, 0.8));
}
.mars3d-template-content label {
padding-right: 6px;
}
.mars3d-template-titile {
color: var(--mars-base-color, #ffffff);
border-bottom: 1px solid var(--mars-hover-btn-bg, #3ea6ff);
}
.mars3d-template-titile a {
font-size: 16px;
color: var(--mars-msg-title-color, #c7d3dd);
}
.mars3d-popup-btn-custom {
padding: 3px 10px;
border: 1px solid #209ffd;
background: #209ffd1c;
}
.mars3d-popup-content {
margin: 15px;
}
.mars3d-divGraphic:hover {
z-index: 999 !important;
}
}
2023-10-10 09:31:35 +08:00
</style>