吉安感知网项目-前端
shuishen
2026-01-27 d9dfdc18704382cd39f896cc75a71374b83ed7a2
feat:无人机关注增加高亮
1 files modified
123 ■■■■■ changed files
applications/drone-command/src/components/map-container/device-map-container.vue 123 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/components/map-container/device-map-container.vue
@@ -119,6 +119,14 @@
let droneTrackTickHandler = null
let droneTrackStartTime = null
let droneTrackRuntime = []
let favoritePulseRafId = null
let favoritePulseStartAt = 0
let favoritePulseElapsed = 0
const favoritePulseEntities = []
const pulseBaseColor = Cesium.Color.fromCssColorString('#FF3B30')
const PULSE_MIN_RADIUS_M = 60
const PULSE_MAX_RADIUS_M = 180
const PULSE_DURATION_S = 1.6
const detailVisible = ref(true)
const clusterVisible = ref(false)
const countyCenterMap = new Map()
@@ -172,6 +180,57 @@
 */
const adminBoundaryVisible = ref(treeCheckedKeys.value.includes('admin'))
const isFavorited = item => {
    const value = item?.favorited ?? item?.isFavorite
    return value === 1 || value === '1' || value === true
}
let pulseCanvas = null
const getPulseCanvas = () => {
    if (pulseCanvas) return pulseCanvas
    const size = 256
    const canvas = document.createElement('canvas')
    canvas.width = size
    canvas.height = size
    const ctx = canvas.getContext('2d')
    const center = size / 2
    const radius = center - 2
    const gradient = ctx.createRadialGradient(center, center, radius * 0.1, center, center, radius)
    gradient.addColorStop(0, 'rgba(255,59,48,0.55)')
    gradient.addColorStop(0.35, 'rgba(255,59,48,0.35)')
    gradient.addColorStop(0.7, 'rgba(255,59,48,0.15)')
    gradient.addColorStop(1, 'rgba(255,59,48,0)')
    ctx.fillStyle = gradient
    ctx.beginPath()
    ctx.arc(center, center, radius, 0, Math.PI * 2)
    ctx.fill()
    pulseCanvas = canvas
    return canvas
}
const createFavoritePulseEntity = (billboard) => {
    if (!viewer || !billboard) return
    const material = new Cesium.ImageMaterialProperty({
        image: getPulseCanvas(),
        transparent: true,
    })
    const pulse = {
        material,
        offset: Math.random() * PULSE_DURATION_S,
        entity: null,
    }
    pulse.entity = viewer.entities.add({
        position: new Cesium.CallbackProperty(() => billboard.position, false),
        ellipse: {
            semiMajorAxis: new Cesium.CallbackProperty(() => getPulseRadius(pulse), false),
            semiMinorAxis: new Cesium.CallbackProperty(() => getPulseRadius(pulse), false),
            material,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        },
    })
    favoritePulseEntities.push(pulse)
}
const getDevicePosition = item => {
    const longitudeRaw = item.longitude ?? item.lng ?? item.lon
@@ -311,6 +370,12 @@
    }
}
const getPulseRadius = pulse => {
    const phase = ((favoritePulseElapsed + pulse.offset) % PULSE_DURATION_S) / PULSE_DURATION_S
    const wave = phase < 0.5 ? phase * 2 : (1 - phase) * 2
    return PULSE_MIN_RADIUS_M + (PULSE_MAX_RADIUS_M - PULSE_MIN_RADIUS_M) * wave
}
const setDetailVisibility = visible => {
    detailVisible.value = visible
    if (defenseZonePrimitive) defenseZonePrimitive.show = visible
@@ -345,6 +410,11 @@
const setDroneVisibility = visible => {
    if (droneTrackBillboardCollection) droneTrackBillboardCollection.show = visible
    if (droneTrackPolylineCollection) droneTrackPolylineCollection.show = visible
    if (favoritePulseEntities.length) {
        favoritePulseEntities.forEach(pulse => {
            if (pulse?.entity) pulse.entity.show = visible
        })
    }
    if (!visible && selectedTargetType.value === 'drone') {
        closePopup()
    }
@@ -453,6 +523,7 @@
const clearDroneTrackEntities = () => {
    if (!viewer) return
    stopDroneTrackAnimation()
    stopFavoritePulseAnimation()
    if (droneTrackBillboardCollection) {
        if (!droneTrackBillboardCollection.isDestroyed?.()) {
            removeCockpitPrimitive(droneTrackBillboardCollection)
@@ -466,6 +537,12 @@
        droneTrackPolylineCollection = null
    }
    droneTrackRuntime = []
    if (favoritePulseEntities.length) {
        favoritePulseEntities.forEach(pulse => {
            if (pulse?.entity) viewer?.entities?.remove(pulse.entity)
        })
        favoritePulseEntities.length = 0
    }
    dronePickMap.clear()
    if (selectedTargetType.value === 'drone') {
        closePopup()
@@ -532,6 +609,28 @@
    droneTrackTickHandler = null
}
const startFavoritePulseAnimation = () => {
    if (!viewer || favoritePulseRafId) return
    favoritePulseStartAt = performance.now()
    const tick = now => {
        if (!viewer || viewer.isDestroyed?.() || !favoritePulseEntities.length) {
            favoritePulseRafId = null
            return
        }
        favoritePulseElapsed = (now - favoritePulseStartAt) / 1000
        viewer.scene.requestRender()
        favoritePulseRafId = requestAnimationFrame(tick)
    }
    favoritePulseRafId = requestAnimationFrame(tick)
}
const stopFavoritePulseAnimation = () => {
    if (favoritePulseRafId) {
        cancelAnimationFrame(favoritePulseRafId)
        favoritePulseRafId = null
    }
}
const renderSimulatedDroneTrack = (list) => {
    if (!viewer) return
    clearDroneTrackEntities()
@@ -576,16 +675,19 @@
            })
            billboard.id = droneId
            const speedMs = Math.round(Cesium.Cartesian3.distance(positions[0], positions[1]) / segmentDuration)
            dronePickMap.set(droneId, {
                data: {
                    ...item,
                    flightHeightM: item.flightHeightM ?? points[0].height,
                    flightSpeedMs: item.flightSpeedMs ?? speedMs,
                    longitude: item.longitude ?? points[0].longitude,
                    latitude: item.latitude ?? points[0].latitude,
                },
                billboard,
            })
        dronePickMap.set(droneId, {
            data: {
                ...item,
                flightHeightM: item.flightHeightM ?? points[0].height,
                flightSpeedMs: item.flightSpeedMs ?? speedMs,
                longitude: item.longitude ?? points[0].longitude,
                latitude: item.latitude ?? points[0].latitude,
            },
            billboard,
        })
        if (isFavorited(item)) {
            createFavoritePulseEntity(billboard)
        }
            droneTrackRuntime.push({
                positions,
                billboard,
@@ -595,6 +697,7 @@
        })
    viewer.clock.multiplier = 1
    startDroneTrackAnimation()
    startFavoritePulseAnimation()
    reorderCockpitPrimitives()
}