/* * @Author: shuishen 1109946754@qq.com * @Date: 2025-04-15 22:41:40 * @LastEditors: shuishen 1109946754@qq.com * @LastEditTime: 2025-04-17 19:43:36 * @FilePath: \command-center-dashboard\src\hooks\components\useMapHandlerClick.js * @Description: * * Copyright (c) 2025 by shuishen, All Rights Reserved. */ import * as Cesium from 'cesium' import { render } from 'vue' import { useStore } from 'vuex' import DevicePopUpBox from '@/hooks/components/DevicePopUpBox.vue' import EventPopUpBox from '@/hooks/components/EventPopUpBox.vue' /** * * @param {Object} options - 配置选项 */ export function useMapHandlerClick (options = {}) { const { popupType = 'event-popup', eventType = 'single-drone-event', styleTransform = 'translate(-50%,-110%)', getViewer } = options const store = useStore() const popupData = { 'event-popup': EventPopUpBox, 'device-popup': DevicePopUpBox } const MapPopUpBox = popupData[popupType] let viewer = null let handler = null let currentClickEntity = null // 查找特定类型的实体 const findEntityByType = (entities, type) => { let types = [] Array.isArray(type) ? types = type : types = [type] return types.reduce((pre, curType) => { let entity = entities.find(entity => entity?.properties?.customData?._value?.data?.type === curType) return entity ? (pre.push({ type: curType, entity }), pre) : pre }, []) } const publicEvent = (entity) => { viewer.scene.postRender.addEventListener(labelBoxRender) } const typeEvent = { 'deviceAggregation': publicEvent, 'single-drone-event': publicEvent, 'event': publicEvent, 'device': (entity) => { const device = entity.properties.customData._value.data store.commit('setSingleUavHome', device) } } // 左键单机事件 const singleMachineEvent = async click => { let clickedEntities = viewer?.scene.drillPick(click.position).map(item => item.id) if (!clickedEntities.length) return let curClick = findEntityByType(clickedEntities, eventType) removeLabel() if (curClick.length > 0 && typeEvent[curClick[0].type]) { currentClickEntity = curClick[0].entity typeEvent[curClick[0].type](currentClickEntity) } } // 事件初始化 const handlerInit = () => { !viewer && (viewer = getViewer()) if (handler) return handler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas) handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK) } // 事件移除 const removeHandler = () => { handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK) handler?.destroy() handler = null } // 获取弹框box const getLabelDom = data => { const vNode = h(MapPopUpBox, { data, removeLabel }) const tooltipContainer = document.createElement('div') tooltipContainer.id = 'mapPopUpBox' tooltipContainer.style.position = 'absolute' tooltipContainer.style.transform = styleTransform tooltipContainer.style.pointerEvents = 'none' document.querySelector('.page-index').append(tooltipContainer) render(vNode, tooltipContainer) return tooltipContainer } // 弹框位置刷新 const labelBoxRender = () => { if (!currentClickEntity) return let dom = document.querySelector('#mapPopUpBox') if (!dom) { dom = getLabelDom(currentClickEntity.properties.customData._value.data) } const screenPosition = viewer?.scene.cartesianToCanvasCoordinates(currentClickEntity?.position?._value) if (screenPosition) { dom.style.left = `${screenPosition.x}px` dom.style.top = `${screenPosition.y}px` dom.style.display = 'block' } } const removeDom = () => { const dom = document.querySelector('#mapPopUpBox') if (dom && dom.parentNode) { dom.parentNode.removeChild(dom) } } // 移除弹框标签 const removeLabel = () => { viewer?.scene.postRender.removeEventListener(labelBoxRender) removeDom() } const removeAll = () => { removeHandler() removeLabel() } // 自动清理 onUnmounted(() => { removeAll() }) return { handlerInit, removeAll, removeLabel } }