2023-10-21 18:24:25 +08:00

1457 lines
39 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<layoutTop></layoutTop>
<div class="map-content">
<div id="mars3dContainer" class="mars3d-container"></div>
<!-- 搜索框 -->
<div class="input-search">
<el-input v-model="inputVal" @blur="closeSearch" clearable @focus="showHistoryList" @input="searchInput">
<template #append>
<el-icon size="18" @click="searchInput"><Search /></el-icon> </template
></el-input>
<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">
<div v-if="item.widget && !item.children" class="toolbar-item" @click="showWidget(item.name)">
<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">
<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
>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
<!-- 底图菜单操作页面 -->
<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" />
<!-- 空间分析弹框 -->
<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" />
<!-- 视角书签弹框 -->
<ViewBookmark :mapInstance="map" v-if="viewBookmarkShow" @hiddenConfim="viewBookmarkShow = false" />
<!-- 地图打印弹框 -->
<MapPrint :mapInstance="map" v-if="mapPrintShow" @hiddenConfim="mapPrintShow = false" />
<!-- 飞行漫游弹框 -->
<FlyRoam :mapInstance="map" v-if="flyRoamShow" @hiddenConfim="flyRoamShow = false" />
<!-- 图上标绘弹框 -->
<MapMark :mapInstance="map" v-if="mapMarkShow" @hiddenConfim="mapMarkShow = false" />
</div>
<!-- <div class="option-list">
<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>
<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>
</el-scrollbar>
</div> -->
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, computed, markRaw } from "vue";
//引入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";
import { ElMessage } from "element-plus";
import { datas } from "@/enums/company/SetpsEnum";
import { initVue3Popup } from "@/utils/file-util";
import QueryPopup from "./components/query-popup.vue";
import MapMeasurement from "./components/mapMeasurement.vue";
import SpaceAnalysis from "./components/spaceAnalysis.vue";
import CoordinatePicking from "./components/coordinatePicking.vue";
import RegionalNavigation from "./components/regionalNavigation.vue";
import MyTags from "./components/myTags.vue";
import ViewBookmark from "./components/viewBookmark.vue";
import MapPrint from "./components/mapPrint.vue";
import FlyRoam from "./components/flyRoam.vue";
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); // 坐标定位弹框
const analysisShow = ref(false); // 空间分析弹框
const measurementShow = ref(false); // 图上量算弹框
const layersShow = ref(false); // 图层弹框
const basicMapShow = ref(false); // 底图弹框
const chkHasTerrain = ref(false);
const active = ref("");
const baseMaps = ref([]);
const storageName = "mars3d_queryGaodePOI";
const inputVal = ref();
const dataSource = ref<any>([]);
const searchListShow = ref(false);
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
});
const skyProperty = ref({
boxVal: 4
});
const checkedKeys = ref<any[]>([]);
const expandedKeys = ref<any>([]);
const layersObj: any = {};
const treeData = ref<any>([]);
const props = {
label: "title",
children: "children"
};
const hours = computed(() => Math.floor(sunProperty.value.currDate / 60));
const minutes = computed(() => Math.floor(sunProperty.value.currDate / 60));
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; // 延时器
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);
// });
for (let i = 0; i < 6; i++) {
const img = await getCanvas(i + 1);
imgArr.push(img);
}
await initMars3d(ConfigJson.map3d);
await initTree();
});
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
}
});
const data = [
{ name: "底图", icon: "PictureRounded", widget: "manage-basemap" },
{ name: "图层", icon: "PictureRounded", widget: "manage-layers" },
{
name: "工具",
icon: "tool",
children: [
{ name: "图上量算", icon: "ruler", widget: "measure" },
{ name: "空间分析", icon: "analysis", widget: "analysis" },
{ name: "坐标定位", icon: "local", widget: "location-point" },
{ name: "地区导航", icon: "navigation", widget: "location-region" },
{ name: "我的标记", icon: "mark", widget: "addmarker" },
{ 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: "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" }
]
}
];
// 显示地形
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;
}
console.log(666);
};
const clickMenu = (name: any) => {
console.log(name);
if (name == "图上量算") {
measurementShow.value = true;
} else if (name == "空间分析") {
analysisShow.value = true;
} else if (name == "坐标定位") {
pickingShow.value = true;
} else if (name == "地区导航") {
regionalNavigationShow.value = true;
} else if (name == "我的标记") {
myTagsShow.value = true;
} else if (name == "视角书签") {
viewBookmarkShow.value = true;
} else if (name == "地图打印") {
mapPrintShow.value = true;
} else if (name == "飞行漫游") {
flyRoamShow.value = true;
} else if(name == "图上标绘"){
mapMarkShow.value = true;
}
};
// 获取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); // 时间太短会导致点击获取失效
};
const initMars3d = (option: any) => {
map = new mars3d.Map("mars3dContainer", option);
// 加载石化工厂模型
// 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;
});
map.addLayer(graphicLayer);
// 获取配置文件底图数据
getBasicMaps();
// 添加数据
// 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]);
// map.scene.moon.show = true; // 太阳
// map.scene.sun.show = true; // 月亮
// 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);
};
// 获取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;
};
const addRandomGraphicByCount = (graphicLayer: any, position: any) => {
const graphicImg = new mars3d.graphic.DivGraphic({
position: position,
style: {
html: ` <div class="mars3d-camera-content">
<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
}
});
graphicLayer.addGraphic(graphicImg);
};
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;
}
}
};
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);
}
}
};
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;
};
// 天空盒操作
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;
}
};
onUnmounted(() => {
map.removeLayer(graphicLayer);
map.off(mars3d.EventType.cameraChanged, cameraChanged);
queryPoi = null;
address = null;
map = null;
});
</script>
<style lang="scss" scoped>
@mixin flex {
display: flex;
align-items: center;
}
.map-content {
height: calc(100% - 72px);
width: 100%;
position: relative;
background-color: #ccc;
overflow: hidden;
.mars3d-container {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
border: none;
overflow: hidden;
}
.input-search {
width: 260px;
position: absolute;
top: 10px;
left: 10px;
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 {
@include flex;
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 {
@include flex;
padding: 6px 12px;
height: 100%;
font-size: 15px;
cursor: pointer;
.title {
color: white;
margin-left: 5px;
}
&:hover {
background-color: rgba(0, 138, 255, 0.5);
}
}
}
}
// 菜单弹框出现动画
@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;
}
}
}
}
}
// .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);
// }
// }
// }
.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;
}
.item-classify {
display: flex;
flex-direction: column;
&-item {
display: flex;
align-items: center;
:deep() {
.el-slider,
.el-date-editor {
width: 60% !important;
}
}
}
}
}
}
// 视频监控点位样式
: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;
}
}
// 全局基础样式
: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;
}
}
</style>