瀏覽代碼

根据移动地图更新点位

xsh_1997 1 月之前
父節點
當前提交
ee7100c511
共有 2 個文件被更改,包括 101 次插入22 次删除
  1. 92 22
      ruoyi-screen/src/components/GisMap.vue
  2. 9 0
      ruoyi-screen/src/utils/gisTownshipBoundary.js

+ 92 - 22
ruoyi-screen/src/components/GisMap.vue

@@ -22,7 +22,6 @@ import {
22 22
   buildTownshipInfo,
23 23
   flyToTownship,
24 24
   getTownshipLabelPoints,
25
-  getTownshipPoiSearchCenter,
26 25
   removeTownshipBoundaryLayers
27 26
 } from '@/utils/gisTownshipBoundary'
28 27
 import { getTownshipLivestockStats } from '@/constants/townshipLivestock'
@@ -48,7 +47,7 @@ const props = defineProps({
48 47
     type: Boolean,
49 48
     default: false
50 49
   },
51
-  /** 点击乡镇后是否展示该乡镇中心点周边 POI(默认不加载,点击后才查) */
50
+  /** 是否展示地图中心点周边 POI(移动地图后防抖查询) */
52 51
   showPoiMarkers: {
53 52
     type: Boolean,
54 53
     default: true
@@ -87,6 +86,10 @@ let unbindWheelZoom = null
87 86
 /** 滚轮缩放防抖:停止滚动后再合并应用,减少瓦片 canceled */
88 87
 const WHEEL_ZOOM_DEBOUNCE_MS = 150
89 88
 const WHEEL_ZOOM_RATE = 0.0022
89
+/** 地图移动结束后防抖再查 POI,避免拖拽过程中频繁请求 */
90
+const POI_SEARCH_DEBOUNCE_MS = 400
91
+/** 仅 zoom >= 16 时查询并展示 POI */
92
+const POI_SEARCH_MIN_ZOOM = 16
90 93
 
91 94
 let wheelDeltaAccum = 0
92 95
 let wheelDebounceTimer = null
@@ -94,8 +97,68 @@ let lastWheelAround = null
94 97
 let poiMarkers = []
95 98
 let townshipMarkers = []
96 99
 let unbindTownshipClick = null
97
-/** 当前 POI 查询中心,仅点击乡镇后赋值 */
98
-let poiSearchCenter = null
100
+let unbindPoiSearch = null
101
+let poiSearchDebounceTimer = null
102
+
103
+function getMapViewCenter() {
104
+  if (!map || typeof map.getCenter !== 'function') {
105
+    return null
106
+  }
107
+  const center = map.getCenter()
108
+  const lng = Number(center?.lng ?? center?.[0])
109
+  const lat = Number(center?.lat ?? center?.[1])
110
+  if (!Number.isFinite(lng) || !Number.isFinite(lat)) {
111
+    return null
112
+  }
113
+  return [lng, lat]
114
+}
115
+
116
+function getMapZoom() {
117
+  if (!map || typeof map.getZoom !== 'function') {
118
+    return null
119
+  }
120
+  const zoom = map.getZoom()
121
+  return Number.isFinite(zoom) ? zoom : null
122
+}
123
+
124
+function shouldSearchPoiAtCurrentZoom() {
125
+  const zoom = getMapZoom()
126
+  return zoom != null && zoom >= POI_SEARCH_MIN_ZOOM
127
+}
128
+
129
+function schedulePoiSearch() {
130
+  if (!props.showPoiMarkers || !map) {
131
+    return
132
+  }
133
+  if (poiSearchDebounceTimer) {
134
+    clearTimeout(poiSearchDebounceTimer)
135
+  }
136
+  poiSearchDebounceTimer = setTimeout(() => {
137
+    poiSearchDebounceTimer = null
138
+    if (!shouldSearchPoiAtCurrentZoom()) {
139
+      clearPoiMarkers()
140
+      return
141
+    }
142
+    renderPoiMarkers()
143
+  }, POI_SEARCH_DEBOUNCE_MS)
144
+}
145
+
146
+function bindPoiSearchListener() {
147
+  if (!map || typeof map.on !== 'function') {
148
+    return () => {}
149
+  }
150
+  const onMoveEnd = () => {
151
+    schedulePoiSearch()
152
+  }
153
+  map.on('moveend', onMoveEnd)
154
+  return () => {
155
+    if (poiSearchDebounceTimer) {
156
+      clearTimeout(poiSearchDebounceTimer)
157
+      poiSearchDebounceTimer = null
158
+    }
159
+    map.off('moveend', onMoveEnd)
160
+  }
161
+}
99 162
 
100 163
 function logClickCoordinate(lngLat) {
101 164
   if (!lngLat) {
@@ -176,16 +239,6 @@ function bindTownshipDrillDown() {
176 239
       zoom: props.townshipDrillMaxZoom
177 240
     })
178 241
     emit('township-click', info)
179
-
180
-    if (props.showPoiMarkers) {
181
-      const searchCenter = getTownshipPoiSearchCenter(feature)
182
-      if (searchCenter) {
183
-        poiSearchCenter = searchCenter
184
-        map.once('moveend', () => {
185
-          renderPoiMarkers()
186
-        })
187
-      }
188
-    }
189 242
   })
190 243
 }
191 244
 
@@ -285,16 +338,24 @@ function createPoiMarkerElement(name) {
285 338
 }
286 339
 
287 340
 async function renderPoiMarkers() {
288
-  if (!props.showPoiMarkers || !map || !cmmapglRef || !poiSearchCenter) {
341
+  if (!props.showPoiMarkers || !map || !cmmapglRef) {
289 342
     return
290 343
   }
344
+  if (!shouldSearchPoiAtCurrentZoom()) {
345
+    clearPoiMarkers()
346
+    return
347
+  }
348
+
349
+  const center = getMapViewCenter()
350
+  if (!center) {
351
+    return
352
+  }
353
+
291 354
   clearPoiMarkers()
292 355
 
293 356
   let pois = []
294 357
   try {
295
-    pois = await searchNearbyPois({
296
-      center: poiSearchCenter
297
-    })
358
+    pois = await searchNearbyPois({ center })
298 359
   } catch {
299 360
     return
300 361
   }
@@ -328,6 +389,10 @@ async function renderPoiMarkers() {
328 389
 }
329 390
 
330 391
 function destroyMap() {
392
+  if (typeof unbindPoiSearch === 'function') {
393
+    unbindPoiSearch()
394
+    unbindPoiSearch = null
395
+  }
331 396
   if (typeof unbindWheelZoom === 'function') {
332 397
     unbindWheelZoom()
333 398
     unbindWheelZoom = null
@@ -335,7 +400,6 @@ function destroyMap() {
335 400
   wheelDeltaAccum = 0
336 401
   lastWheelAround = null
337 402
   clampingZoom = false
338
-  poiSearchCenter = null
339 403
   clearPoiMarkers()
340 404
   teardownTownshipBoundary()
341 405
   if (map) {
@@ -569,6 +633,7 @@ async function initMap() {
569 633
     bindMapListeners()
570 634
     bindZoomClampListener()
571 635
     unbindWheelZoom = bindDebouncedWheelZoom()
636
+    unbindPoiSearch = bindPoiSearchListener()
572 637
     configureScrollZoom()
573 638
     map.on('load', () => {
574 639
       applyMapLimits()
@@ -577,6 +642,7 @@ async function initMap() {
577 642
       syncWmtsLayerVisibility(map)
578 643
       resizeMap()
579 644
       renderTownshipBoundary()
645
+      schedulePoiSearch()
580 646
       emit('ready', map)
581 647
     })
582 648
     // 瓦片/遥测等非致命错误不向页面报错
@@ -602,9 +668,13 @@ watch(
602 668
   () => props.showPoiMarkers,
603 669
   (show) => {
604 670
     if (!map || !cmmapglRef) return
605
-    if (show && poiSearchCenter) {
606
-      renderPoiMarkers()
607
-    } else if (!show) {
671
+    if (show) {
672
+      schedulePoiSearch()
673
+    } else {
674
+      if (poiSearchDebounceTimer) {
675
+        clearTimeout(poiSearchDebounceTimer)
676
+        poiSearchDebounceTimer = null
677
+      }
608 678
       clearPoiMarkers()
609 679
     }
610 680
   }

+ 9 - 0
ruoyi-screen/src/utils/gisTownshipBoundary.js

@@ -70,6 +70,15 @@ export function getTownshipPoiSearchCenter(feature) {
70 70
   return null
71 71
 }
72 72
 
73
+/** POI 多边形搜索范围:取乡镇边界外环 [经度, 纬度][] */
74
+export function getTownshipPoiSearchPolygon(feature) {
75
+  const ring = getPolygonOuterRing(feature)
76
+  if (!Array.isArray(ring) || ring.length < 3) {
77
+    return null
78
+  }
79
+  return ring.map(([lng, lat]) => [Number(lng), Number(lat)])
80
+}
81
+
73 82
 export function getTownshipGeoJson() {
74 83
   return townshipGeoJson
75 84
 }