| src/assets/images/home/mapPopUpBox/itembg.png | patch | view | raw | blame | history | |
| src/assets/images/home/mapPopUpBox/mapPopUpBg.png | patch | view | raw | blame | history | |
| src/assets/images/home/mapPopUpBox/titleImg.png | patch | view | raw | blame | history | |
| src/views/Home/Home.vue | ●●●●● patch | view | raw | blame | history | |
| src/views/Home/MapPopUpBox.vue | ●●●●● patch | view | raw | blame | history | |
| src/views/Home/useAggregation.js | ●●●●● patch | view | raw | blame | history |
src/assets/images/home/mapPopUpBox/itembg.png
src/assets/images/home/mapPopUpBox/mapPopUpBg.png
src/assets/images/home/mapPopUpBox/titleImg.png
src/views/Home/Home.vue
@@ -10,6 +10,9 @@ import HomeLeft from '@/views/Home/components/HomeLeft/HomeLeft.vue'; import SearchBox from '@/views/Home/SearchBox.vue'; import { useAggregation } from '@/views/Home/useAggregation'; import MapPopUpBox from '@/views/Home/MapPopUpBox.vue'; import { render } from 'vue'; useAggregation() </script> src/views/Home/MapPopUpBox.vue
New file @@ -0,0 +1,166 @@ <script setup> import { Close } from '@element-plus/icons-vue'; const list = [ { name: '执行中', value: '1', color: '#FFA768' }, { name: '在线', value: '20', color: '#8EFFAC' }, { name: '离线', value: '14', color: '#FFFFFF' }, { name: '异常', value: '25', color: '#FF6262' }, ]; const props = defineProps(['data', 'removeLabel']); </script> <template> <div class="mapPopUpBox"> <div class="header"> <div class="headerLeft"> <img class="header-image" src="@/assets/images/home/MapPopUpBox/titleImg.png" alt="" /> <div class="header-title">安义县机场</div> </div> <el-icon class="header-close" @click="props.removeLabel"> <Close /> </el-icon> </div> <div class="info"> <div class="info-item"> 机巢数: <div class="num">10</div> </div> <div class="info-item"> 任务数: <div class="num">32</div> </div> </div> <div class="status-title">机巢状态</div> <div class="status-list"> <div v-for="item in list" :key="item.name" class="status-item"> <div class="status-value" :style="{ color: item.color }">{{ item.value }}</div> <div class="status-name">{{ item.name }}</div> </div> </div> </div> </template> <style scoped lang="scss"> .mapPopUpBox { width: 418px; height: 240px; background: url('@/assets/images/home/MapPopUpBox/mapPopUpBg.png') no-repeat center / 100% 100%; padding-left: 98px; .header { padding: 0 12px; width: 320px; height: 51px; display: flex; align-items: center; justify-content: space-between; .headerLeft { display: flex; } img { width: 26px; height: 26px; } &-title { font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; font-weight: 400; font-size: 26px; line-height: 30px; letter-spacing: 2px; text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25); background: linear-gradient(180deg, #ffffff 41%, #35d0ff 86%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-left: 4px; } &-close { width: 25px; height: 100%; line-height: 100%; display: flex; align-items: center; color: #9cd5ff; pointer-events: all; cursor: pointer; } } .info { height: 34px; font-family: Source Han Sans CN, Source Han Sans CN, serif; font-weight: 400; font-size: 16px; color: #ffffff; line-height: 19px; display: flex; align-items: center; padding-left: 15px; gap: 0 20px; margin: 18px 0; .info-item { display: flex; align-items: center; .num { font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; font-weight: 400; font-size: 26px; color: #ffffff; line-height: 30px; } } } .status-title { font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; font-weight: 400; font-size: 20px; color: #ffffff; line-height: 23px; text-shadow: 0px 0px 12px rgba(68, 105, 255, 0.67); padding-left: 15px; margin-bottom: 14px; } .status-list { display: flex; justify-content: space-between; align-items: center; .status-item { width: 66px; height: 54px; background: url('@/assets/images/home/MapPopUpBox/itembg.png') no-repeat center / 100% 100%; text-align: center; .status-value { font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; font-weight: 400; font-size: 26px; color: #ffa768; line-height: 17px; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); position: relative; top: -3px; } .status-name { font-family: Source Han Sans CN, Source Han Sans CN, serif; font-weight: 400; font-size: 14px; color: #ffffff; line-height: 16px; position: relative; top: -3px; } } } } </style> src/views/Home/useAggregation.js
@@ -4,19 +4,24 @@ import jiangxishi from '@/assets/geojson/jiangxishi.json'; import jiangxi from '@/assets/geojson/jiangxi.json'; import zg from '@/assets/geojson/zg.json'; import MapPopUpBox from '@/views/Home/MapPopUpBox.vue'; import { render } from 'vue'; /** * 机巢聚合功能 */ export const useAggregation = () => { let viewer = null; const scalingJudgment = [ { name: '县', value: [0, 48651], gJson: null }, { name: '市', value: [48651, 314863], gJson: jiangxishi }, { name: '省', value: [314863, 1169651], gJson: jiangxi }, { name: '国', value: [1169651, 37962800], gJson: zg }, ]; let viewer = null; const active = ref(''); let handler = null; let labelDiv = null; let positionC3 = null; const init = () => { determineScaling(); viewer.camera.moveEnd.addEventListener(() => { @@ -24,18 +29,15 @@ }); }; const removeFun = () => { viewer.dataSources.removeAll(true); viewer.entities.removeAll(); }; // 确定缩放比例 const determineScaling = () => { let height = viewer.camera.positionCartographic.height; // 根据高度展示对应的 gJson for (let item of scalingJudgment) { if (height > item.value[0] && height <= item.value[1]) { if (active.value !== item.name) { removeFun(); removeEntities(); removeLabel(); active.value = item.name; item.gJson ? aggregation(item) : splashed(); } @@ -83,6 +85,7 @@ if (!feature.position) return; const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1]); viewer.entities.add({ id: feature.id, position: position, label: { // 随机整数 @@ -99,6 +102,12 @@ image: new Cesium.ConstantProperty(data2), width: 24, height: 24, }, properties: { id: feature.id, customData: { name: feature.name, }, }, }); }); @@ -118,15 +127,60 @@ }); }; const getLabelDom = () => { const vNode = h(MapPopUpBox, { data: '参数',removeLabel }); const tooltipContainer = document.createElement('div'); tooltipContainer.style.position = 'absolute'; tooltipContainer.style.transform = 'translateY(-50%)'; tooltipContainer.style.pointerEvents = 'none'; document.querySelector('.page-index').append(tooltipContainer); render(vNode, tooltipContainer); return tooltipContainer; }; const labelBox = () => { if (!labelDiv) { labelDiv = getLabelDom(); } const screenPosition = viewer.scene.cartesianToCanvasCoordinates(positionC3); if (screenPosition) { labelDiv.style.left = `${screenPosition.x}px`; labelDiv.style.top = `${screenPosition.y}px`; } }; const clickFun = click => { const pickedObject = viewer.scene.pick(click.position); if (Cesium.defined(pickedObject) && pickedObject.id) { const entity = pickedObject.id; positionC3 = entity.position._value; viewer.scene.postRender.addEventListener(labelBox); } }; const removeEntities = () => { viewer.dataSources.removeAll(true); viewer.entities.removeAll(); }; const removeLabel = () => { viewer.scene.postRender.removeEventListener(labelBox); if (labelDiv && labelDiv.parentNode) { labelDiv.parentNode.removeChild(labelDiv); labelDiv = null; } }; onUnmounted(() => { console.log('xiezai'); removeFun(); removeEntities(); removeLabel(); handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); }); onMounted(() => { console.log('触发'); nextTick(() => { viewer = window.$viewer; handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(clickFun, Cesium.ScreenSpaceEventType.LEFT_CLICK); init(); }); });