expo-gaode-map 1.0.3 → 1.0.4
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 +71 -5
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +90 -6
- package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +87 -0
- package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +16 -0
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolygonView.kt +22 -2
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +83 -17
- package/build/ExpoGaodeMapView.d.ts +20 -0
- package/build/ExpoGaodeMapView.d.ts.map +1 -1
- package/build/ExpoGaodeMapView.js +55 -3
- package/build/ExpoGaodeMapView.js.map +1 -1
- package/build/components/overlays/Polygon.d.ts +1 -0
- package/build/components/overlays/Polygon.d.ts.map +1 -1
- package/build/components/overlays/Polygon.js +15 -3
- package/build/components/overlays/Polygon.js.map +1 -1
- package/build/components/overlays/Polyline.d.ts +1 -0
- package/build/components/overlays/Polyline.d.ts.map +1 -1
- package/build/components/overlays/Polyline.js +18 -3
- package/build/components/overlays/Polyline.js.map +1 -1
- package/build/types/map-view.types.d.ts +12 -0
- package/build/types/map-view.types.d.ts.map +1 -1
- package/build/types/map-view.types.js.map +1 -1
- package/build/types/overlays.types.d.ts +6 -0
- package/build/types/overlays.types.d.ts.map +1 -1
- package/build/types/overlays.types.js.map +1 -1
- package/docs/API.md +81 -7
- package/docs/INITIALIZATION.md +14 -4
- package/ios/ExpoGaodeMapModule.swift +91 -5
- package/ios/ExpoGaodeMapView.swift +157 -11
- package/ios/managers/OverlayManager.swift +116 -8
- package/ios/modules/LocationManager.swift +3 -0
- package/ios/overlays/PolygonView.swift +2 -0
- package/ios/overlays/PolylineView.swift +14 -0
- package/ios/utils/PermissionManager.swift +62 -7
- package/package.json +1 -1
- package/src/ExpoGaodeMapView.tsx +87 -11
- package/src/components/overlays/Polygon.tsx +16 -3
- package/src/components/overlays/Polyline.tsx +19 -3
- package/src/types/map-view.types.ts +10 -0
- package/src/types/overlays.types.ts +6 -0
|
@@ -24,6 +24,14 @@ class OverlayManager {
|
|
|
24
24
|
var onCirclePress: (([String: Any]) -> Void)?
|
|
25
25
|
/// Circle ID 映射 (overlay -> id)
|
|
26
26
|
private var circleIdMap: [MACircle: String] = [:]
|
|
27
|
+
/// Polygon ID 映射 (overlay -> id)
|
|
28
|
+
private var polygonIdMap: [MAPolygon: String] = [:]
|
|
29
|
+
/// Polyline ID 映射 (overlay -> id)
|
|
30
|
+
private var polylineIdMap: [MAPolyline: String] = [:]
|
|
31
|
+
/// Polygon 点击回调
|
|
32
|
+
var onPolygonPress: (([String: Any]) -> Void)?
|
|
33
|
+
/// Polyline 点击回调
|
|
34
|
+
var onPolylinePress: (([String: Any]) -> Void)?
|
|
27
35
|
|
|
28
36
|
/**
|
|
29
37
|
* 初始化覆盖物管理器
|
|
@@ -191,6 +199,7 @@ class OverlayManager {
|
|
|
191
199
|
// 先保存样式和 overlay,再添加到地图
|
|
192
200
|
overlayStyles[id] = props
|
|
193
201
|
overlays[id] = polyline
|
|
202
|
+
polylineIdMap[polyline] = id
|
|
194
203
|
mapView.add(polyline)
|
|
195
204
|
}
|
|
196
205
|
|
|
@@ -199,10 +208,11 @@ class OverlayManager {
|
|
|
199
208
|
* @param id 折线唯一标识
|
|
200
209
|
*/
|
|
201
210
|
func removePolyline(id: String) {
|
|
202
|
-
guard let mapView = mapView, let polyline = overlays[id] else { return }
|
|
211
|
+
guard let mapView = mapView, let polyline = overlays[id] as? MAPolyline else { return }
|
|
203
212
|
mapView.remove(polyline)
|
|
204
213
|
overlays.removeValue(forKey: id)
|
|
205
214
|
overlayStyles.removeValue(forKey: id)
|
|
215
|
+
polylineIdMap.removeValue(forKey: polyline)
|
|
206
216
|
}
|
|
207
217
|
|
|
208
218
|
/**
|
|
@@ -234,6 +244,7 @@ class OverlayManager {
|
|
|
234
244
|
let polygon = MAPolygon(coordinates: &coordinates, count: UInt(coordinates.count))
|
|
235
245
|
overlayStyles[id] = props
|
|
236
246
|
overlays[id] = polygon
|
|
247
|
+
polygonIdMap[polygon!] = id
|
|
237
248
|
mapView.add(polygon!)
|
|
238
249
|
}
|
|
239
250
|
|
|
@@ -242,10 +253,11 @@ class OverlayManager {
|
|
|
242
253
|
* @param id 多边形唯一标识
|
|
243
254
|
*/
|
|
244
255
|
func removePolygon(id: String) {
|
|
245
|
-
guard let mapView = mapView, let polygon = overlays[id] else { return }
|
|
256
|
+
guard let mapView = mapView, let polygon = overlays[id] as? MAPolygon else { return }
|
|
246
257
|
mapView.remove(polygon)
|
|
247
258
|
overlays.removeValue(forKey: id)
|
|
248
259
|
overlayStyles.removeValue(forKey: id)
|
|
260
|
+
polygonIdMap.removeValue(forKey: polygon)
|
|
249
261
|
}
|
|
250
262
|
|
|
251
263
|
/**
|
|
@@ -293,13 +305,13 @@ class OverlayManager {
|
|
|
293
305
|
// 设置线宽
|
|
294
306
|
if let width = style?["width"] as? Double {
|
|
295
307
|
renderer.lineWidth = CGFloat(width)
|
|
296
|
-
|
|
308
|
+
|
|
297
309
|
} else if let strokeWidth = style?["strokeWidth"] as? Double {
|
|
298
310
|
renderer.lineWidth = CGFloat(strokeWidth)
|
|
299
|
-
|
|
311
|
+
|
|
300
312
|
} else {
|
|
301
313
|
renderer.lineWidth = 8
|
|
302
|
-
|
|
314
|
+
|
|
303
315
|
}
|
|
304
316
|
|
|
305
317
|
// 设置线条样式
|
|
@@ -337,18 +349,18 @@ class OverlayManager {
|
|
|
337
349
|
if let fillColor = style?["fillColor"] {
|
|
338
350
|
let parsedColor = ColorParser.parseColor(fillColor)
|
|
339
351
|
renderer.fillColor = parsedColor
|
|
340
|
-
|
|
352
|
+
|
|
341
353
|
}
|
|
342
354
|
// 设置边框颜色
|
|
343
355
|
if let strokeColor = style?["strokeColor"] {
|
|
344
356
|
let parsedColor = ColorParser.parseColor(strokeColor)
|
|
345
357
|
renderer.strokeColor = parsedColor
|
|
346
|
-
|
|
358
|
+
|
|
347
359
|
}
|
|
348
360
|
// 设置边框宽度
|
|
349
361
|
if let strokeWidth = style?["strokeWidth"] as? Double {
|
|
350
362
|
renderer.lineWidth = CGFloat(strokeWidth)
|
|
351
|
-
|
|
363
|
+
|
|
352
364
|
}
|
|
353
365
|
|
|
354
366
|
return renderer
|
|
@@ -402,6 +414,99 @@ class OverlayManager {
|
|
|
402
414
|
renderer.strokeImage = image
|
|
403
415
|
}
|
|
404
416
|
|
|
417
|
+
/**
|
|
418
|
+
* 检查点击位置是否在多边形内
|
|
419
|
+
*/
|
|
420
|
+
func checkPolygonPress(at coordinate: CLLocationCoordinate2D) -> Bool {
|
|
421
|
+
for (polygon, polygonId) in polygonIdMap {
|
|
422
|
+
let count = Int(polygon.pointCount)
|
|
423
|
+
guard count >= 3 else { continue }
|
|
424
|
+
|
|
425
|
+
var coords = [CLLocationCoordinate2D](repeating: CLLocationCoordinate2D(), count: count)
|
|
426
|
+
polygon.getCoordinates(&coords, range: NSRange(location: 0, length: count))
|
|
427
|
+
|
|
428
|
+
if isPoint(coordinate, inPolygon: coords) {
|
|
429
|
+
onPolygonPress?([
|
|
430
|
+
"polygonId": polygonId,
|
|
431
|
+
"latitude": coordinate.latitude,
|
|
432
|
+
"longitude": coordinate.longitude
|
|
433
|
+
])
|
|
434
|
+
return true
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return false
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* 检查点击位置是否在折线附近
|
|
442
|
+
*/
|
|
443
|
+
func checkPolylinePress(at coordinate: CLLocationCoordinate2D) -> Bool {
|
|
444
|
+
let threshold: Double = 20.0
|
|
445
|
+
for (polyline, polylineId) in polylineIdMap {
|
|
446
|
+
let count = Int(polyline.pointCount)
|
|
447
|
+
guard count >= 2 else { continue }
|
|
448
|
+
|
|
449
|
+
var coords = [CLLocationCoordinate2D](repeating: CLLocationCoordinate2D(), count: count)
|
|
450
|
+
polyline.getCoordinates(&coords, range: NSRange(location: 0, length: count))
|
|
451
|
+
|
|
452
|
+
if isPoint(coordinate, nearPolyline: coords, threshold: threshold) {
|
|
453
|
+
onPolylinePress?([
|
|
454
|
+
"polylineId": polylineId,
|
|
455
|
+
"latitude": coordinate.latitude,
|
|
456
|
+
"longitude": coordinate.longitude
|
|
457
|
+
])
|
|
458
|
+
return true
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return false
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
private func isPoint(_ point: CLLocationCoordinate2D, inPolygon coords: [CLLocationCoordinate2D]) -> Bool {
|
|
465
|
+
var inside = false
|
|
466
|
+
var j = coords.count - 1
|
|
467
|
+
|
|
468
|
+
for i in 0..<coords.count {
|
|
469
|
+
if ((coords[i].latitude > point.latitude) != (coords[j].latitude > point.latitude)) {
|
|
470
|
+
let slope = (coords[j].longitude - coords[i].longitude) * (point.latitude - coords[i].latitude) / (coords[j].latitude - coords[i].latitude)
|
|
471
|
+
if point.longitude < slope + coords[i].longitude {
|
|
472
|
+
inside = !inside
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
j = i
|
|
476
|
+
}
|
|
477
|
+
return inside
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private func isPoint(_ point: CLLocationCoordinate2D, nearPolyline coords: [CLLocationCoordinate2D], threshold: Double) -> Bool {
|
|
481
|
+
for i in 0..<(coords.count - 1) {
|
|
482
|
+
let distance = distanceFromPoint(point, toLineSegment: (coords[i], coords[i + 1]))
|
|
483
|
+
if distance <= threshold {
|
|
484
|
+
return true
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return false
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private func distanceFromPoint(_ point: CLLocationCoordinate2D, toLineSegment line: (CLLocationCoordinate2D, CLLocationCoordinate2D)) -> Double {
|
|
491
|
+
let p = CLLocation(latitude: point.latitude, longitude: point.longitude)
|
|
492
|
+
let a = CLLocation(latitude: line.0.latitude, longitude: line.0.longitude)
|
|
493
|
+
let b = CLLocation(latitude: line.1.latitude, longitude: line.1.longitude)
|
|
494
|
+
|
|
495
|
+
let ab = a.distance(from: b)
|
|
496
|
+
if ab == 0 { return a.distance(from: p) }
|
|
497
|
+
|
|
498
|
+
let t = max(0, min(1, ((p.coordinate.latitude - a.coordinate.latitude) * (b.coordinate.latitude - a.coordinate.latitude) +
|
|
499
|
+
(p.coordinate.longitude - a.coordinate.longitude) * (b.coordinate.longitude - a.coordinate.longitude)) /
|
|
500
|
+
(ab * ab)))
|
|
501
|
+
|
|
502
|
+
let projection = CLLocationCoordinate2D(
|
|
503
|
+
latitude: a.coordinate.latitude + t * (b.coordinate.latitude - a.coordinate.latitude),
|
|
504
|
+
longitude: a.coordinate.longitude + t * (b.coordinate.longitude - a.coordinate.longitude)
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
return p.distance(from: CLLocation(latitude: projection.latitude, longitude: projection.longitude))
|
|
508
|
+
}
|
|
509
|
+
|
|
405
510
|
/**
|
|
406
511
|
* 清除所有覆盖物和标记点
|
|
407
512
|
*/
|
|
@@ -416,5 +521,8 @@ class OverlayManager {
|
|
|
416
521
|
overlays.removeAll()
|
|
417
522
|
overlayStyles.removeAll()
|
|
418
523
|
annotations.removeAll()
|
|
524
|
+
circleIdMap.removeAll()
|
|
525
|
+
polygonIdMap.removeAll()
|
|
526
|
+
polylineIdMap.removeAll()
|
|
419
527
|
}
|
|
420
528
|
}
|
|
@@ -179,6 +179,9 @@ class LocationManager: NSObject, AMapLocationManagerDelegate {
|
|
|
179
179
|
locationManager?.locationTimeout = 1
|
|
180
180
|
locationManager?.reGeocodeTimeout = 1
|
|
181
181
|
locationManager?.locatingWithReGeocode = true
|
|
182
|
+
|
|
183
|
+
// iOS 9 之前:防止后台被系统挂起(默认关闭,用户可通过 setPausesLocationUpdatesAutomatically 配置)
|
|
184
|
+
locationManager?.pausesLocationUpdatesAutomatically = false
|
|
182
185
|
}
|
|
183
186
|
|
|
184
187
|
// MARK: - AMapLocationManagerDelegate
|
|
@@ -16,9 +16,14 @@ class PolylineView: ExpoView {
|
|
|
16
16
|
var strokeWidth: Float = 0
|
|
17
17
|
/// 线条颜色
|
|
18
18
|
var strokeColor: Any?
|
|
19
|
+
/// 是否虚线
|
|
20
|
+
var isDotted: Bool = false
|
|
19
21
|
/// 纹理图片 URL
|
|
20
22
|
var textureUrl: String?
|
|
21
23
|
|
|
24
|
+
/// 点击事件派发器
|
|
25
|
+
let onPress = EventDispatcher()
|
|
26
|
+
|
|
22
27
|
/// 地图视图弱引用
|
|
23
28
|
private var mapView: MAMapView?
|
|
24
29
|
/// 折线覆盖物对象
|
|
@@ -77,6 +82,9 @@ class PolylineView: ExpoView {
|
|
|
77
82
|
renderer = MAPolylineRenderer(polyline: polyline)
|
|
78
83
|
renderer?.lineWidth = CGFloat(strokeWidth)
|
|
79
84
|
|
|
85
|
+
// 注意: iOS 高德地图 SDK 不支持简单的虚线设置
|
|
86
|
+
// 需要使用 MAMultiPolyline 实现虚线,暂不支持
|
|
87
|
+
|
|
80
88
|
if let url = textureUrl {
|
|
81
89
|
print("🔷 PolylineView.getRenderer: 加载纹理 \(url)")
|
|
82
90
|
loadTexture(url: url, renderer: renderer!)
|
|
@@ -179,6 +187,12 @@ class PolylineView: ExpoView {
|
|
|
179
187
|
updatePolyline()
|
|
180
188
|
}
|
|
181
189
|
|
|
190
|
+
func setDotted(_ dotted: Bool) {
|
|
191
|
+
isDotted = dotted
|
|
192
|
+
renderer = nil
|
|
193
|
+
updatePolyline()
|
|
194
|
+
}
|
|
195
|
+
|
|
182
196
|
/**
|
|
183
197
|
* 析构时移除折线
|
|
184
198
|
*/
|
|
@@ -20,24 +20,79 @@ class PermissionManager: NSObject, CLLocationManagerDelegate {
|
|
|
20
20
|
* @param callback 权限结果回调 (granted, status)
|
|
21
21
|
*/
|
|
22
22
|
func requestPermission(callback: @escaping (Bool, String) -> Void) {
|
|
23
|
+
print("🔐 [PermissionManager] requestPermission 被调用")
|
|
23
24
|
self.permissionCallback = callback
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// 确保在主线程操作
|
|
27
|
+
DispatchQueue.main.async { [weak self] in
|
|
28
|
+
guard let self = self else { return }
|
|
29
|
+
|
|
30
|
+
if self.locationManager == nil {
|
|
31
|
+
print("🔐 [PermissionManager] 创建 CLLocationManager")
|
|
32
|
+
self.locationManager = CLLocationManager()
|
|
33
|
+
self.locationManager?.delegate = self
|
|
34
|
+
print("🔐 [PermissionManager] delegate 已设置: \(self.locationManager?.delegate != nil)")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let currentStatus = CLLocationManager.authorizationStatus()
|
|
38
|
+
print("🔐 [PermissionManager] 当前权限状态: \(self.getAuthorizationStatusString(currentStatus))")
|
|
39
|
+
|
|
40
|
+
// 如果已经有权限,直接返回
|
|
41
|
+
if currentStatus == .authorizedAlways || currentStatus == .authorizedWhenInUse {
|
|
42
|
+
print("🔐 [PermissionManager] 已有权限,直接返回")
|
|
43
|
+
self.permissionCallback?(true, self.getAuthorizationStatusString(currentStatus))
|
|
44
|
+
self.permissionCallback = nil
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 如果已经被拒绝,直接返回
|
|
49
|
+
if currentStatus == .denied || currentStatus == .restricted {
|
|
50
|
+
print("🔐 [PermissionManager] 权限已被拒绝")
|
|
51
|
+
self.permissionCallback?(false, self.getAuthorizationStatusString(currentStatus))
|
|
52
|
+
self.permissionCallback = nil
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
print("🔐 [PermissionManager] 调用 requestWhenInUseAuthorization()")
|
|
57
|
+
self.locationManager?.requestWhenInUseAuthorization()
|
|
58
|
+
print("🔐 [PermissionManager] requestWhenInUseAuthorization() 调用完成")
|
|
28
59
|
}
|
|
29
|
-
|
|
30
|
-
locationManager?.requestWhenInUseAuthorization()
|
|
31
60
|
}
|
|
32
61
|
|
|
33
62
|
/**
|
|
34
|
-
* 权限状态变化回调
|
|
63
|
+
* 权限状态变化回调 (iOS 14+)
|
|
35
64
|
*/
|
|
36
65
|
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
|
37
|
-
|
|
66
|
+
print("🔐 [PermissionManager] locationManagerDidChangeAuthorization 被调用")
|
|
67
|
+
handleAuthorizationChange(manager.authorizationStatus)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 权限状态变化回调 (iOS 13 及以下,兼容旧版本)
|
|
72
|
+
*/
|
|
73
|
+
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
|
|
74
|
+
print("🔐 [PermissionManager] didChangeAuthorization 被调用")
|
|
75
|
+
handleAuthorizationChange(status)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 处理权限状态变化
|
|
80
|
+
*/
|
|
81
|
+
private func handleAuthorizationChange(_ status: CLAuthorizationStatus) {
|
|
82
|
+
print("🔐 [PermissionManager] 当前状态: \(getAuthorizationStatusString(status))")
|
|
83
|
+
|
|
84
|
+
// 如果状态仍是 notDetermined,说明用户还没有做出选择,忽略这次回调
|
|
85
|
+
if status == .notDetermined {
|
|
86
|
+
print("🔐 [PermissionManager] 状态仍为 notDetermined,等待用户选择")
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 状态已确定(授予或拒绝),返回结果
|
|
38
91
|
let granted = status == .authorizedAlways || status == .authorizedWhenInUse
|
|
39
92
|
let statusString = getAuthorizationStatusString(status)
|
|
40
93
|
|
|
94
|
+
print("🔐 [PermissionManager] 返回结果: granted=\(granted), status=\(statusString)")
|
|
95
|
+
|
|
41
96
|
permissionCallback?(granted, statusString)
|
|
42
97
|
permissionCallback = nil
|
|
43
98
|
}
|
package/package.json
CHANGED
package/src/ExpoGaodeMapView.tsx
CHANGED
|
@@ -77,6 +77,58 @@ class CircleEventManager {
|
|
|
77
77
|
|
|
78
78
|
export const CircleEventContext = React.createContext<CircleEventManager | null>(null);
|
|
79
79
|
|
|
80
|
+
// Polygon 事件管理器
|
|
81
|
+
type PolygonEventCallbacks = {
|
|
82
|
+
onPress?: () => void;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
class PolygonEventManager {
|
|
86
|
+
private callbacks = new Map<string, PolygonEventCallbacks>();
|
|
87
|
+
|
|
88
|
+
register(polygonId: string, callbacks: PolygonEventCallbacks) {
|
|
89
|
+
this.callbacks.set(polygonId, callbacks);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
unregister(polygonId: string) {
|
|
93
|
+
this.callbacks.delete(polygonId);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
trigger(polygonId: string, eventType: keyof PolygonEventCallbacks) {
|
|
97
|
+
const callbacks = this.callbacks.get(polygonId);
|
|
98
|
+
if (callbacks && callbacks[eventType]) {
|
|
99
|
+
callbacks[eventType]!();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const PolygonEventContext = React.createContext<PolygonEventManager | null>(null);
|
|
105
|
+
|
|
106
|
+
// Polyline 事件管理器
|
|
107
|
+
type PolylineEventCallbacks = {
|
|
108
|
+
onPress?: () => void;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
class PolylineEventManager {
|
|
112
|
+
private callbacks = new Map<string, PolylineEventCallbacks>();
|
|
113
|
+
|
|
114
|
+
register(polylineId: string, callbacks: PolylineEventCallbacks) {
|
|
115
|
+
this.callbacks.set(polylineId, callbacks);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
unregister(polylineId: string) {
|
|
119
|
+
this.callbacks.delete(polylineId);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
trigger(polylineId: string, eventType: keyof PolylineEventCallbacks) {
|
|
123
|
+
const callbacks = this.callbacks.get(polylineId);
|
|
124
|
+
if (callbacks && callbacks[eventType]) {
|
|
125
|
+
callbacks[eventType]!();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export const PolylineEventContext = React.createContext<PolylineEventManager | null>(null);
|
|
131
|
+
|
|
80
132
|
/**
|
|
81
133
|
* 高德地图视图组件,提供地图操作API和覆盖物管理功能
|
|
82
134
|
*
|
|
@@ -100,6 +152,8 @@ const ExpoGaodeMapView = React.forwardRef<MapViewRef, MapViewProps>((props, ref)
|
|
|
100
152
|
const internalRef = React.useRef<MapViewRef | null>(null);
|
|
101
153
|
const markerEventManager = React.useRef(new MarkerEventManager()).current;
|
|
102
154
|
const circleEventManager = React.useRef(new CircleEventManager()).current;
|
|
155
|
+
const polygonEventManager = React.useRef(new PolygonEventManager()).current;
|
|
156
|
+
const polylineEventManager = React.useRef(new PolylineEventManager()).current;
|
|
103
157
|
|
|
104
158
|
// 处理 Marker 事件
|
|
105
159
|
const handleMarkerPress = React.useCallback((event: any) => {
|
|
@@ -146,6 +200,22 @@ const ExpoGaodeMapView = React.forwardRef<MapViewRef, MapViewProps>((props, ref)
|
|
|
146
200
|
}
|
|
147
201
|
props.onCirclePress?.(event);
|
|
148
202
|
}, [props.onCirclePress]);
|
|
203
|
+
|
|
204
|
+
const handlePolygonPress = React.useCallback((event: any) => {
|
|
205
|
+
const polygonId = event.nativeEvent?.polygonId;
|
|
206
|
+
if (polygonId) {
|
|
207
|
+
polygonEventManager.trigger(polygonId, 'onPress');
|
|
208
|
+
}
|
|
209
|
+
props.onPolygonPress?.(event);
|
|
210
|
+
}, [props.onPolygonPress]);
|
|
211
|
+
|
|
212
|
+
const handlePolylinePress = React.useCallback((event: any) => {
|
|
213
|
+
const polylineId = event.nativeEvent?.polylineId;
|
|
214
|
+
if (polylineId) {
|
|
215
|
+
polylineEventManager.trigger(polylineId, 'onPress');
|
|
216
|
+
}
|
|
217
|
+
props.onPolylinePress?.(event);
|
|
218
|
+
}, [props.onPolylinePress]);
|
|
149
219
|
|
|
150
220
|
const apiRef: MapViewRef = React.useMemo(() => ({
|
|
151
221
|
/**
|
|
@@ -348,17 +418,23 @@ const ExpoGaodeMapView = React.forwardRef<MapViewRef, MapViewProps>((props, ref)
|
|
|
348
418
|
<MapContext.Provider value={internalRef}>
|
|
349
419
|
<MarkerEventContext.Provider value={markerEventManager}>
|
|
350
420
|
<CircleEventContext.Provider value={circleEventManager}>
|
|
351
|
-
<
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
421
|
+
<PolygonEventContext.Provider value={polygonEventManager}>
|
|
422
|
+
<PolylineEventContext.Provider value={polylineEventManager}>
|
|
423
|
+
<NativeView
|
|
424
|
+
ref={nativeRef}
|
|
425
|
+
{...props}
|
|
426
|
+
onMarkerPress={handleMarkerPress}
|
|
427
|
+
onMarkerDragStart={handleMarkerDragStart}
|
|
428
|
+
onMarkerDrag={handleMarkerDrag}
|
|
429
|
+
onMarkerDragEnd={handleMarkerDragEnd}
|
|
430
|
+
onCirclePress={handleCirclePress}
|
|
431
|
+
onPolygonPress={handlePolygonPress}
|
|
432
|
+
onPolylinePress={handlePolylinePress}
|
|
433
|
+
>
|
|
434
|
+
{props.children}
|
|
435
|
+
</NativeView>
|
|
436
|
+
</PolylineEventContext.Provider>
|
|
437
|
+
</PolygonEventContext.Provider>
|
|
362
438
|
</CircleEventContext.Provider>
|
|
363
439
|
</MarkerEventContext.Provider>
|
|
364
440
|
</MapContext.Provider>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useContext, useEffect, useRef } from 'react';
|
|
2
2
|
import type { PolygonProps } from '../../types';
|
|
3
|
-
import { MapContext } from '../../ExpoGaodeMapView';
|
|
3
|
+
import { MapContext, PolygonEventContext } from '../../ExpoGaodeMapView';
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -12,6 +12,7 @@ import { MapContext } from '../../ExpoGaodeMapView';
|
|
|
12
12
|
* @param props.strokeColor - 多边形边框颜色,默认-16776961
|
|
13
13
|
* @param props.strokeWidth - 多边形边框宽度,默认10
|
|
14
14
|
* @param props.zIndex - 多边形层级,默认0
|
|
15
|
+
* @param props.onPress - 多边形点击事件
|
|
15
16
|
*
|
|
16
17
|
* @remarks
|
|
17
18
|
* 组件内部会自动生成唯一ID用于标识多边形,并在组件挂载时添加到地图,
|
|
@@ -22,6 +23,7 @@ import { MapContext } from '../../ExpoGaodeMapView';
|
|
|
22
23
|
export default function Polygon(props: PolygonProps) {
|
|
23
24
|
const { points, fillColor, strokeColor, strokeWidth, zIndex } = props;
|
|
24
25
|
const nativeRef = useContext(MapContext);
|
|
26
|
+
const eventManager = useContext(PolygonEventContext);
|
|
25
27
|
const polygonIdRef = useRef<string | null>(null);
|
|
26
28
|
const propsRef = useRef(props);
|
|
27
29
|
|
|
@@ -39,6 +41,12 @@ export default function Polygon(props: PolygonProps) {
|
|
|
39
41
|
const polygonId = `polygon_${Date.now()}_${Math.random()}`;
|
|
40
42
|
polygonIdRef.current = polygonId;
|
|
41
43
|
|
|
44
|
+
if (eventManager && props.onPress) {
|
|
45
|
+
eventManager.register(polygonId, {
|
|
46
|
+
onPress: props.onPress,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
const { points, fillColor, strokeColor, strokeWidth, zIndex } = propsRef.current;
|
|
43
51
|
|
|
44
52
|
if (points && points.length >= 3) {
|
|
@@ -55,8 +63,13 @@ export default function Polygon(props: PolygonProps) {
|
|
|
55
63
|
checkAndAdd();
|
|
56
64
|
|
|
57
65
|
return () => {
|
|
58
|
-
if (polygonIdRef.current
|
|
59
|
-
|
|
66
|
+
if (polygonIdRef.current) {
|
|
67
|
+
if (eventManager) {
|
|
68
|
+
eventManager.unregister(polygonIdRef.current);
|
|
69
|
+
}
|
|
70
|
+
if (nativeRef?.current) {
|
|
71
|
+
nativeRef.current.removePolygon(polygonIdRef.current);
|
|
72
|
+
}
|
|
60
73
|
}
|
|
61
74
|
};
|
|
62
75
|
}, []);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { MapContext } from '../../ExpoGaodeMapView';
|
|
3
|
+
import { MapContext, PolylineEventContext } from '../../ExpoGaodeMapView';
|
|
4
4
|
import type { PolylineProps } from '../../types';
|
|
5
5
|
|
|
6
6
|
|
|
@@ -11,6 +11,7 @@ import type { PolylineProps } from '../../types';
|
|
|
11
11
|
* @param props.points - 折线的坐标点数组
|
|
12
12
|
* @param props.width - 折线的宽度(像素)
|
|
13
13
|
* @param props.color - 折线的颜色(十六进制或RGBA)
|
|
14
|
+
* @param props.onPress - 折线点击事件回调函数
|
|
14
15
|
* @param [props.texture] - 可选,折线的纹理样式
|
|
15
16
|
*
|
|
16
17
|
* @remarks
|
|
@@ -21,6 +22,7 @@ import type { PolylineProps } from '../../types';
|
|
|
21
22
|
*/
|
|
22
23
|
export default function Polyline(props: PolylineProps) {
|
|
23
24
|
const mapRef = React.useContext(MapContext);
|
|
25
|
+
const eventManager = React.useContext(PolylineEventContext);
|
|
24
26
|
const polylineIdRef = React.useRef<string | null>(null);
|
|
25
27
|
const propsRef = React.useRef(props);
|
|
26
28
|
|
|
@@ -38,11 +40,20 @@ export default function Polyline(props: PolylineProps) {
|
|
|
38
40
|
const polylineId = `polyline_${Date.now()}_${Math.random()}`;
|
|
39
41
|
polylineIdRef.current = polylineId;
|
|
40
42
|
|
|
43
|
+
if (eventManager && props.onPress) {
|
|
44
|
+
eventManager.register(polylineId, {
|
|
45
|
+
onPress: props.onPress,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
const polylineProps = {
|
|
42
50
|
points: propsRef.current.points,
|
|
43
51
|
width: propsRef.current.width,
|
|
44
52
|
color: propsRef.current.color,
|
|
45
53
|
...(propsRef.current.texture && { texture: propsRef.current.texture }),
|
|
54
|
+
...(propsRef.current.dotted !== undefined && { dotted: propsRef.current.dotted }),
|
|
55
|
+
...(propsRef.current.geodesic !== undefined && { geodesic: propsRef.current.geodesic }),
|
|
56
|
+
...(propsRef.current.zIndex !== undefined && { zIndex: propsRef.current.zIndex }),
|
|
46
57
|
};
|
|
47
58
|
|
|
48
59
|
mapRef.current.addPolyline(polylineId, polylineProps);
|
|
@@ -51,8 +62,13 @@ export default function Polyline(props: PolylineProps) {
|
|
|
51
62
|
checkAndAdd();
|
|
52
63
|
|
|
53
64
|
return () => {
|
|
54
|
-
if (polylineIdRef.current
|
|
55
|
-
|
|
65
|
+
if (polylineIdRef.current) {
|
|
66
|
+
if (eventManager) {
|
|
67
|
+
eventManager.unregister(polylineIdRef.current);
|
|
68
|
+
}
|
|
69
|
+
if (mapRef?.current) {
|
|
70
|
+
mapRef.current.removePolyline(polylineIdRef.current);
|
|
71
|
+
}
|
|
56
72
|
}
|
|
57
73
|
};
|
|
58
74
|
}, []);
|
|
@@ -224,6 +224,16 @@ export interface MapViewProps {
|
|
|
224
224
|
*/
|
|
225
225
|
onCirclePress?: (event: { circleId: string } & LatLng) => void;
|
|
226
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Polygon 点击事件
|
|
229
|
+
*/
|
|
230
|
+
onPolygonPress?: (event: { polygonId: string } & LatLng) => void;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Polyline 点击事件
|
|
234
|
+
*/
|
|
235
|
+
onPolylinePress?: (event: { polylineId: string } & LatLng) => void;
|
|
236
|
+
|
|
227
237
|
/**
|
|
228
238
|
* 子组件
|
|
229
239
|
*/
|
|
@@ -149,16 +149,22 @@ export interface PolylineProps {
|
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
151
|
* 是否使用渐变色
|
|
152
|
+
* @platform android
|
|
153
|
+
* @note iOS 不支持
|
|
152
154
|
*/
|
|
153
155
|
gradient?: boolean;
|
|
154
156
|
|
|
155
157
|
/**
|
|
156
158
|
* 是否绘制大地线
|
|
159
|
+
* @platform android
|
|
160
|
+
* @note iOS 不支持
|
|
157
161
|
*/
|
|
158
162
|
geodesic?: boolean;
|
|
159
163
|
|
|
160
164
|
/**
|
|
161
165
|
* 是否绘制虚线
|
|
166
|
+
* @platform android
|
|
167
|
+
* @note iOS 不支持
|
|
162
168
|
*/
|
|
163
169
|
dotted?: boolean;
|
|
164
170
|
|