吉安感知网项目-前端
罗广辉
2026-04-01 8bb2f8984e684b6baa3b4cc335ac034192f58ea1
applications/drone-command/src/views/resource/components/DrawPolygon.vue
New file
@@ -0,0 +1,312 @@
<template>
  <div></div>
</template>
<script setup>
import * as Cesium from 'cesium';
import { ElMessage } from 'element-plus';
import { sdfwUpdate } from '@/api/home/territory';
let curPolygonPosition = [];
let savePolygonPosition = [];
let curPolygon = null;
let curPolygonEntity = null;
let curPolygonObj = null;
let menuPanel = null;
let saveMenuPanel = null;
const selectionIds = inject('selectionIds');
const clearSelect = inject('clearSelect');
const getTableList = inject('getTableList')
const viewInstance = inject('viewInstance');
const homeViewer = inject('homeViewer');
watch(
  () => selectionIds.value,
  (newValue, oldValue) => {
    if (newValue && oldValue && newValue !== oldValue) {
      cancel();
    }
  }
);
function preventDefault(event) {
  event.preventDefault();
  return;
}
function init() {
  // let draw = new Draw(homeViewer.value);
  // 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;
}
function saveMenuClickEvent(e) {
  const className = e.target.className;
  if (className === 'save-draw') {
    updatePolygon();
  }
  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: true,
    };
    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');
}
const emit = defineEmits(['upDateDrawState',]);
function updatePolygon() {
  let polygon = savePolygonPosition.reduce((pre, cur) => {
    pre.push(`${cur.lng} ${cur.lat}`);
    return pre;
  }, []);
  polygon.push(polygon[0]);
  // 接口
  sdfwUpdate({
     ids: selectionIds.value,
     sdfw: `POLYGON((${polygon.join(',')}))`,
  })
     .then(res => {
        if (selectionIds.value) {
           emit('upDateDrawState')
           selectionIds.value = null
           clearSelect()
        }
        if (res.data.code !== 0) return ElMessage.error(res.message)
        ElMessage.success('重新绘制图斑成功!!')
        getTableList()
     })
     .catch(e => {
        cancel()
     })
}
function cancel() {
  remove();
  removeMenuPanel();
  clearPlanar();
  removeSaveMenuPanel();
  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;
  }
}
.proof-custom-add-polygon {
  position: absolute;
  left: 20px;
  background: rgba(0, 0, 0, 0.6);
  white-space: nowrap;
  border-radius: 4px;
pointer-events: none;
  &::after {
    content: '';
    position: absolute;
    left: -3px;
    top: calc(50% - 2px);
    width: 0;
    height: 0;
    border-top: 4px solid rgba(0, 0, 0, 0.6);
    border-left: 4px solid rgba(0, 0, 0, 0.6);
    border-right: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transform: rotate(-45deg);
  }
}
</style>