Browse Source

标绘 地图

Hwf 8 months ago
parent
commit
84e4e6bb0f

+ 6 - 17
src/components/Map/index.vue

@@ -48,7 +48,7 @@ const props = withDefaults(defineProps<Props>(), {});
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { point_type } = toRefs<any>(proxy?.useDict('point_type'));
 
-const emits = defineEmits(['update:drawing', 'selectGraphics', 'unSelectGraphics', 'showTextEditBox']);
+const emits = defineEmits(['update:drawing', 'selectGraphics', 'unSelectGraphics', 'showTextEditBox', 'onDrawCompleted']);
 const containerRef = ref();
 const width = ref('100%');
 const height = ref('100%');
@@ -73,23 +73,10 @@ const { getMouseTool, initMouseTool, drawGraphics, closeDraw, handleUndo } = use
   graphicsType: props.mouseToolState.graphicsType,
   // 绘制完成事件
   onDrawCompleted: (data, overlaysData, obj) => {
-    if (overlaysData.length === 1) {
-      emits('selectGraphics', data);
-    }
-    // else if (overlaysData.length === 2) {
-    //   emits('unSelectGraphics', overlaysData[0]);
-    // }
-    // 点击空间分析
-    obj.on('click', function () {
-      // 没在编辑时
-      if (!props.drawing) {
-        emits('selectGraphics', data);
-      }
-    });
+    closeDraw();
+    emits('onDrawCompleted', data, overlaysData, obj);
   }
 });
-// 测距工具
-const { initRuler } = useRuler();
 // 初始化地图
 const { getAMap, getMap, switchMap, addMarker, addSearchMarker, clearMarker, getMarkers, getScale, showInfo } = useAMap({
   key: '30d3d8448efd68cb0b284549fd41adcf', // 申请好的Web端开发者Key,首次调用 load 时必填
@@ -113,7 +100,6 @@ const { getAMap, getMap, switchMap, addMarker, addSearchMarker, clearMarker, get
     }
     map.on('zoomchange', zoomChangeHandler);
     initMouseTool({ container: 'aMap', map, AMap });
-    initRuler(map, AMap);
     handleResize();
   },
   onMarkerClick: (data) => {
@@ -357,5 +343,8 @@ onUnmounted(() => {
     color: #444;
     font-size: 14px;
   }
+  :deep(.amap-marker) {
+    font-size: 16px;
+  }
 }
 </style>

+ 38 - 11
src/hooks/AMap/useDrawTool.ts

@@ -35,7 +35,7 @@ export function useDrawTool(options: DrawToolOptions) {
     // 右键删除按钮
     contextMenu.addItem(
       '删除',
-      function (event) {
+      function () {
         deleteGraphics();
       },
       0
@@ -65,8 +65,8 @@ export function useDrawTool(options: DrawToolOptions) {
       }
       overlays.push(obj);
       overlaysData.push(data);
-      debugger
       commit(deepClone(overlaysData));
+      debugger
       if (typeof options.onDrawCompleted === 'function') {
         options.onDrawCompleted(data, overlaysData, obj, event);
       }
@@ -95,7 +95,7 @@ export function useDrawTool(options: DrawToolOptions) {
   // 绘制图形
   const drawGraphics = (newOptions: MouseTool) => {
     const data = getRgba(newOptions.color);
-    if (['circle', 'rectangle', 'polygon'].includes(newOptions.graphicsType)) {
+    if (['circle', 'rectangle', 'polygon', 'measureArea'].includes(newOptions.graphicsType)) {
       drawOptions = {
         type: newOptions.graphicsType,
         strokeColor: !!data.color ? data.color : newOptions.color,
@@ -151,6 +151,9 @@ export function useDrawTool(options: DrawToolOptions) {
     } else if (newOptions.graphicsType === 'marker') {
       // 绘制图标
       mouseTool.marker(drawOptions);
+    } else if (newOptions.graphicsType === 'measureArea') {
+      // 测量面积
+      mouseTool.measureArea(drawOptions);
     }
     if (newOptions.graphicsType !== 'text') {
       // 绘制完成事件
@@ -266,12 +269,12 @@ export function useDrawTool(options: DrawToolOptions) {
     } else if (data.type === 'polygon') {
       // 绘制多边形
       createPolygon(data);
-    } else if (data.type === 'polygon') {
-      // 绘制多边形
-      createPolygon(data);
     } else if (data.type === 'marker') {
       // 绘制图标
       createMarker(data);
+    } else if (data.type === 'measureArea') {
+      // 绘制图标
+      createMeasureArea(data);
     }
   };
   // 创建圆形
@@ -283,7 +286,7 @@ export function useDrawTool(options: DrawToolOptions) {
       strokeOpacity: 1,
       strokeWeight: options.lineWidth,
       fillColor: options.color,
-      fillOpacity: options.drawType === '1' ? 0 : 0.5,
+      fillOpacity: options.opacity,
       strokeStyle: 'solid'
     });
     overlays.push(circle);
@@ -300,7 +303,7 @@ export function useDrawTool(options: DrawToolOptions) {
       strokeOpacity: 1,
       strokeWeight: options.lineWidth,
       fillColor: options.color,
-      fillOpacity: options.drawType === '1' ? 0 : 0.5,
+      fillOpacity: options.opacity,
       strokeStyle: 'solid'
     });
     overlays.push(rectangle);
@@ -318,7 +321,7 @@ export function useDrawTool(options: DrawToolOptions) {
       strokeOpacity: 1,
       strokeWeight: options.lineWidth,
       fillColor: options.color,
-      fillOpacity: options.drawType === '1' ? 0 : 0.5,
+      fillOpacity: options.opacity,
       strokeStyle: 'solid'
     });
     overlays.push(polygon);
@@ -326,7 +329,6 @@ export function useDrawTool(options: DrawToolOptions) {
   };
   // 绘制图标
   const createMarker = (options: any) => {
-    debugger
     const marker = new AMap.Marker({
       position: new AMap.LngLat(116.38, 39.92),
       // 将一张图片的地址设置为 icon
@@ -335,7 +337,32 @@ export function useDrawTool(options: DrawToolOptions) {
       anchor: 'bottom-center'
     });
     map.add(marker);
-  }
+  };
+  // 绘制测量面积
+  const createMeasureArea = (options: any) => {
+    // 将数组转换为AMap.LngLat对象的数组
+    const path = options.path.map((coord) => {
+      return new AMap.LngLat(coord[0], coord[1]);
+    });
+    const polygon = new AMap.Polygon({
+      path: path,
+      strokeColor: options.color,
+      strokeOpacity: 1,
+      strokeWeight: options.lineWidth,
+      fillColor: options.color,
+      fillOpacity: options.opacity,
+      strokeStyle: 'solid'
+    });
+    // 计算区域面积
+    const area = Math.round(AMap.GeometryUtil.ringArea(options.path));
+    const text = new AMap.Text({
+      position: path[path.length - 1],
+      text: '区域面积' + area + '平方米',
+      offset: new AMap.Pixel(-20, -20)
+    });
+    map.add(polygon);
+    map.add(text);
+  };
   // 处理撤销
   const handleUndo = () => {
     const previous = history.value[history.value.length - 2];

+ 7 - 0
src/types/components.d.ts

@@ -45,6 +45,9 @@ declare module 'vue' {
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
+    ElPopover: typeof import('element-plus/es')['ElPopover']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
@@ -63,6 +66,8 @@ declare module 'vue' {
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
+    ElTree: typeof import('element-plus/es')['ElTree']
+    ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']
     FooterSection: typeof import('./../components/FooterSection/index.vue')['default']
@@ -73,6 +78,7 @@ declare module 'vue' {
     HikvisionPlayer: typeof import('./../components/HKVideo/hikvision-player.vue')['default']
     HKVideo: typeof import('./../components/HKVideo/index.vue')['default']
     IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
+    IEpUploadFilled: typeof import('~icons/ep/upload-filled')['default']
     IFrame: typeof import('./../components/iFrame/index.vue')['default']
     ImagePreview: typeof import('./../components/ImagePreview/index.vue')['default']
     ImageUpload: typeof import('./../components/ImageUpload/index.vue')['default']
@@ -101,6 +107,7 @@ declare module 'vue' {
     UserSelect: typeof import('./../components/UserSelect/index.vue')['default']
     VideoContainer: typeof import('./../components/HKVideo/video-container.vue')['default']
     YMap: typeof import('./../components/Map/YMap.vue')['default']
+    YMapold: typeof import('./../components/Map/YMapold.vue')['default']
     YztMap: typeof import('./../components/Map/YztMap/index.vue')['default']
   }
   export interface ComponentCustomProperties {

+ 105 - 27
src/views/globalMap/RightMenu/OnlinePlotting.vue

@@ -25,19 +25,19 @@
       >
         {{ item.name }}
       </div>
-      <div class="tab-content2">
-        <div
-          v-for="(item, index) in menu[menuActive1].children[menuActive2].children"
-          :key="index"
-          :class="menuActive2 === index ? 'tab tab_active' : 'tab'"
-          @click="clickTab3(item)"
-        >
-          {{ item.name }}
-        </div>
+    </div>
+    <div class="tab-content2">
+      <div
+        v-for="(item, index) in menu[menuActive1].children[menuActive2].children"
+        :key="index"
+        :class="menuActive3 === index ? 'tab tab_active' : 'tab'"
+        @click="clickTab3(item, index)"
+      >
+        {{ item.name }}
       </div>
     </div>
   </div>
-  <div v-show="menuActive1 === 1" class="tab-content">历史记录</div>
+  <div v-show="menuActive1 === 1" class="tab-content">历史预案</div>
   <div v-show="textEditState.showTextEdit" class="text-edit-container">
     <el-input v-model="textEditState.text" :rows="8" type="textarea" />
     <div class="edit-box">
@@ -55,6 +55,8 @@
       <el-button type="primary" size="large" @click="addText">确定</el-button>
     </div>
   </div>
+  <!--绘制提示信息-->
+  <div v-show="tipTitle !== ''" class="tipTitle">{{ tipTitle }}</div>
 </template>
 
 <script lang="ts" setup>
@@ -70,8 +72,9 @@ const getMouseTool = inject('getMouseTool');
 const updateMouseToolState = inject('updateMouseToolState');
 const undo = inject('undo');
 
-const menuActive1 = ref(0);
-const menuActive2 = ref(0);
+const menuActive1 = ref<string | number>(0);
+const menuActive2 = ref<string | number>(0);
+const menuActive3 = ref<string | number>('');
 const menu = ref([
   {
     name: '标绘工具',
@@ -80,10 +83,10 @@ const menu = ref([
         name: '基本工具',
         value: 'basicTools',
         children: [
-          {
-            name: '直箭头',
-            value: 'straightArrow'
-          },
+          // {
+          //   name: '直箭头',
+          //   value: 'straightArrow'
+          // },
           {
             name: '矩形',
             value: 'rectangle'
@@ -92,10 +95,10 @@ const menu = ref([
             name: '任意面',
             value: 'polygon'
           },
-          {
-            name: '任意线',
-            value: 'anyLine'
-          },
+          // {
+          //   name: '任意线',
+          //   value: 'anyLine'
+          // },
           {
             name: '圆',
             value: 'circle'
@@ -110,7 +113,7 @@ const menu = ref([
           },
           {
             name: '面积',
-            value: ''
+            value: 'measureArea'
           }
         ]
       },
@@ -150,6 +153,34 @@ const textEditState = reactive({
   text: '',
   lnglat: []
 });
+watch(
+  () => props.drawing,
+  () => {
+    if (!props.drawing) {
+      menuActive3.value = '';
+    }
+  }
+);
+const tipTitle = computed(() => {
+  let res = '';
+  if (
+    menu.value[menuActive1.value] &&
+    menu.value[menuActive1.value].children &&
+    menu.value[menuActive1.value].children[menuActive2.value] &&
+    menu.value[menuActive1.value].children[menuActive2.value].children &&
+    menu.value[menuActive1.value].children[menuActive2.value].children[menuActive3.value]
+  ) {
+    const data = menu.value[menuActive1.value].children[menuActive2.value].children[menuActive3.value];
+    if (data.value === 'straightArrow') {
+      res = '单击开始、单击结束';
+    } else if (['rectangle', 'polygon', 'anyLine', 'circle'].includes(data.value)) {
+      res = '鼠标按住拖曳,松开鼠标结束标绘';
+    } else if (['straightLine', 'measureArea'].includes(data.value)) {
+      res = '单击开始,移动,单击改变方向,双击结束';
+    }
+  }
+  return res;
+});
 
 // 点击一级菜单
 const clickTab = (value: number) => {
@@ -160,12 +191,11 @@ const clickTab2 = (value: number) => {
   menuActive2.value = value;
 };
 // 点击三级菜单
-const clickTab3 = (item) => {
+const clickTab3 = (item, index) => {
   const type = item.value;
-  if (
-    props.mouseToolState.graphicsType !== type ||
-    (props.mouseToolState.graphicsType === 'marker' && props.mouseToolState.title !== item.name)
-  ) {
+  let flag: boolean;
+  if (props.mouseToolState.graphicsType !== type || (props.mouseToolState.graphicsType === 'marker' && props.mouseToolState.title !== item.name)) {
+    flag = true;
     if (type === 'text') {
       handleTextEdit();
     } else if (type === 'marker') {
@@ -185,10 +215,14 @@ const clickTab3 = (item) => {
       props.mouseToolState.graphicsType = type;
     }
   } else {
+    flag = false;
     textEditState.showTextEdit = false;
     emits('updateDrawing', false);
     props.mouseToolState.graphicsType = '';
   }
+  if (flag) {
+    menuActive3.value = index;
+  }
 };
 const handleTextEdit = () => {
   const map = getMap();
@@ -206,7 +240,7 @@ const addText = () => {
   const data = {
     graphicsType: 'text',
     lineWidth: props.mouseToolState.lineWidth,
-    color: props.mouseToolState.lineWidth,
+    color: props.mouseToolState.color,
     text: textEditState.text,
     fontColor: textEditState.fontColor,
     fontSize: textEditState.fontSize,
@@ -245,6 +279,38 @@ const changeDrawing = () => {
 :deep(.el-color-dropdown__link-btn) {
   display: none;
 }
+
+.tabs1 {
+  display: flex;
+}
+.tab-content {
+  display: flex;
+  margin-top: 20px;
+  .tab-content2 {
+    display: flex;
+    flex-wrap: wrap;
+    margin-left: 20px;
+    .tab {
+      padding: 0 10px;
+      height: 50px;
+      line-height: 50px;
+      border: 1px solid #000;
+      border-radius: 8px;
+      margin-right: 8px;
+      cursor: pointer;
+      &:hover {
+        border: 1px solid #40a2e7;
+        background-color: #40a2e7;
+        color: #fff;
+      }
+    }
+    .tab_active {
+      border: 1px solid #40a2e7;
+      background-color: #40a2e7;
+      color: #fff;
+    }
+  }
+}
 .text-edit-container {
   position: fixed;
   top: 500px;
@@ -273,4 +339,16 @@ const changeDrawing = () => {
     }
   }
 }
+.tipTitle {
+  position: fixed;
+  top: 300px;
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 2;
+  padding: 10px 30px;
+  font-size: 38px;
+  color: #fff;
+  background-color: rgba(0, 0, 0, 0.4);
+  border-radius: 10px;
+}
 </style>

+ 2 - 1
src/views/globalMap/RightMenu/index.vue

@@ -52,10 +52,11 @@ import Reservoir from './Reservoir.vue';
 import SpatialAnalysis from '@/views/globalMap/RightMenu/SpatialAnalysis.vue';
 import LayerAnalysis from '@/views/globalMap/RightMenu/LayerAnalysis.vue';
 import OnlinePlotting from '@/views/globalMap/RightMenu/OnlinePlotting.vue';
+import { PointType } from '@/api/globalMap/type';
 
 interface Props {
   drawing: boolean;
-  pointType: string[];
+  pointType: PointType;
   mouseToolState: MouseTool;
 }
 

+ 19 - 6
src/views/globalMap/index.vue

@@ -9,7 +9,7 @@
         :mouseToolState="mouseToolState"
         :active-map="activeMap"
         :pointType="pointType"
-        @select-graphics="analysisSpatial"
+        @onDrawCompleted="onDrawCompleted"
       />
       <Map
         v-else
@@ -18,8 +18,7 @@
         :mouseToolState="mouseToolState"
         :active-map="activeMap"
         :pointType="pointType"
-        @select-graphics="analysisSpatial"
-        @un-select-graphics="unSelectGraphics"
+        @onDrawCompleted="onDrawCompleted"
       />
       <!--左侧菜单-->
       <LeftMenu style="position: absolute; top: 20px; left: 20px" @click-menu="clickMenu" @select-search-marker="selectSearchMarker" />
@@ -66,8 +65,8 @@ const rightMenuRef = ref(null);
 const mapData = reactive(logicalData);
 let mapRef = ref(null);
 let map2Ref = ref(null);
-// logical vectorgraph satellite satellite2
-let activeMap = ref('logical');
+// logical vectorgraph satellite satellite2 satellite3
+let activeMap = ref('vectorgraph');
 
 const switchMap = (key) => {
   activeMap.value = key;
@@ -171,8 +170,22 @@ const undo = () => {
   dom.handleUndo();
 };
 let selectedScope = reactive({});
+// 绘制结束事件
+const onDrawCompleted = (data, overlaysData, obj) => {
+  drawing.value = false;
+  if (overlaysData.length === 1) {
+    analysisSpatial(data);
+  }
+  // 点击空间分析
+  obj.on('click', function () {
+    // 没在编辑时
+    if (!drawing.value) {
+      analysisSpatial(data);
+    }
+  });
+};
 // 空间分析数据
-const analysisSpatial = (data, len?: string) => {
+const analysisSpatial = (data) => {
   // 已选中的范围
   if (selectedScope[data.id]) {
     delete selectedScope[data.id];