吉安感知网项目-前端
罗广辉
2026-04-01 8bb2f8984e684b6baa3b4cc335ac034192f58ea1
applications/drone-command/src/views/resource/components/BoxSelect.vue
New file
@@ -0,0 +1,250 @@
<template>
   <div></div>
</template>
<script setup>
import * as Cesium from 'cesium'
import { ElMessage } from 'element-plus'
let curPolygonPosition = []
let savePolygonPosition = []
let curPolygon = null
let curPolygonEntity = null
let curPolygonObj = null
let menuPanel = null
let saveMenuPanel = null
const viewInstance = inject('viewInstance')
const homeViewer = inject('homeViewer')
const updateBoxSelect = inject('updateBoxSelect')
function preventDefault(event) {
   event.preventDefault()
   return
}
function init() {
   // draw.drawPlane();
   curPolygon = new Cesium.PolygonHierarchy()
   curPolygonEntity = new Cesium.Entity()
   homeViewer.value.scene.globe.depthTestAgainstTerrain = true
   viewInstance.value.addLeftClickEvent(null, addPlanerPointEvent, 'drawCustomPolygon')
   viewInstance.value.addRightClickEvent(null, addPlanarMenuEvent, 'drawCustomPolygon')
   viewInstance.value.addMouseHandler(null, mouseMoveEvent, 'drawCustomPolygon')
}
function mouseMoveEvent(movement, viewer) {
   const mouseInfo = viewInstance.value.getMouseInfoAll(movement.endPosition)
   const { x, y } = mouseInfo.windowPosition
   if (!menuPanel) {
      menuPanel = createMenuPanel()
      viewer.container.appendChild(menuPanel)
   }
   menuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`
   if (
      curPolygonObj &&
      mouseInfo.surfacePosition &&
      mouseInfo.surfacePosition != null &&
      curPolygonPosition.length >= 1
   ) {
      curPolygonPosition.pop()
      curPolygonPosition.push(mouseInfo.surfacePosition)
      curPolygon.positions.pop()
      curPolygon.positions.push(mouseInfo.surfacePosition)
   }
}
function addPlanerPointEvent(click, pick) {
   const { position } = click
   const mouseInfo = viewInstance.value.getMouseInfoAll(position)
   if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo)
}
function addPlanarMenuEvent(click, pick, viewer) {
   if (savePolygonPosition.length <= 2) {
      ElMessage.warning('当前绘制无法形成面,请继续绘制或取消绘制!!')
      return
   }
   const { position } = click
   const mouseInfo = viewInstance.value.getMouseInfoAll(position)
   remove()
   removeMenuPanel()
   if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo)
   const { x, y } = position
   saveMenuPanel = createSaveMenuPanel()
   saveMenuPanel.addEventListener('click', saveMenuClickEvent)
   saveMenuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`
   viewer.container.appendChild(saveMenuPanel)
}
function createSaveMenuPanel() {
   const menuPanel = document.createElement('div')
   menuPanel.className = 'planar-menu-panel'
   const arr = [
      { title: '保存框选', class: 'save-draw' },
      { title: '清除框选', class: 'anew-draw' },
   ]
   arr.forEach(item => {
      const title = document.createElement('div')
      title.innerText = item.title
      title.className = item.class
      menuPanel.appendChild(title)
   })
   return menuPanel
}
const emit = defineEmits(['upDateBoxSelect'])
function saveMenuClickEvent(e) {
   const className = e.target.className
   if (className === 'save-draw') {
      emit('upDateBoxSelect')
      updateBoxSelect(savePolygonPosition)
   }
   if (className == 'anew-draw') {
      cancel()
   }
   removeSaveMenuPanel()
}
function removeSaveMenuPanel() {
   if (saveMenuPanel) {
      homeViewer.value.container?.removeChild(saveMenuPanel)
      saveMenuPanel.removeEventListener('click', saveMenuClickEvent)
      saveMenuPanel = null
   }
}
function createMenuPanel() {
   const menuPanel = document.createElement('div')
   menuPanel.className = 'planar-menu-panel'
   const title = document.createElement('div')
   title.innerText = '左击选择点位,右击结束'
   title.className = 'proof-custom-add-polygon'
   menuPanel.appendChild(title)
   return menuPanel
}
function removeMenuPanel() {
   if (menuPanel) {
      homeViewer.value.container?.removeChild(menuPanel)
      menuPanel = null
   }
}
function drawCustomPolygon(point) {
   if (curPolygonPosition.length == 0) {
      curPolygonPosition.push(point.surfacePosition.clone())
      curPolygon.positions.push(point.surfacePosition.clone())
   }
   savePolygonPosition.push(point.wgs84SurfacePosition)
   curPolygonPosition.push(point.surfacePosition.clone())
   curPolygon.positions.push(point.surfacePosition.clone())
   if (!curPolygonObj) {
      curPolygonEntity.polyline = {
         width: 2,
         material: Cesium.Color.WHITE,
         clampToGround: false,
      }
      curPolygonEntity.polyline.positions = new Cesium.CallbackProperty(function () {
         return curPolygonPosition
      }, false)
      curPolygonEntity.polygon = {
         hierarchy: new Cesium.CallbackProperty(function () {
            return curPolygon
         }, false),
         material: Cesium.Color.fromCssColorString('#00ffff').withAlpha(0.4),
         clampToGround: false,
      }
      curPolygonEntity.name = 'customProofPolygon'
      curPolygonEntity._id = 'customProofPolygon'
      curPolygonObj = homeViewer.value.entities.add(curPolygonEntity)
   }
}
function clearPlanar() {
   homeViewer.value.entities.remove(curPolygonObj)
   curPolygonObj = null
   curPolygon = null
   curPolygonEntity = null
   curPolygonPosition = []
   savePolygonPosition = []
}
function remove() {
   viewInstance.value.removeLeftClickEvent('drawCustomPolygon')
   viewInstance.value.removeRightClickEvent('drawCustomPolygon')
   viewInstance.value.removeMouseHandler('drawCustomPolygon')
}
function cancel() {
   remove()
   removeMenuPanel()
   clearPlanar()
   init()
}
onMounted(() => {
   document.addEventListener('contextmenu', preventDefault)
   init()
})
onBeforeUnmount(() => {
   document.removeEventListener('contextmenu', preventDefault)
   remove()
   removeMenuPanel()
   removeSaveMenuPanel()
   clearPlanar()
   homeViewer.value.scene.globe.depthTestAgainstTerrain = false
})
</script>
<style lang="scss" scoped>
p {
   text-indent: 2em;
   color: #ffffff;
   font-size: 18px;
}
.export-btns {
   margin-top: 44px;
   display: flex;
   align-items: center;
   justify-content: space-around;
   .el-button {
      background-color: transparent !important;
   }
}
</style>