From f1e4e5843ff9ae37ccecd0ea391911f67de0e50d Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Sat, 29 Mar 2025 16:02:53 +0800
Subject: [PATCH] feat: 机巢点击交互
---
src/assets/images/home/mapPopUpBox/titleImg.png | 0
src/assets/images/home/mapPopUpBox/itembg.png | 0
src/views/Home/useAggregation.js | 74 ++++++++++++--
src/views/Home/MapPopUpBox.vue | 166 +++++++++++++++++++++++++++++++++
src/assets/images/home/mapPopUpBox/mapPopUpBg.png | 0
src/views/Home/Home.vue | 3
6 files changed, 233 insertions(+), 10 deletions(-)
diff --git a/src/assets/images/home/mapPopUpBox/itembg.png b/src/assets/images/home/mapPopUpBox/itembg.png
new file mode 100644
index 0000000..37209f4
--- /dev/null
+++ b/src/assets/images/home/mapPopUpBox/itembg.png
Binary files differ
diff --git a/src/assets/images/home/mapPopUpBox/mapPopUpBg.png b/src/assets/images/home/mapPopUpBox/mapPopUpBg.png
new file mode 100644
index 0000000..f4897af
--- /dev/null
+++ b/src/assets/images/home/mapPopUpBox/mapPopUpBg.png
Binary files differ
diff --git a/src/assets/images/home/mapPopUpBox/titleImg.png b/src/assets/images/home/mapPopUpBox/titleImg.png
new file mode 100644
index 0000000..03e6505
--- /dev/null
+++ b/src/assets/images/home/mapPopUpBox/titleImg.png
Binary files differ
diff --git a/src/views/Home/Home.vue b/src/views/Home/Home.vue
index 50174fe..6139619 100644
--- a/src/views/Home/Home.vue
+++ b/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>
diff --git a/src/views/Home/MapPopUpBox.vue b/src/views/Home/MapPopUpBox.vue
new file mode 100644
index 0000000..cc4d0e9
--- /dev/null
+++ b/src/views/Home/MapPopUpBox.vue
@@ -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>
diff --git a/src/views/Home/useAggregation.js b/src/views/Home/useAggregation.js
index 32756bd..db6ec45 100644
--- a/src/views/Home/useAggregation.js
+++ b/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();
});
});
--
Gitblit v1.9.3