/*
|
* @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,
|
}
|
}
|