CzRger 1 년 전
부모
커밋
18a33c4fef
4개의 변경된 파일179개의 추가작업 그리고 43개의 파일을 삭제
  1. 0 2
      src/router/index.ts
  2. 41 2
      src/utils/util.ts
  3. 137 25
      src/views/screen/video-resource/index.vue
  4. 1 14
      src/views/screen/video-resource/map-style.ts

+ 0 - 2
src/router/index.ts

@@ -28,8 +28,6 @@ const router = createRouter({
 });
 
 router.beforeEach((to, from, next) => {
-    console.info(to)
-
     if (to.meta.noLogin) {
         next()
     } else {

+ 41 - 2
src/utils/util.ts

@@ -130,6 +130,45 @@ export const formatUrlByInfo = (url: string) => {
 
 
 //生成从minNum到maxNum的随机数
-export  const randomNum = (minNum: number,maxNum: number) => {
-  return parseInt(String(Math.random() * (maxNum - minNum + 1) + minNum),10);
+// export  const randomNum = (minNum: number,maxNum: number) => {
+//   return parseInt(String(Math.random() * (maxNum - minNum + 1) + minNum),10);
+// }
+
+export const randomNum = (min = 0, max = 0, decimal=0) => {
+  // 获取数值的小数部分
+  const getDecimalNum = (data: number) => {
+    return Number(data.toString().split('.')[1]);
+  }
+  let min_z = Math.trunc(min); // 最小值的整数部分
+  let max_z = Math.trunc(max); // 最大值的整数部分
+  // 判断是否存在小数部分,不存在的话为0
+  let min_x = isNaN(getDecimalNum(min)) ? 0 : getDecimalNum(min);  // 最小值的小数部分
+  let max_x = isNaN(getDecimalNum(max)) ? 0 : getDecimalNum(max);  // 最大值的小数部分
+
+  // 区分有小数和没小数的情况
+  if (min_x > 0 || max_x > 0 || decimal > 0) {
+    // 整数部分随机数
+    let z = parseInt(String(Math.random() * (max_z - min_z + 1) + min_z), 10);
+    // 小数部分随机数
+    let x = 0;
+    // 小数部分随机数最大位数
+    let max_decimal = min_x.toString().length > max_x.toString().length ? min_x.toString().length : max_x.toString().length;
+    max_decimal = decimal > max_decimal ? decimal : max_decimal;
+    // 判断随机出的整数部分,是否等于最小值或者最大值
+    if(z == min_z || z == max_z){
+      if(z == min_z){
+        // 整数部分随机数等于最小值,那么应该从最小值的小数部分开始,到小数位数的最大值随机就可以
+        x = parseInt(String(Math.random() * (Math.pow(10, max_decimal) - min_x) + min_x), 10);
+      }else{
+        // 整数部分随机数等于最大值,那么应该从0开始,到最大值小数部分
+        x = parseInt(String(Math.random() * (max_x + 1)), 10);
+      }
+    }else{
+      // 整数部分在最大最小值区间的,就从0到小数位数的最大值随机就可以
+      x = parseInt(String(Math.random() * (Math.pow(10, max_decimal))), 10);
+    }
+    return Number(`${z}.${x}`);
+  } else {
+    return parseInt(String(Math.random() * (max_z - min_z + 1) + min_z), 10);
+  }
 }

+ 137 - 25
src/views/screen/video-resource/index.vue

@@ -1,10 +1,22 @@
 <template>
   <div class="video-resource">
+    <div class="buttons">
+      <el-button @click="addFeatures">随机新增</el-button>
+      <el-input v-model="sss"></el-input>
+      <el-button @click="delFeatures">删除一个</el-button>
+      <el-button @click="clearFeatures">清空</el-button>
+    </div>
     <EasyMapComponent
         class="map"
         :showBaseSwitch="false"
         @easyMapLoad="mapLoad"
     />
+    <div ref="ref_pointHoverOverlay" class="hover-info">
+      {{ pointHoverInfo.id }}
+    </div>
+    <div ref="ref_pointClickOverlay" class="click-info">
+      {{ pointClickInfo.id }}
+    </div>
   </div>
 </template>
 
@@ -25,6 +37,11 @@ import {useStore} from 'vuex'
 import axios from "axios";
 import {ElMessage, ElMessageBox} from "element-plus";
 import MapStyle from "@/views/screen/video-resource/map-style";
+import * as source from "ol/source";
+import * as layer from "ol/layer";
+import * as format from "ol/format";
+import {randomNum} from "@/utils/util";
+import * as ol from "ol";
 
 export default defineComponent({
   name: 'App',
@@ -35,39 +52,129 @@ export default defineComponent({
     const state = reactive({
       map: <any>null,
       mapFunc: null,
-      videoLayer: null
+      pointLayer: <any>null,
+      pointSource: <any>null,
+      pointHoverOverlay: <any>null,
+      pointClickOverlay: <any>null,
+      pointHoverInfo: <any>{},
+      pointClickInfo: <any>{},
+      sss: ''
     });
+    const ref_pointHoverOverlay = ref()
+    const ref_pointClickOverlay = ref()
     const mapLoad = (map: null, func: null) => {
       state.map = map
       state.mapFunc = func
-      that.$easyMap.initShape({
-        map: state.map,
-        layerName: "track-point-line",
-        layerZIndex: 7,
-        list: [
-          {
-            easyMapParams: {
-              id: `1`,
-              position: 'POINT(109.19 19.45)',
-              normalStyle: MapStyle.videoPointStyle()
-            }
-          },
-          {
-            easyMapParams: {
-              id: `2`,
-              position: 'POLYGON((108.26 19.07, 110.19 18.45, 111.19 20.45,109.19 19.45))',
-              normalStyle: MapStyle.normalStyleArea()
-            }
-          },
-        ]
-      });
-      const addFeatures = (arr: any) => {}
-      const delFeatures = (arr: any) => {}
+      // 初始化source
+      state.pointSource = new source.Vector({
+        features: [],
+        wrapX: false
+      })
+      // 初始化layer
+      state.pointLayer = new layer.VectorImage({
+        source: state.pointSource,
+        zIndex: 10,
+        style: (feat: any) => {
+          feat.setStyle(MapStyle.videoPointStyle())
+        }
+      })
+      state.map.addLayer(state.pointLayer)
+      //  初始化悬浮
+      state.pointHoverOverlay = new ol.Overlay({
+        id: 'pointHoverOverlay',
+        element: ref_pointHoverOverlay.value,
+        autoPan: false,
+        offset: [0, -40],
+        positioning: 'top-center',
+        stopEvent: true,
+        autoPanAnimation: {
+          duration: 250
+        }
+      })
+      state.map.addOverlay(state.pointHoverOverlay)
+      state.map.on('pointermove', (e: {
+          coordinate(coordinate: any): unknown; pixel: any;
+      }) => {
+        state.pointHoverOverlay.setPosition(undefined)
+        state.pointHoverInfo = {}
+        state.map.forEachFeatureAtPixel(e.pixel, (f: any) => {
+          if (f.get('layerType') === 'video') {
+            state.pointHoverInfo = f.get('val')
+            state.pointHoverOverlay.setPosition(e.coordinate)
+          }
+        }, {
+          hitTolerance: 0,
+        });
+      })
+      //  初始化点击
+      state.pointClickOverlay = new ol.Overlay({
+        id: 'pointClickOverlay',
+        element: ref_pointClickOverlay.value,
+        autoPan: false,
+        offset: [0, 0],
+        positioning: 'top-left',
+        stopEvent: true,
+        autoPanAnimation: {
+          duration: 250
+        }
+      })
+      state.map.addOverlay(state.pointClickOverlay)
+      state.map.on('singleclick', (e: {
+          coordinate(coordinate: any): unknown; pixel: any;
+      }) => {
+        state.pointClickOverlay.setPosition(undefined)
+        state.pointHoverInfo = {}
+        state.map.forEachFeatureAtPixel(e.pixel, (f: any) => {
+          if (f.get('layerType') === 'video') {
+            state.pointClickInfo = f.get('val')
+            state.pointClickOverlay.setPosition(e.coordinate)
+          }
+        }, {
+          hitTolerance: 0,
+        });
+      })
+    }
+    const mockWKT = () => {
+      const lon = that.$util.randomNum(108, 111, 6)
+      const lat = that.$util.randomNum(18, 20, 6)
+      return `POINT(${lon} ${lat})`
+    }
+    const addFeatures = (arr: any) => {
+      arr = []
+      for (let i = 0; i < 8; i++) {
+        arr.push({
+          wkt: mockWKT(),
+          id: `点位_${new Date().getTime()}_${i}`,
+        })
+      }
+      arr.forEach((v: any, i: number) => {
+        const feat = new format.WKT().readFeature(v.wkt)
+        feat.setId(v.id)
+        feat.set('val', v)
+        feat.set('layerType', 'video')
+        state.pointSource.addFeature(feat)
+      })
+    }
+    const delFeatures = (arr: any) => {
+      state.sss.split(',').forEach(v => {
+        console.log(state.pointSource.getFeatureById(v))
+        if (state.pointClickInfo.id === v) {
+          state.pointClickOverlay.setPosition(undefined)
+        }
+        state.pointSource.removeFeature(state.pointSource.getFeatureById(v))
+      })
+    }
+    const clearFeatures = () => {
+      state.pointSource.clear()
     }
-
     return {
       ...toRefs(state),
       mapLoad,
+      addFeatures,
+      delFeatures,
+      clearFeatures,
+      ref_pointHoverOverlay,
+      ref_pointClickOverlay,
     }
   }
 })
@@ -82,5 +189,10 @@ export default defineComponent({
     width: 100%;
     height: 100vh;
   }
+  .click-info {
+    width: 300px;
+    height: 100px;
+    background-color: red;
+  }
 }
 </style>

+ 1 - 14
src/views/screen/video-resource/map-style.ts

@@ -22,20 +22,7 @@ const videoPointStyle = () => {
     }))
     return _style
 }
-const normalStyleArea = () => {
-    const _style = []
-    _style.push(new style.Style({
-        stroke: new style.Stroke({
-            color: '#ed3880',
-            width: 2,
-        }),
-        fill: new style.Fill({
-            color: 'rgba(47,232,217,0.35)',
-        }),
-    }))
-    return _style
-}
+
 export default {
     videoPointStyle,
-    normalStyleArea
 }