expo-gaode-map 2.2.30-next.0 → 2.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +4 -2
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +117 -57
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapViewModule.kt +8 -15
- package/android/src/main/java/expo/modules/gaodemap/managers/UIManager.kt +20 -6
- package/android/src/main/java/expo/modules/gaodemap/overlays/ClusterView.kt +24 -13
- package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerBitmapRenderer.kt +351 -0
- package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerView.kt +94 -310
- package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerViewModule.kt +3 -3
- package/build/ExpoGaodeMapModule.d.ts +13 -5
- package/build/ExpoGaodeMapModule.d.ts.map +1 -1
- package/build/ExpoGaodeMapModule.js +166 -34
- package/build/ExpoGaodeMapModule.js.map +1 -1
- package/build/ExpoGaodeMapView.d.ts.map +1 -1
- package/build/ExpoGaodeMapView.js +12 -0
- package/build/ExpoGaodeMapView.js.map +1 -1
- package/build/components/AreaMaskOverlay.d.ts +5 -0
- package/build/components/AreaMaskOverlay.d.ts.map +1 -0
- package/build/components/AreaMaskOverlay.js +20 -0
- package/build/components/AreaMaskOverlay.js.map +1 -0
- package/build/components/FoldableMapView.d.ts.map +1 -1
- package/build/components/FoldableMapView.js +115 -104
- package/build/components/FoldableMapView.js.map +1 -1
- package/build/components/RouteOverlay.d.ts +5 -0
- package/build/components/RouteOverlay.d.ts.map +1 -0
- package/build/components/RouteOverlay.js +20 -0
- package/build/components/RouteOverlay.js.map +1 -0
- package/build/components/overlays/Cluster.d.ts.map +1 -1
- package/build/components/overlays/Cluster.js +12 -0
- package/build/components/overlays/Cluster.js.map +1 -1
- package/build/components/overlays/Marker.d.ts.map +1 -1
- package/build/components/overlays/Marker.js +86 -3
- package/build/components/overlays/Marker.js.map +1 -1
- package/build/hooks/useRoutePlayback.d.ts +4 -0
- package/build/hooks/useRoutePlayback.d.ts.map +1 -0
- package/build/hooks/useRoutePlayback.js +310 -0
- package/build/hooks/useRoutePlayback.js.map +1 -0
- package/build/index.d.ts +4 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4 -2
- package/build/index.js.map +1 -1
- package/build/types/common.types.d.ts +29 -5
- package/build/types/common.types.d.ts.map +1 -1
- package/build/types/common.types.js +5 -5
- package/build/types/common.types.js.map +1 -1
- package/build/types/index.d.ts +3 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js.map +1 -1
- package/build/types/location.types.d.ts +28 -0
- package/build/types/location.types.d.ts.map +1 -1
- package/build/types/location.types.js +5 -0
- package/build/types/location.types.js.map +1 -1
- package/build/types/map-view.types.d.ts +22 -22
- package/build/types/map-view.types.d.ts.map +1 -1
- package/build/types/map-view.types.js.map +1 -1
- package/build/types/native-module.types.d.ts +2 -2
- package/build/types/native-module.types.d.ts.map +1 -1
- package/build/types/native-module.types.js.map +1 -1
- package/build/types/overlays.types.d.ts +14 -0
- package/build/types/overlays.types.d.ts.map +1 -1
- package/build/types/overlays.types.js.map +1 -1
- package/build/types/route-playback.types.d.ts +118 -0
- package/build/types/route-playback.types.d.ts.map +1 -0
- package/build/types/route-playback.types.js +2 -0
- package/build/types/route-playback.types.js.map +1 -0
- package/build/utils/RouteUtils.d.ts +8 -0
- package/build/utils/RouteUtils.d.ts.map +1 -0
- package/build/utils/RouteUtils.js +140 -0
- package/build/utils/RouteUtils.js.map +1 -0
- package/ios/ExpoGaodeMapModule.swift +41 -22
- package/ios/ExpoGaodeMapView.swift +236 -241
- package/ios/ExpoGaodeMapViewModule.swift +16 -11
- package/ios/managers/UIManager.swift +5 -4
- package/ios/modules/LocationManager.swift +32 -9
- package/ios/overlays/ClusterView.swift +114 -12
- package/ios/overlays/ClusterViewModule.swift +5 -1
- package/ios/overlays/MarkerView.swift +195 -18
- package/ios/overlays/MarkerViewModule.swift +7 -7
- package/package.json +6 -6
- package/build/utils/throttle.d.ts +0 -10
- package/build/utils/throttle.d.ts.map +0 -1
- package/build/utils/throttle.js +0 -19
- package/build/utils/throttle.js.map +0 -1
|
@@ -2,6 +2,7 @@ import ExpoModulesCore
|
|
|
2
2
|
import MAMapKit
|
|
3
3
|
import MapKit
|
|
4
4
|
import CoreLocation
|
|
5
|
+
import QuartzCore
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* 高德地图视图组件
|
|
@@ -15,8 +16,8 @@ import CoreLocation
|
|
|
15
16
|
class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate {
|
|
16
17
|
// MARK: - 属性
|
|
17
18
|
|
|
18
|
-
/// 地图类型 (
|
|
19
|
-
var mapType: Int =
|
|
19
|
+
/// 地图类型 (1:标准 2:卫星 3:夜间 4:导航 5:公交)
|
|
20
|
+
var mapType: Int = 1
|
|
20
21
|
/// 初始相机位置
|
|
21
22
|
var initialCameraPosition: [String: Any]?
|
|
22
23
|
/// 是否显示缩放控件
|
|
@@ -51,6 +52,19 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
51
52
|
var showsBuildings: Bool = false
|
|
52
53
|
/// 是否显示室内地图
|
|
53
54
|
var showsIndoorMap: Bool = false
|
|
55
|
+
/// 定位最小更新距离
|
|
56
|
+
var distanceFilter: CLLocationDistance = kCLDistanceFilterNone
|
|
57
|
+
/// 朝向最小更新角度
|
|
58
|
+
var headingFilter: CLLocationDegrees = kCLHeadingFilterNone
|
|
59
|
+
/// 相机移动事件节流间隔(毫秒)
|
|
60
|
+
var cameraEventThrottleMs: Int = 32 {
|
|
61
|
+
didSet {
|
|
62
|
+
if cameraEventThrottleMs == 0 {
|
|
63
|
+
cameraMoveDispatchWorkItem?.cancel()
|
|
64
|
+
cameraMoveDispatchWorkItem = nil
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
54
68
|
/// 自定义地图样式配置
|
|
55
69
|
var customMapStyleData: [String: Any]?
|
|
56
70
|
/// 是否启用国内外地图自动切换
|
|
@@ -59,6 +73,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
59
73
|
// MARK: - 事件派发器
|
|
60
74
|
|
|
61
75
|
let onMapPress = EventDispatcher()
|
|
76
|
+
let onPressPoi = EventDispatcher()
|
|
62
77
|
let onMapLongPress = EventDispatcher()
|
|
63
78
|
let onLoad = EventDispatcher()
|
|
64
79
|
let onLocation = EventDispatcher()
|
|
@@ -94,6 +109,8 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
94
109
|
|
|
95
110
|
/// 缓存的相机移动事件数据
|
|
96
111
|
private var pendingCameraMoveData: [String: Any]?
|
|
112
|
+
private var cameraMoveDispatchWorkItem: DispatchWorkItem?
|
|
113
|
+
private var lastCameraMoveDispatchTime: CFTimeInterval = 0
|
|
97
114
|
|
|
98
115
|
/// 缩放手势识别器(用于模拟惯性)
|
|
99
116
|
private var pinchGesture: UIPinchGestureRecognizer!
|
|
@@ -185,22 +202,76 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
185
202
|
|
|
186
203
|
// 统一从 overlayViews 数组设置所有覆盖物(包括 MarkerView)
|
|
187
204
|
for view in overlayViews {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
205
|
+
connectOverlayViewToMap(view, mapView: mapView)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private func connectOverlayViewToMap(_ view: UIView, mapView: MAMapView) {
|
|
210
|
+
if let markerView = view as? MarkerView {
|
|
211
|
+
markerView.setMap(mapView)
|
|
212
|
+
} else if let circleView = view as? CircleView {
|
|
213
|
+
circleView.setMap(mapView)
|
|
214
|
+
} else if let polylineView = view as? PolylineView {
|
|
215
|
+
polylineView.setMap(mapView)
|
|
216
|
+
} else if let polygonView = view as? PolygonView {
|
|
217
|
+
polygonView.setMap(mapView)
|
|
218
|
+
} else if let heatMapView = view as? HeatMapView {
|
|
219
|
+
heatMapView.setMap(mapView)
|
|
220
|
+
} else if let multiPointView = view as? MultiPointView {
|
|
221
|
+
multiPointView.setMap(mapView)
|
|
222
|
+
} else if let clusterView = view as? ClusterView {
|
|
223
|
+
clusterView.setMap(mapView)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private func isOverlayView(_ view: UIView) -> Bool {
|
|
228
|
+
view is MarkerView ||
|
|
229
|
+
view is CircleView ||
|
|
230
|
+
view is PolylineView ||
|
|
231
|
+
view is PolygonView ||
|
|
232
|
+
view is HeatMapView ||
|
|
233
|
+
view is MultiPointView ||
|
|
234
|
+
view is ClusterView
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private func registerOverlayView(_ view: UIView) {
|
|
238
|
+
guard !overlayViews.contains(where: { $0 === view }) else {
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
overlayViews.append(view)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private func unregisterOverlayView(_ view: UIView) {
|
|
245
|
+
overlayViews.removeAll { $0 === view }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private func prepareOverlayViewForHosting(_ view: UIView) {
|
|
249
|
+
guard !(view is MarkerView) else {
|
|
250
|
+
return
|
|
203
251
|
}
|
|
252
|
+
|
|
253
|
+
view.alpha = 0
|
|
254
|
+
view.isHidden = true
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@discardableResult
|
|
258
|
+
private func hostOverlayView(_ view: UIView, moveToOverlayContainer: Bool) -> Bool {
|
|
259
|
+
guard isOverlayView(view) else {
|
|
260
|
+
return false
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if moveToOverlayContainer {
|
|
264
|
+
overlayContainer.addSubview(view)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
prepareOverlayViewForHosting(view)
|
|
268
|
+
registerOverlayView(view)
|
|
269
|
+
|
|
270
|
+
if let mapView {
|
|
271
|
+
connectOverlayViewToMap(view, mapView: mapView)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return true
|
|
204
275
|
}
|
|
205
276
|
|
|
206
277
|
/**
|
|
@@ -210,77 +281,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
210
281
|
override func addSubview(_ view: UIView) {
|
|
211
282
|
// 🔑 关键修复:旧架构下统一不移动任何覆盖物视图,避免破坏 React Native 布局
|
|
212
283
|
// 所有覆盖物都隐藏并添加到 overlayViews 数组追踪
|
|
213
|
-
if
|
|
214
|
-
overlayContainer.addSubview(markerView)
|
|
215
|
-
// 🔑 关键:MarkerView 不能隐藏,否则 children 无法渲染成图片
|
|
216
|
-
// 通过 hitTest 返回 nil 已经确保不阻挡地图交互
|
|
217
|
-
overlayViews.append(markerView)
|
|
218
|
-
if let mapView {
|
|
219
|
-
markerView.setMap(mapView)
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if let circleView = view as? CircleView {
|
|
226
|
-
overlayContainer.addSubview(circleView)
|
|
227
|
-
circleView.alpha = 0
|
|
228
|
-
circleView.isHidden = true
|
|
229
|
-
overlayViews.append(circleView)
|
|
230
|
-
if let mapView {
|
|
231
|
-
circleView.setMap(mapView)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return
|
|
235
|
-
} else if let polylineView = view as? PolylineView {
|
|
236
|
-
overlayContainer.addSubview(polylineView)
|
|
237
|
-
polylineView.alpha = 0
|
|
238
|
-
polylineView.isHidden = true
|
|
239
|
-
overlayViews.append(polylineView)
|
|
240
|
-
if let mapView {
|
|
241
|
-
polylineView.setMap(mapView)
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return
|
|
245
|
-
} else if let polygonView = view as? PolygonView {
|
|
246
|
-
overlayContainer.addSubview(polygonView)
|
|
247
|
-
polygonView.alpha = 0
|
|
248
|
-
polygonView.isHidden = true
|
|
249
|
-
overlayViews.append(polygonView)
|
|
250
|
-
if let mapView {
|
|
251
|
-
polygonView.setMap(mapView)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return
|
|
255
|
-
} else if let heatMapView = view as? HeatMapView {
|
|
256
|
-
overlayContainer.addSubview(heatMapView)
|
|
257
|
-
heatMapView.alpha = 0
|
|
258
|
-
heatMapView.isHidden = true
|
|
259
|
-
overlayViews.append(heatMapView)
|
|
260
|
-
if let mapView {
|
|
261
|
-
heatMapView.setMap(mapView)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return
|
|
265
|
-
} else if let multiPointView = view as? MultiPointView {
|
|
266
|
-
overlayContainer.addSubview(multiPointView)
|
|
267
|
-
multiPointView.alpha = 0
|
|
268
|
-
multiPointView.isHidden = true
|
|
269
|
-
overlayViews.append(multiPointView)
|
|
270
|
-
if let mapView {
|
|
271
|
-
multiPointView.setMap(mapView)
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return
|
|
275
|
-
} else if let clusterView = view as? ClusterView {
|
|
276
|
-
overlayContainer.addSubview(clusterView)
|
|
277
|
-
clusterView.alpha = 0
|
|
278
|
-
clusterView.isHidden = true
|
|
279
|
-
overlayViews.append(clusterView)
|
|
280
|
-
if let mapView {
|
|
281
|
-
clusterView.setMap(mapView)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
+
if hostOverlayView(view, moveToOverlayContainer: true) {
|
|
284
285
|
return
|
|
285
286
|
}
|
|
286
287
|
|
|
@@ -304,106 +305,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
304
305
|
}
|
|
305
306
|
|
|
306
307
|
// 🔑 处理 MarkerView - 新架构下直接连接,旧架构下已在 addSubview 处理
|
|
307
|
-
if
|
|
308
|
-
// 检查是否已经在容器中(旧架构下 addSubview 已经处理过)
|
|
309
|
-
if markerView.superview === overlayContainer {
|
|
310
|
-
|
|
311
|
-
return
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// 🔑 新架构下也不能隐藏 MarkerView,否则 children 无法渲染
|
|
315
|
-
overlayViews.append(markerView)
|
|
316
|
-
if let mapView {
|
|
317
|
-
markerView.setMap(mapView)
|
|
318
|
-
}
|
|
319
|
-
// 🔑 关键修复:不再调用 setupAllOverlayViews(),避免所有覆盖物重新设置
|
|
320
|
-
return
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// 🔑 其他覆盖物不移动视图,只设置连接和隐藏
|
|
324
|
-
if let circleView = subview as? CircleView {
|
|
325
|
-
if circleView.superview === overlayContainer {
|
|
326
|
-
|
|
327
|
-
return
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
circleView.alpha = 0
|
|
331
|
-
circleView.isHidden = true
|
|
332
|
-
overlayViews.append(circleView)
|
|
333
|
-
if let mapView {
|
|
334
|
-
circleView.setMap(mapView)
|
|
335
|
-
}
|
|
336
|
-
// 🔑 关键修复:不再调用 setupAllOverlayViews()
|
|
337
|
-
return
|
|
338
|
-
} else if let polylineView = subview as? PolylineView {
|
|
339
|
-
if polylineView.superview === overlayContainer {
|
|
340
|
-
|
|
341
|
-
return
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
polylineView.alpha = 0
|
|
345
|
-
polylineView.isHidden = true
|
|
346
|
-
overlayViews.append(polylineView)
|
|
347
|
-
if let mapView {
|
|
348
|
-
polylineView.setMap(mapView)
|
|
349
|
-
}
|
|
350
|
-
// 🔑 关键修复:不再调用 setupAllOverlayViews()
|
|
351
|
-
return
|
|
352
|
-
} else if let polygonView = subview as? PolygonView {
|
|
353
|
-
if polygonView.superview === overlayContainer {
|
|
354
|
-
|
|
355
|
-
return
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
polygonView.alpha = 0
|
|
359
|
-
polygonView.isHidden = true
|
|
360
|
-
overlayViews.append(polygonView)
|
|
361
|
-
if let mapView {
|
|
362
|
-
polygonView.setMap(mapView)
|
|
363
|
-
}
|
|
364
|
-
// 🔑 关键修复:不再调用 setupAllOverlayViews()
|
|
365
|
-
return
|
|
366
|
-
} else if let heatMapView = subview as? HeatMapView {
|
|
367
|
-
if heatMapView.superview === overlayContainer {
|
|
368
|
-
|
|
369
|
-
return
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
heatMapView.alpha = 0
|
|
373
|
-
heatMapView.isHidden = true
|
|
374
|
-
overlayViews.append(heatMapView)
|
|
375
|
-
if let mapView {
|
|
376
|
-
heatMapView.setMap(mapView)
|
|
377
|
-
}
|
|
378
|
-
// 🔑 关键修复:不再调用 setupAllOverlayViews()
|
|
379
|
-
return
|
|
380
|
-
} else if let multiPointView = subview as? MultiPointView {
|
|
381
|
-
if multiPointView.superview === overlayContainer {
|
|
382
|
-
|
|
383
|
-
return
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
multiPointView.alpha = 0
|
|
387
|
-
multiPointView.isHidden = true
|
|
388
|
-
overlayViews.append(multiPointView)
|
|
389
|
-
if let mapView {
|
|
390
|
-
multiPointView.setMap(mapView)
|
|
391
|
-
}
|
|
392
|
-
// 🔑 关键修复:不再调用 setupAllOverlayViews()
|
|
393
|
-
return
|
|
394
|
-
} else if let clusterView = subview as? ClusterView {
|
|
395
|
-
if clusterView.superview === overlayContainer {
|
|
396
|
-
|
|
397
|
-
return
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
clusterView.alpha = 0
|
|
401
|
-
clusterView.isHidden = true
|
|
402
|
-
overlayViews.append(clusterView)
|
|
403
|
-
if let mapView {
|
|
404
|
-
clusterView.setMap(mapView)
|
|
405
|
-
}
|
|
406
|
-
// 🔑 关键修复:不再调用 setupAllOverlayViews()
|
|
308
|
+
if subview.superview !== overlayContainer && hostOverlayView(subview, moveToOverlayContainer: false) {
|
|
407
309
|
return
|
|
408
310
|
}
|
|
409
311
|
|
|
@@ -418,29 +320,29 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
418
320
|
// 🔑 处理所有覆盖物 - 从跟踪数组中移除并确保 native 对象也从地图移除
|
|
419
321
|
// 🔑 关键修复:先从数组移除,再调用 super,防止 super 触发的事件回调中引用已卸载的视图
|
|
420
322
|
if let markerView = subview as? MarkerView {
|
|
421
|
-
|
|
323
|
+
unregisterOverlayView(markerView)
|
|
422
324
|
// MarkerView 内部的 willMove(toSuperview: nil) 会处理 annotation 的移除
|
|
423
325
|
} else if let circleView = subview as? CircleView {
|
|
424
|
-
|
|
326
|
+
unregisterOverlayView(circleView)
|
|
425
327
|
if let mapView, let circle = circleView.circle {
|
|
426
328
|
mapView.remove(circle)
|
|
427
329
|
}
|
|
428
330
|
} else if let polylineView = subview as? PolylineView {
|
|
429
|
-
|
|
331
|
+
unregisterOverlayView(polylineView)
|
|
430
332
|
if let mapView, let polyline = polylineView.polyline {
|
|
431
333
|
mapView.remove(polyline)
|
|
432
334
|
}
|
|
433
335
|
} else if let polygonView = subview as? PolygonView {
|
|
434
|
-
|
|
336
|
+
unregisterOverlayView(polygonView)
|
|
435
337
|
if let mapView, let polygon = polygonView.polygon {
|
|
436
338
|
mapView.remove(polygon)
|
|
437
339
|
}
|
|
438
340
|
} else if let heatMapView = subview as? HeatMapView {
|
|
439
|
-
|
|
341
|
+
unregisterOverlayView(heatMapView)
|
|
440
342
|
} else if let multiPointView = subview as? MultiPointView {
|
|
441
|
-
|
|
343
|
+
unregisterOverlayView(multiPointView)
|
|
442
344
|
} else if let clusterView = subview as? ClusterView {
|
|
443
|
-
|
|
345
|
+
unregisterOverlayView(clusterView)
|
|
444
346
|
}
|
|
445
347
|
|
|
446
348
|
super.willRemoveSubview(subview)
|
|
@@ -454,7 +356,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
454
356
|
return
|
|
455
357
|
}
|
|
456
358
|
|
|
457
|
-
uiManager.setMapType(
|
|
359
|
+
uiManager.setMapType(1)
|
|
458
360
|
uiManager.setShowsScale(showsScale)
|
|
459
361
|
uiManager.setShowsCompass(showsCompass)
|
|
460
362
|
uiManager.setZoomEnabled(isZoomEnabled)
|
|
@@ -462,6 +364,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
462
364
|
uiManager.setRotateEnabled(isRotateEnabled)
|
|
463
365
|
uiManager.setTiltEnabled(isTiltEnabled)
|
|
464
366
|
uiManager.setShowsUserLocation(showsUserLocation, followUser: followUserLocation)
|
|
367
|
+
updatePinchGestureState()
|
|
465
368
|
}
|
|
466
369
|
|
|
467
370
|
/**
|
|
@@ -492,6 +395,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
492
395
|
uiManager.setShowsTraffic(showsTraffic)
|
|
493
396
|
uiManager.setShowsBuildings(showsBuildings)
|
|
494
397
|
uiManager.setShowsIndoorMap(showsIndoorMap)
|
|
398
|
+
updatePinchGestureState()
|
|
399
|
+
mapView.distanceFilter = distanceFilter
|
|
400
|
+
mapView.headingFilter = headingFilter
|
|
495
401
|
if let customMapStyleData {
|
|
496
402
|
uiManager.setCustomMapStyle(customMapStyleData)
|
|
497
403
|
}
|
|
@@ -507,17 +413,20 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
507
413
|
*/
|
|
508
414
|
private func updateAppleMapStyle() {
|
|
509
415
|
switch mapType {
|
|
510
|
-
case
|
|
416
|
+
case 2: // 卫星
|
|
511
417
|
appleMapView.mapType = .satellite
|
|
512
418
|
appleMapView.overrideUserInterfaceStyle = .unspecified
|
|
513
|
-
case
|
|
419
|
+
case 3: // 夜间
|
|
514
420
|
// 苹果地图没有专门的夜间模式枚举,通过强制 Dark Mode 实现
|
|
515
421
|
appleMapView.mapType = .standard
|
|
516
422
|
appleMapView.overrideUserInterfaceStyle = .dark
|
|
517
|
-
case
|
|
423
|
+
case 4: // 导航
|
|
518
424
|
appleMapView.mapType = .standard
|
|
519
425
|
appleMapView.overrideUserInterfaceStyle = .unspecified
|
|
520
|
-
|
|
426
|
+
case 5: // 公交
|
|
427
|
+
appleMapView.mapType = .standard
|
|
428
|
+
appleMapView.overrideUserInterfaceStyle = .unspecified
|
|
429
|
+
default: // 标准 (1,兼容旧值 0)
|
|
521
430
|
appleMapView.mapType = .standard
|
|
522
431
|
// 标准模式下跟随系统,如果系统是深色则显示深色,否则浅色
|
|
523
432
|
appleMapView.overrideUserInterfaceStyle = .unspecified
|
|
@@ -890,7 +799,10 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
890
799
|
*/
|
|
891
800
|
deinit {
|
|
892
801
|
// 清理资源
|
|
802
|
+
stopInertiaAnimation()
|
|
893
803
|
pendingCameraMoveData = nil
|
|
804
|
+
cameraMoveDispatchWorkItem?.cancel()
|
|
805
|
+
cameraMoveDispatchWorkItem = nil
|
|
894
806
|
if let privacyObserver {
|
|
895
807
|
NotificationCenter.default.removeObserver(privacyObserver)
|
|
896
808
|
}
|
|
@@ -940,6 +852,7 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
940
852
|
resolvedMapView.frame = bounds
|
|
941
853
|
resolvedMapView.delegate = self
|
|
942
854
|
resolvedMapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
855
|
+
resolvedMapView.touchPOIEnabled = true
|
|
943
856
|
|
|
944
857
|
mapView = resolvedMapView
|
|
945
858
|
super.addSubview(resolvedMapView)
|
|
@@ -961,6 +874,14 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate, UIGestureRecognizerDelegate
|
|
|
961
874
|
pinchGesture.delegate = self
|
|
962
875
|
resolvedMapView.addGestureRecognizer(pinchGesture)
|
|
963
876
|
self.pinchGesture = pinchGesture
|
|
877
|
+
updatePinchGestureState()
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
private func updatePinchGestureState() {
|
|
881
|
+
pinchGesture?.isEnabled = isZoomEnabled
|
|
882
|
+
if !isZoomEnabled {
|
|
883
|
+
stopInertiaAnimation()
|
|
884
|
+
}
|
|
964
885
|
}
|
|
965
886
|
}
|
|
966
887
|
|
|
@@ -1013,42 +934,39 @@ extension ExpoGaodeMapView {
|
|
|
1013
934
|
* 地图区域即将改变时触发
|
|
1014
935
|
*/
|
|
1015
936
|
public func mapView(_ mapView: MAMapView, regionWillChangeAnimated animated: Bool) {
|
|
1016
|
-
|
|
937
|
+
// 保留代理实现,但不在这里分发 onCameraMove。
|
|
938
|
+
// 持续移动过程应使用 mapViewRegionChanged。
|
|
939
|
+
}
|
|
1017
940
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
let visibleRegion = mapView.region
|
|
1021
|
-
|
|
1022
|
-
let eventData: [String: Any] = [
|
|
1023
|
-
"cameraPosition": cameraPosition,
|
|
1024
|
-
"latLngBounds": [
|
|
1025
|
-
"northeast": [
|
|
1026
|
-
"latitude": visibleRegion.center.latitude + visibleRegion.span.latitudeDelta / 2,
|
|
1027
|
-
"longitude": visibleRegion.center.longitude + visibleRegion.span.longitudeDelta / 2
|
|
1028
|
-
],
|
|
1029
|
-
"southwest": [
|
|
1030
|
-
"latitude": visibleRegion.center.latitude - visibleRegion.span.latitudeDelta / 2,
|
|
1031
|
-
"longitude": visibleRegion.center.longitude - visibleRegion.span.longitudeDelta / 2
|
|
1032
|
-
]
|
|
1033
|
-
]
|
|
1034
|
-
]
|
|
1035
|
-
|
|
1036
|
-
// 直接触发事件,移除手动节流
|
|
1037
|
-
// 建议在 JS 端进行 debounce/throttle 处理
|
|
1038
|
-
onCameraMove(eventData)
|
|
941
|
+
public func mapViewRegionChanged(_ mapView: MAMapView) {
|
|
942
|
+
dispatchCameraMoveEvent(buildCameraEventData(for: mapView))
|
|
1039
943
|
}
|
|
1040
944
|
|
|
1041
945
|
/**
|
|
1042
946
|
* 地图区域改变完成后触发
|
|
1043
947
|
*/
|
|
1044
948
|
public func mapView(_ mapView: MAMapView, regionDidChangeAnimated animated: Bool) {
|
|
1045
|
-
|
|
949
|
+
flushPendingCameraMoveEvent()
|
|
950
|
+
onCameraIdle(buildCameraEventData(for: mapView))
|
|
1046
951
|
|
|
1047
|
-
//
|
|
1048
|
-
|
|
1049
|
-
|
|
952
|
+
// 这里的 overlayViews 是 [UIView] 类型,可能包含 ClusterView
|
|
953
|
+
for view in overlayViews {
|
|
954
|
+
if let clusterView = view as? ClusterView {
|
|
955
|
+
// 只有当 clusterView 依然在视图树中时才通知
|
|
956
|
+
if clusterView.superview != nil && clusterView.window != nil {
|
|
957
|
+
clusterView.mapRegionDidChange()
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
1050
961
|
|
|
1051
|
-
|
|
962
|
+
handleMapviewRegionChange(mapView: mapView)
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
private func buildCameraEventData(for mapView: MAMapView) -> [String: Any] {
|
|
966
|
+
let cameraPosition = cameraManager?.getCameraPosition() ?? [String: Any]()
|
|
967
|
+
let visibleRegion = mapView.region
|
|
968
|
+
|
|
969
|
+
return [
|
|
1052
970
|
"cameraPosition": cameraPosition,
|
|
1053
971
|
"latLngBounds": [
|
|
1054
972
|
"northeast": [
|
|
@@ -1060,25 +978,60 @@ extension ExpoGaodeMapView {
|
|
|
1060
978
|
"longitude": visibleRegion.center.longitude - visibleRegion.span.longitudeDelta / 2
|
|
1061
979
|
]
|
|
1062
980
|
]
|
|
1063
|
-
]
|
|
981
|
+
]
|
|
982
|
+
}
|
|
1064
983
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
984
|
+
private func dispatchCameraMoveEvent(_ eventData: [String: Any]) {
|
|
985
|
+
let throttleMs = max(cameraEventThrottleMs, 0)
|
|
986
|
+
if throttleMs == 0 {
|
|
987
|
+
pendingCameraMoveData = nil
|
|
988
|
+
cameraMoveDispatchWorkItem?.cancel()
|
|
989
|
+
cameraMoveDispatchWorkItem = nil
|
|
990
|
+
lastCameraMoveDispatchTime = CACurrentMediaTime()
|
|
991
|
+
onCameraMove(eventData)
|
|
992
|
+
return
|
|
1073
993
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
994
|
+
|
|
995
|
+
pendingCameraMoveData = eventData
|
|
996
|
+
|
|
997
|
+
let now = CACurrentMediaTime()
|
|
998
|
+
let throttleSeconds = Double(throttleMs) / 1000
|
|
999
|
+
let elapsed = now - lastCameraMoveDispatchTime
|
|
1000
|
+
|
|
1001
|
+
if elapsed >= throttleSeconds {
|
|
1002
|
+
cameraMoveDispatchWorkItem?.cancel()
|
|
1003
|
+
cameraMoveDispatchWorkItem = nil
|
|
1004
|
+
flushPendingCameraMoveEvent(at: now)
|
|
1005
|
+
return
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
guard cameraMoveDispatchWorkItem == nil else {
|
|
1009
|
+
return
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
let delay = max(0, throttleSeconds - elapsed)
|
|
1013
|
+
let workItem = DispatchWorkItem { [weak self] in
|
|
1014
|
+
self?.cameraMoveDispatchWorkItem = nil
|
|
1015
|
+
self?.flushPendingCameraMoveEvent()
|
|
1016
|
+
}
|
|
1017
|
+
cameraMoveDispatchWorkItem = workItem
|
|
1018
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem)
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
private func flushPendingCameraMoveEvent(at timestamp: CFTimeInterval = CACurrentMediaTime()) {
|
|
1022
|
+
guard let eventData = pendingCameraMoveData else {
|
|
1023
|
+
return
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
pendingCameraMoveData = nil
|
|
1027
|
+
lastCameraMoveDispatchTime = timestamp
|
|
1028
|
+
onCameraMove(eventData)
|
|
1076
1029
|
}
|
|
1077
1030
|
|
|
1078
1031
|
/**
|
|
1079
1032
|
* 地图单击事件
|
|
1080
1033
|
*/
|
|
1081
|
-
|
|
1034
|
+
private func handleGaodeMapTap(at coordinate: CLLocationCoordinate2D) {
|
|
1082
1035
|
// 如果正在处理 annotation 选择,跳过地图点击事件
|
|
1083
1036
|
if isHandlingAnnotationSelect {
|
|
1084
1037
|
isHandlingAnnotationSelect = false
|
|
@@ -1092,6 +1045,15 @@ extension ExpoGaodeMapView {
|
|
|
1092
1045
|
|
|
1093
1046
|
onMapPress(["latitude": coordinate.latitude, "longitude": coordinate.longitude])
|
|
1094
1047
|
}
|
|
1048
|
+
|
|
1049
|
+
public func mapView(_ mapView: MAMapView, didSingleTappedAtCoordinate coordinate: CLLocationCoordinate2D) {
|
|
1050
|
+
handleGaodeMapTap(at: coordinate)
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// 兼容部分旧版 SDK/历史实现
|
|
1054
|
+
public func mapView(_ mapView: MAMapView, didSingleTappedAt coordinate: CLLocationCoordinate2D) {
|
|
1055
|
+
handleGaodeMapTap(at: coordinate)
|
|
1056
|
+
}
|
|
1095
1057
|
|
|
1096
1058
|
/**
|
|
1097
1059
|
* 检查点击位置是否在圆形内
|
|
@@ -1257,9 +1219,37 @@ extension ExpoGaodeMapView {
|
|
|
1257
1219
|
/**
|
|
1258
1220
|
* 地图长按事件
|
|
1259
1221
|
*/
|
|
1260
|
-
|
|
1222
|
+
private func handleGaodeMapLongPress(at coordinate: CLLocationCoordinate2D) {
|
|
1261
1223
|
onMapLongPress(["latitude": coordinate.latitude, "longitude": coordinate.longitude])
|
|
1262
1224
|
}
|
|
1225
|
+
|
|
1226
|
+
public func mapView(_ mapView: MAMapView, didLongPressedAtCoordinate coordinate: CLLocationCoordinate2D) {
|
|
1227
|
+
handleGaodeMapLongPress(at: coordinate)
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
// 兼容部分旧版 SDK/历史实现
|
|
1231
|
+
public func mapView(_ mapView: MAMapView, didLongPressedAt coordinate: CLLocationCoordinate2D) {
|
|
1232
|
+
handleGaodeMapLongPress(at: coordinate)
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
private func handleGaodePoiTouch(_ pois: [Any]?) {
|
|
1236
|
+
guard let touchedPoi = pois?.first as? MATouchPoi else {
|
|
1237
|
+
return
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
onPressPoi([
|
|
1241
|
+
"id": touchedPoi.uid ?? "",
|
|
1242
|
+
"name": touchedPoi.name ?? "",
|
|
1243
|
+
"position": [
|
|
1244
|
+
"latitude": touchedPoi.coordinate.latitude,
|
|
1245
|
+
"longitude": touchedPoi.coordinate.longitude
|
|
1246
|
+
]
|
|
1247
|
+
])
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
public func mapView(_ mapView: MAMapView!, didTouchPois pois: [Any]!) {
|
|
1251
|
+
handleGaodePoiTouch(pois)
|
|
1252
|
+
}
|
|
1263
1253
|
|
|
1264
1254
|
/**
|
|
1265
1255
|
* 创建标注视图
|
|
@@ -1335,7 +1325,12 @@ extension ExpoGaodeMapView {
|
|
|
1335
1325
|
* 标注点击事件
|
|
1336
1326
|
*/
|
|
1337
1327
|
public func mapView(_ mapView: MAMapView, didSelect view: MAAnnotationView) {
|
|
1338
|
-
guard let annotation = view.annotation
|
|
1328
|
+
guard let annotation = view.annotation else {
|
|
1329
|
+
return
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
if annotation.isKind(of: MAUserLocation.self) {
|
|
1333
|
+
mapView.deselectAnnotation(annotation, animated: false)
|
|
1339
1334
|
return
|
|
1340
1335
|
}
|
|
1341
1336
|
|