expo-gaode-map 1.0.2 → 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.
Files changed (56) hide show
  1. package/README.md +1 -0
  2. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +87 -5
  3. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +132 -1
  4. package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +271 -6
  5. package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +40 -51
  6. package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerView.kt +3 -0
  7. package/android/src/main/java/expo/modules/gaodemap/overlays/PolygonView.kt +22 -2
  8. package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +83 -17
  9. package/build/ExpoGaodeMapView.d.ts +46 -1
  10. package/build/ExpoGaodeMapView.d.ts.map +1 -1
  11. package/build/ExpoGaodeMapView.js +134 -1
  12. package/build/ExpoGaodeMapView.js.map +1 -1
  13. package/build/components/overlays/Circle.d.ts +0 -20
  14. package/build/components/overlays/Circle.d.ts.map +1 -1
  15. package/build/components/overlays/Circle.js +28 -45
  16. package/build/components/overlays/Circle.js.map +1 -1
  17. package/build/components/overlays/Marker.d.ts +2 -16
  18. package/build/components/overlays/Marker.d.ts.map +1 -1
  19. package/build/components/overlays/Marker.js +60 -37
  20. package/build/components/overlays/Marker.js.map +1 -1
  21. package/build/components/overlays/Polygon.d.ts +1 -0
  22. package/build/components/overlays/Polygon.d.ts.map +1 -1
  23. package/build/components/overlays/Polygon.js +38 -47
  24. package/build/components/overlays/Polygon.js.map +1 -1
  25. package/build/components/overlays/Polyline.d.ts +1 -0
  26. package/build/components/overlays/Polyline.d.ts.map +1 -1
  27. package/build/components/overlays/Polyline.js +38 -12
  28. package/build/components/overlays/Polyline.js.map +1 -1
  29. package/build/types/map-view.types.d.ts +42 -0
  30. package/build/types/map-view.types.d.ts.map +1 -1
  31. package/build/types/map-view.types.js.map +1 -1
  32. package/build/types/overlays.types.d.ts +31 -1
  33. package/build/types/overlays.types.d.ts.map +1 -1
  34. package/build/types/overlays.types.js.map +1 -1
  35. package/docs/API.md +121 -7
  36. package/docs/EXAMPLES.md +86 -2
  37. package/docs/INITIALIZATION.md +14 -4
  38. package/expo-module.config.json +1 -1
  39. package/ios/ExpoGaodeMapModule.swift +132 -18
  40. package/ios/ExpoGaodeMapView.swift +361 -12
  41. package/ios/managers/OverlayManager.swift +188 -12
  42. package/ios/modules/LocationManager.swift +3 -0
  43. package/ios/overlays/CircleView.swift +41 -12
  44. package/ios/overlays/MarkerView.swift +55 -3
  45. package/ios/overlays/PolygonView.swift +27 -5
  46. package/ios/overlays/PolylineView.swift +37 -4
  47. package/ios/utils/ColorParser.swift +0 -5
  48. package/ios/utils/PermissionManager.swift +62 -7
  49. package/package.json +1 -1
  50. package/src/ExpoGaodeMapView.tsx +194 -1
  51. package/src/components/overlays/Circle.tsx +31 -48
  52. package/src/components/overlays/Marker.tsx +69 -42
  53. package/src/components/overlays/Polygon.tsx +46 -49
  54. package/src/components/overlays/Polyline.tsx +46 -15
  55. package/src/types/map-view.types.ts +35 -0
  56. package/src/types/overlays.types.ts +36 -1
@@ -18,6 +18,20 @@ class OverlayManager {
18
18
  private var overlayStyles: [String: [String: Any]] = [:]
19
19
  /// 标记点字典 (id -> annotation)
20
20
  private var annotations: [String: MAPointAnnotation] = [:]
21
+ /// 标记点属性字典 (id -> props)
22
+ private var markerProps: [String: [String: Any]] = [:]
23
+ /// Circle 点击回调
24
+ var onCirclePress: (([String: Any]) -> Void)?
25
+ /// Circle ID 映射 (overlay -> id)
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)?
21
35
 
22
36
  /**
23
37
  * 初始化覆盖物管理器
@@ -27,6 +41,28 @@ class OverlayManager {
27
41
  self.mapView = mapView
28
42
  }
29
43
 
44
+ /**
45
+ * 检查点击位置是否在圆形内
46
+ */
47
+ func checkCirclePress(at coordinate: CLLocationCoordinate2D) -> Bool {
48
+ for (circle, circleId) in circleIdMap {
49
+ let circleCenter = circle.coordinate
50
+ let fromLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
51
+ let toLocation = CLLocation(latitude: circleCenter.latitude, longitude: circleCenter.longitude)
52
+ let distance = fromLocation.distance(from: toLocation)
53
+
54
+ if distance <= circle.radius {
55
+ onCirclePress?([
56
+ "circleId": circleId,
57
+ "latitude": coordinate.latitude,
58
+ "longitude": coordinate.longitude
59
+ ])
60
+ return true
61
+ }
62
+ }
63
+ return false
64
+ }
65
+
30
66
  // MARK: - Circle 圆形
31
67
 
32
68
  /**
@@ -43,8 +79,9 @@ class OverlayManager {
43
79
 
44
80
  let circle = MACircle(center: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), radius: radius)
45
81
  overlayStyles[id] = props
46
- mapView.add(circle!)
47
82
  overlays[id] = circle
83
+ circleIdMap[circle!] = id
84
+ mapView.add(circle!)
48
85
  }
49
86
 
50
87
  /**
@@ -52,10 +89,11 @@ class OverlayManager {
52
89
  * @param id 圆形唯一标识
53
90
  */
54
91
  func removeCircle(id: String) {
55
- guard let mapView = mapView, let circle = overlays[id] else { return }
92
+ guard let mapView = mapView, let circle = overlays[id] as? MACircle else { return }
56
93
  mapView.remove(circle)
57
94
  overlays.removeValue(forKey: id)
58
95
  overlayStyles.removeValue(forKey: id)
96
+ circleIdMap.removeValue(forKey: circle)
59
97
  }
60
98
 
61
99
  /**
@@ -84,9 +122,24 @@ class OverlayManager {
84
122
  let annotation = MAPointAnnotation()
85
123
  annotation.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
86
124
  annotation.title = props["title"] as? String
87
- annotation.subtitle = props["description"] as? String
88
- mapView.addAnnotation(annotation)
125
+ annotation.subtitle = props["snippet"] as? String ?? props["description"] as? String
126
+
127
+ // 先保存 props 和 annotation,再添加到地图
128
+ // 这样 viewFor annotation 回调时就能找到 props
89
129
  annotations[id] = annotation
130
+ markerProps[id] = props
131
+
132
+ mapView.addAnnotation(annotation)
133
+ }
134
+
135
+ /**
136
+ * 根据 annotation 获取 marker 属性
137
+ * @param annotation 标记点对象
138
+ * @return 对应的属性字典
139
+ */
140
+ func getMarkerProps(for annotation: MAAnnotation) -> [String: Any]? {
141
+ guard let id = getMarkerId(for: annotation) else { return nil }
142
+ return markerProps[id]
90
143
  }
91
144
 
92
145
  /**
@@ -97,6 +150,7 @@ class OverlayManager {
97
150
  guard let mapView = mapView, let annotation = annotations[id] else { return }
98
151
  mapView.removeAnnotation(annotation)
99
152
  annotations.removeValue(forKey: id)
153
+ markerProps.removeValue(forKey: id)
100
154
  }
101
155
 
102
156
  /**
@@ -109,6 +163,15 @@ class OverlayManager {
109
163
  addMarker(id: id, props: props)
110
164
  }
111
165
 
166
+ /**
167
+ * 根据 annotation 获取 markerId
168
+ * @param annotation 标记点对象
169
+ * @return 对应的 markerId,如果未找到返回 nil
170
+ */
171
+ func getMarkerId(for annotation: MAAnnotation) -> String? {
172
+ return annotations.first(where: { $0.value === annotation })?.key
173
+ }
174
+
112
175
  // MARK: - Polyline 折线
113
176
 
114
177
  /**
@@ -136,6 +199,7 @@ class OverlayManager {
136
199
  // 先保存样式和 overlay,再添加到地图
137
200
  overlayStyles[id] = props
138
201
  overlays[id] = polyline
202
+ polylineIdMap[polyline] = id
139
203
  mapView.add(polyline)
140
204
  }
141
205
 
@@ -144,10 +208,11 @@ class OverlayManager {
144
208
  * @param id 折线唯一标识
145
209
  */
146
210
  func removePolyline(id: String) {
147
- guard let mapView = mapView, let polyline = overlays[id] else { return }
211
+ guard let mapView = mapView, let polyline = overlays[id] as? MAPolyline else { return }
148
212
  mapView.remove(polyline)
149
213
  overlays.removeValue(forKey: id)
150
214
  overlayStyles.removeValue(forKey: id)
215
+ polylineIdMap.removeValue(forKey: polyline)
151
216
  }
152
217
 
153
218
  /**
@@ -178,8 +243,9 @@ class OverlayManager {
178
243
  guard !coordinates.isEmpty else { return }
179
244
  let polygon = MAPolygon(coordinates: &coordinates, count: UInt(coordinates.count))
180
245
  overlayStyles[id] = props
181
- mapView.add(polygon!)
182
246
  overlays[id] = polygon
247
+ polygonIdMap[polygon!] = id
248
+ mapView.add(polygon!)
183
249
  }
184
250
 
185
251
  /**
@@ -187,10 +253,11 @@ class OverlayManager {
187
253
  * @param id 多边形唯一标识
188
254
  */
189
255
  func removePolygon(id: String) {
190
- guard let mapView = mapView, let polygon = overlays[id] else { return }
256
+ guard let mapView = mapView, let polygon = overlays[id] as? MAPolygon else { return }
191
257
  mapView.remove(polygon)
192
258
  overlays.removeValue(forKey: id)
193
259
  overlayStyles.removeValue(forKey: id)
260
+ polygonIdMap.removeValue(forKey: polygon)
194
261
  }
195
262
 
196
263
  /**
@@ -219,15 +286,12 @@ class OverlayManager {
219
286
  return nil
220
287
  }
221
288
 
222
- // 设置填充颜色
223
289
  if let fillColor = style?["fillColor"] {
224
290
  renderer.fillColor = ColorParser.parseColor(fillColor)
225
291
  }
226
- // 设置边框颜色
227
292
  if let strokeColor = style?["strokeColor"] {
228
293
  renderer.strokeColor = ColorParser.parseColor(strokeColor)
229
294
  }
230
- // 设置边框宽度
231
295
  if let strokeWidth = style?["strokeWidth"] as? Double {
232
296
  renderer.lineWidth = CGFloat(strokeWidth)
233
297
  }
@@ -236,13 +300,18 @@ class OverlayManager {
236
300
  } else if let polyline = overlay as? MAPolyline {
237
301
  let renderer = MAPolylineRenderer(polyline: polyline)!
238
302
 
303
+ print("🔷 OverlayManager.getRenderer(Polyline): style=\(String(describing: style))")
304
+
239
305
  // 设置线宽
240
306
  if let width = style?["width"] as? Double {
241
307
  renderer.lineWidth = CGFloat(width)
308
+
242
309
  } else if let strokeWidth = style?["strokeWidth"] as? Double {
243
310
  renderer.lineWidth = CGFloat(strokeWidth)
311
+
244
312
  } else {
245
313
  renderer.lineWidth = 8
314
+
246
315
  }
247
316
 
248
317
  // 设置线条样式
@@ -251,16 +320,20 @@ class OverlayManager {
251
320
 
252
321
  // 设置纹理或颜色
253
322
  if let textureUrl = style?["texture"] as? String, !textureUrl.isEmpty {
323
+ print("🔷 OverlayManager: 加载纹理 \(textureUrl)")
254
324
  loadPolylineTexture(url: textureUrl, renderer: renderer)
255
325
  } else {
256
326
  if let color = style?["color"] {
257
327
  let parsedColor = ColorParser.parseColor(color)
258
328
  renderer.strokeColor = parsedColor ?? .red
329
+ print("🔷 OverlayManager: color=\(color) -> \(String(describing: parsedColor))")
259
330
  } else if let strokeColor = style?["strokeColor"] {
260
331
  let parsedColor = ColorParser.parseColor(strokeColor)
261
332
  renderer.strokeColor = parsedColor ?? .red
333
+ print("🔷 OverlayManager: strokeColor=\(strokeColor) -> \(String(describing: parsedColor))")
262
334
  } else {
263
335
  renderer.strokeColor = .red
336
+ print("🔷 OverlayManager: 使用默认红色")
264
337
  }
265
338
  }
266
339
 
@@ -270,17 +343,24 @@ class OverlayManager {
270
343
  return nil
271
344
  }
272
345
 
346
+ print("🔶 OverlayManager.getRenderer(Polygon): style=\(String(describing: style))")
347
+
273
348
  // 设置填充颜色
274
349
  if let fillColor = style?["fillColor"] {
275
- renderer.fillColor = ColorParser.parseColor(fillColor)
350
+ let parsedColor = ColorParser.parseColor(fillColor)
351
+ renderer.fillColor = parsedColor
352
+
276
353
  }
277
354
  // 设置边框颜色
278
355
  if let strokeColor = style?["strokeColor"] {
279
- renderer.strokeColor = ColorParser.parseColor(strokeColor)
356
+ let parsedColor = ColorParser.parseColor(strokeColor)
357
+ renderer.strokeColor = parsedColor
358
+
280
359
  }
281
360
  // 设置边框宽度
282
361
  if let strokeWidth = style?["strokeWidth"] as? Double {
283
362
  renderer.lineWidth = CGFloat(strokeWidth)
363
+
284
364
  }
285
365
 
286
366
  return renderer
@@ -334,6 +414,99 @@ class OverlayManager {
334
414
  renderer.strokeImage = image
335
415
  }
336
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
+
337
510
  /**
338
511
  * 清除所有覆盖物和标记点
339
512
  */
@@ -348,5 +521,8 @@ class OverlayManager {
348
521
  overlays.removeAll()
349
522
  overlayStyles.removeAll()
350
523
  annotations.removeAll()
524
+ circleIdMap.removeAll()
525
+ polygonIdMap.removeAll()
526
+ polylineIdMap.removeAll()
351
527
  }
352
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
@@ -10,6 +10,9 @@ import MAMapKit
10
10
  * - 响应属性变化并更新渲染
11
11
  */
12
12
  class CircleView: ExpoView {
13
+ /// 事件派发器
14
+ let onPress = EventDispatcher()
15
+
13
16
  /// 圆心坐标
14
17
  var circleCenter: [String: Double] = [:]
15
18
  /// 半径(米)
@@ -30,7 +33,6 @@ class CircleView: ExpoView {
30
33
 
31
34
  required init(appContext: AppContext? = nil) {
32
35
  super.init(appContext: appContext)
33
- circle = MACircle()
34
36
  }
35
37
 
36
38
  /**
@@ -39,19 +41,39 @@ class CircleView: ExpoView {
39
41
  */
40
42
  func setMap(_ map: MAMapView) {
41
43
  self.mapView = map
42
- if let circle = circle {
43
- map.add(circle)
44
- }
44
+ updateCircle()
45
45
  }
46
46
 
47
47
  /**
48
48
  * 更新圆形覆盖物
49
49
  */
50
50
  private func updateCircle() {
51
- guard let latitude = circleCenter["latitude"],
52
- let longitude = circleCenter["longitude"] else { return }
53
- circle?.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
54
- circle?.radius = radius
51
+ guard let mapView = mapView,
52
+ let latitude = circleCenter["latitude"],
53
+ let longitude = circleCenter["longitude"],
54
+ radius > 0 else {
55
+ print("❌ CircleView.updateCircle: 条件不满足")
56
+ return
57
+ }
58
+
59
+ print("🔵 CircleView.updateCircle: center=(\(latitude),\(longitude)), radius=\(radius)")
60
+ print("🔵 CircleView.updateCircle: fillColor=\(String(describing: fillColor)), strokeColor=\(String(describing: strokeColor)), strokeWidth=\(strokeWidth)")
61
+
62
+ if circle == nil {
63
+ let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
64
+ circle = MACircle(center: coordinate, radius: radius)
65
+ mapView.add(circle!)
66
+ print("🔵 CircleView.updateCircle: 创建新圆形")
67
+ } else {
68
+ circle?.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
69
+ circle?.radius = radius
70
+ mapView.remove(circle!)
71
+ mapView.add(circle!)
72
+ print("🔵 CircleView.updateCircle: 更新现有圆形")
73
+ }
74
+
75
+ renderer = nil
76
+ print("🔵 CircleView.updateCircle: renderer 已清空")
55
77
  }
56
78
 
57
79
  /**
@@ -61,9 +83,15 @@ class CircleView: ExpoView {
61
83
  func getRenderer() -> MAOverlayRenderer {
62
84
  if renderer == nil, let circle = circle {
63
85
  renderer = MACircleRenderer(circle: circle)
64
- renderer?.fillColor = ColorParser.parseColor(fillColor) ?? UIColor.clear
65
- renderer?.strokeColor = ColorParser.parseColor(strokeColor) ?? UIColor.clear
86
+ let parsedFillColor = ColorParser.parseColor(fillColor)
87
+ let parsedStrokeColor = ColorParser.parseColor(strokeColor)
88
+ renderer?.fillColor = parsedFillColor ?? UIColor.clear
89
+ renderer?.strokeColor = parsedStrokeColor ?? UIColor.clear
66
90
  renderer?.lineWidth = CGFloat(strokeWidth)
91
+ print("🔵 CircleView.getRenderer: 创建新 renderer")
92
+ print("🔵 CircleView.getRenderer: fillColor=\(String(describing: parsedFillColor)), strokeColor=\(String(describing: parsedStrokeColor)), lineWidth=\(strokeWidth)")
93
+ } else {
94
+ print("🔵 CircleView.getRenderer: 使用缓存的 renderer")
67
95
  }
68
96
  return renderer!
69
97
  }
@@ -74,7 +102,6 @@ class CircleView: ExpoView {
74
102
  */
75
103
  func setCenter(_ center: [String: Double]) {
76
104
  circleCenter = center
77
- renderer = nil
78
105
  updateCircle()
79
106
  }
80
107
 
@@ -84,7 +111,6 @@ class CircleView: ExpoView {
84
111
  */
85
112
  func setRadius(_ radius: Double) {
86
113
  self.radius = radius
87
- renderer = nil
88
114
  updateCircle()
89
115
  }
90
116
 
@@ -93,6 +119,7 @@ class CircleView: ExpoView {
93
119
  * @param color 颜色值
94
120
  */
95
121
  func setFillColor(_ color: Any?) {
122
+ print("🔵 CircleView.setFillColor: \(String(describing: color))")
96
123
  fillColor = color
97
124
  renderer = nil
98
125
  updateCircle()
@@ -103,6 +130,7 @@ class CircleView: ExpoView {
103
130
  * @param color 颜色值
104
131
  */
105
132
  func setStrokeColor(_ color: Any?) {
133
+ print("🔵 CircleView.setStrokeColor: \(String(describing: color))")
106
134
  strokeColor = color
107
135
  renderer = nil
108
136
  updateCircle()
@@ -113,6 +141,7 @@ class CircleView: ExpoView {
113
141
  * @param width 宽度值
114
142
  */
115
143
  func setStrokeWidth(_ width: Float) {
144
+ print("🔵 CircleView.setStrokeWidth: \(width)")
116
145
  strokeWidth = width
117
146
  renderer = nil
118
147
  updateCircle()
@@ -3,13 +3,20 @@ import MAMapKit
3
3
 
4
4
  /**
5
5
  * 标记点视图
6
- *
6
+ *
7
7
  * 负责:
8
8
  * - 在地图上显示标记点
9
9
  * - 管理标记点属性(位置、标题、描述)
10
10
  * - 支持拖拽功能
11
+ * - 支持自定义 children 视图
11
12
  */
12
13
  class MarkerView: ExpoView {
14
+ // MARK: - 事件派发器
15
+ let onPress = EventDispatcher()
16
+ let onDragStart = EventDispatcher()
17
+ let onDrag = EventDispatcher()
18
+ let onDragEnd = EventDispatcher()
19
+
13
20
  /// 标记点位置
14
21
  var position: [String: Double] = [:]
15
22
  /// 标题
@@ -18,11 +25,27 @@ class MarkerView: ExpoView {
18
25
  var markerDescription: String = ""
19
26
  /// 是否可拖拽
20
27
  var draggable: Bool = false
28
+ /// 图标 URI
29
+ var iconUri: String?
30
+ /// 图标宽度
31
+ var iconWidth: Double = 40
32
+ /// 图标高度
33
+ var iconHeight: Double = 40
34
+ /// 中心偏移
35
+ var centerOffset: [String: Double]?
36
+ /// 是否显示动画
37
+ var animatesDrop: Bool = false
38
+ /// 大头针颜色
39
+ var pinColor: String = "red"
40
+ /// 是否显示气泡
41
+ var canShowCallout: Bool = true
21
42
 
22
43
  /// 地图视图弱引用
23
44
  private var mapView: MAMapView?
24
45
  /// 标记点对象
25
- private var annotation: MAPointAnnotation?
46
+ var annotation: MAPointAnnotation?
47
+ /// 标记点视图
48
+ private var annotationView: MAAnnotationView?
26
49
 
27
50
  required init(appContext: AppContext? = nil) {
28
51
  super.init(appContext: appContext)
@@ -60,6 +83,9 @@ class MarkerView: ExpoView {
60
83
 
61
84
  mapView.addAnnotation(annotation)
62
85
  self.annotation = annotation
86
+
87
+ // 获取 annotationView
88
+ annotationView = mapView.view(for: annotation)
63
89
  }
64
90
 
65
91
  /**
@@ -95,7 +121,33 @@ class MarkerView: ExpoView {
95
121
  */
96
122
  func setDraggable(_ draggable: Bool) {
97
123
  self.draggable = draggable
98
- // iOS 高德地图标记默认不可拖拽,需要自定义实现
124
+ updateAnnotation()
125
+ }
126
+
127
+ func setIcon(_ source: [String: Any]?) {
128
+ if let dict = source {
129
+ // 处理 require() 返回的对象
130
+ if let uri = dict["uri"] as? String {
131
+ self.iconUri = uri
132
+ }
133
+ }
134
+ updateAnnotation()
135
+ }
136
+
137
+ func setCenterOffset(_ offset: [String: Double]) {
138
+ self.centerOffset = offset
139
+ }
140
+
141
+ func setAnimatesDrop(_ animate: Bool) {
142
+ self.animatesDrop = animate
143
+ }
144
+
145
+ func setPinColor(_ color: String) {
146
+ self.pinColor = color
147
+ }
148
+
149
+ func setCanShowCallout(_ show: Bool) {
150
+ self.canShowCallout = show
99
151
  }
100
152
 
101
153
  /**
@@ -10,6 +10,8 @@ import MAMapKit
10
10
  * - 响应属性变化并更新渲染
11
11
  */
12
12
  class PolygonView: ExpoView {
13
+ let onPress = EventDispatcher()
14
+
13
15
  /// 多边形点数组
14
16
  var points: [[String: Double]] = []
15
17
  /// 填充颜色
@@ -43,17 +45,29 @@ class PolygonView: ExpoView {
43
45
  * 更新多边形覆盖物
44
46
  */
45
47
  private func updatePolygon() {
46
- guard let mapView = mapView else { return }
48
+ guard let mapView = mapView else {
49
+ print("❌ PolygonView.updatePolygon: mapView 为空")
50
+ return
51
+ }
47
52
  if let old = polygon { mapView.remove(old) }
48
53
 
49
54
  var coords = points.compactMap { point -> CLLocationCoordinate2D? in
50
55
  guard let lat = point["latitude"], let lng = point["longitude"] else { return nil }
51
56
  return CLLocationCoordinate2D(latitude: lat, longitude: lng)
52
57
  }
53
- guard !coords.isEmpty else { return }
58
+ guard !coords.isEmpty else {
59
+ print("❌ PolygonView.updatePolygon: 点数组为空")
60
+ return
61
+ }
62
+
63
+ print("🔶 PolygonView.updatePolygon: points=\(coords.count)个点")
64
+ print("🔶 PolygonView.updatePolygon: fillColor=\(String(describing: fillColor)), strokeColor=\(String(describing: strokeColor)), strokeWidth=\(strokeWidth)")
54
65
 
55
66
  polygon = MAPolygon(coordinates: &coords, count: UInt(coords.count))
56
67
  mapView.add(polygon!)
68
+
69
+ renderer = nil
70
+ print("🔶 PolygonView.updatePolygon: renderer 已清空")
57
71
  }
58
72
 
59
73
  /**
@@ -63,9 +77,15 @@ class PolygonView: ExpoView {
63
77
  func getRenderer() -> MAOverlayRenderer {
64
78
  if renderer == nil, let polygon = polygon {
65
79
  renderer = MAPolygonRenderer(polygon: polygon)
66
- renderer?.fillColor = ColorParser.parseColor(fillColor) ?? UIColor.clear
67
- renderer?.strokeColor = ColorParser.parseColor(strokeColor) ?? UIColor.clear
80
+ let parsedFillColor = ColorParser.parseColor(fillColor)
81
+ let parsedStrokeColor = ColorParser.parseColor(strokeColor)
82
+ renderer?.fillColor = parsedFillColor ?? UIColor.clear
83
+ renderer?.strokeColor = parsedStrokeColor ?? UIColor.clear
68
84
  renderer?.lineWidth = CGFloat(strokeWidth)
85
+ print("🔶 PolygonView.getRenderer: 创建新 renderer")
86
+ print("🔶 PolygonView.getRenderer: fillColor=\(String(describing: parsedFillColor)), strokeColor=\(String(describing: parsedStrokeColor)), lineWidth=\(strokeWidth)")
87
+ } else {
88
+ print("🔶 PolygonView.getRenderer: 使用缓存的 renderer")
69
89
  }
70
90
  return renderer!
71
91
  }
@@ -76,7 +96,6 @@ class PolygonView: ExpoView {
76
96
  */
77
97
  func setPoints(_ points: [[String: Double]]) {
78
98
  self.points = points
79
- renderer = nil
80
99
  updatePolygon()
81
100
  }
82
101
 
@@ -85,6 +104,7 @@ class PolygonView: ExpoView {
85
104
  * @param color 颜色值
86
105
  */
87
106
  func setFillColor(_ color: Any?) {
107
+ print("🔶 PolygonView.setFillColor: \(String(describing: color))")
88
108
  fillColor = color
89
109
  renderer = nil
90
110
  updatePolygon()
@@ -95,6 +115,7 @@ class PolygonView: ExpoView {
95
115
  * @param color 颜色值
96
116
  */
97
117
  func setStrokeColor(_ color: Any?) {
118
+ print("🔶 PolygonView.setStrokeColor: \(String(describing: color))")
98
119
  strokeColor = color
99
120
  renderer = nil
100
121
  updatePolygon()
@@ -105,6 +126,7 @@ class PolygonView: ExpoView {
105
126
  * @param width 宽度值
106
127
  */
107
128
  func setStrokeWidth(_ width: Float) {
129
+ print("🔶 PolygonView.setStrokeWidth: \(width)")
108
130
  strokeWidth = width
109
131
  renderer = nil
110
132
  updatePolygon()