/* * @Author: shuishen 1109946754@qq.com * @Date: 2025-04-15 22:41:40 * @LastEditors: shuishen 1109946754@qq.com * @LastEditTime: 2025-04-16 18:38:00 * @FilePath: \command-center-dashboard\src\hooks\useSingleDroneMap\useSingleDroneMap.js * @Description: * * Copyright (c) 2025 by shuishen, All Rights Reserved. */ import * as Cesium from 'cesium' import endingImg from '@/assets/images/aiNowFly/ending.png' import endingHighImg from '@/assets/images/aiNowFly/ending-high.png' /** * * @param {Object} options - 配置选项 */ export function useSingleDroneMap (options = { eventPositions: [], eventApi: null, eventApiParams: {} }) { const { eventPositions, eventApi, eventApiParams } = options let viewer = null let handler = null let currentEntity = null // 初始化机场位置 const initDroneEntity = (dronePosition) => { const { lng, lat, status } = dronePosition if (!lng || !lat) return const markerImg = status ? endingHighImg : endingImg const position = Cesium.Cartesian3.fromDegrees(+lng, +lat, 0) const droneEntity = viewer?.entities.add({ id: `single-drone-position`, position: position, billboard: { image: new Cesium.ConstantProperty(markerImg), width: 35, height: 35, }, ellipse: { semiMinorAxis: 5000, semiMajorAxis: 5000, outline: true, material: Cesium.Color.CORNFLOWERBLUE.withAlpha(0.3), }, properties: { customData: { data: { type: 'single-drone-event' } } } }) viewer?.flyTo(droneEntity, { offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-60), 0), duration: 0.5, }) } // 机巢事件地图撒点 const initDroneEventEntity = (eventPositions = eventPositions) => { // 遍历特征并添加实体 eventPositions.length && eventPositions.forEach((item, index) => { const { longitude, latitude, status, id } = item const position = Cesium.Cartesian3.fromDegrees(+longitude, +latitude, 0) viewer?.entities.add({ id: `single-drone-event-${index}`, position: position, billboard: { image: new Cesium.ConstantProperty(endingHighImg), width: 35, height: 35, }, properties: { customData: { data: { type: 'single-drone-sign' } } }, }) }) } // 调用传入api const initEventApiEntity = () => { removeEventLayer() eventApi( { ...eventApiParams, } ).then(res => { const result = res.data.data.records initDroneEventEntity(result) }) } // 事件地图撒点加载方式 const initEventLayer = () => { eventApi ? initEventApiEntity() : initDroneEventEntity() } const removeEventLayer = () => { // entities移除 const entitiesIDs = viewer?.entities.values.map(i => i.id) entitiesIDs && entitiesIDs.forEach(item => { item.includes('single-drone-event') && viewer?.entities.removeById(item) }) } // 移除当前地图所有entity const removeLayer = () => { // entities移除 const entitiesIDs = viewer?.entities.values.map(i => i.id) entitiesIDs.forEach(item => { item.includes('single-drone-') && viewer?.entities.removeById(item) }) } // 查找特定类型的实体 const findEntityByType = (entities, type) => { return entities.find(entity => entity?.properties?.customData?._value?.data?.type === type ) } // 左键单机事件 const singleMachineEvent = async click => { let clickedEntities = viewer?.scene.drillPick(click.position).map(item => item.id) if (!clickedEntities.length) return const currentEntity = findEntityByType(clickedEntities, 'single-drone-event') removeLabel() if (currentEntity) { viewer?.scene.postRender.addEventListener(labelBoxRender) } } // 事件初始化 const handlerInit = () => { 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(EventPopUpBox, { 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 (!currentEntity) return let dom = document.querySelector('#mapPopUpBox') if (!dom) { dom = getLabelDom(currentEntity.properties.customData._value.data) } const screenPosition = viewer?.scene.cartesianToCanvasCoordinates(currentEntity?.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 init = () => { viewer = window.$viewer handlerInit() } const removeAll = () => { removeLayer() removeHandler() removeLabel() } // 自动清理 onUnmounted(() => { removeAll() }) return { init, removeAll, initEventLayer, initDroneEntity, } }