expo-gaode-map 0.1.6 → 1.0.1

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 (50) hide show
  1. package/PUBLISHING.md +1 -1
  2. package/README.md +68 -27
  3. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +117 -26
  4. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +97 -36
  5. package/android/src/main/java/expo/modules/gaodemap/managers/CameraManager.kt +27 -21
  6. package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +4 -23
  7. package/android/src/main/java/expo/modules/gaodemap/managers/UIManager.kt +30 -27
  8. package/android/src/main/java/expo/modules/gaodemap/modules/LocationManager.kt +49 -4
  9. package/android/src/main/java/expo/modules/gaodemap/modules/SDKInitializer.kt +13 -5
  10. package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +0 -6
  11. package/build/ExpoGaodeMapView.js +2 -2
  12. package/build/ExpoGaodeMapView.js.map +1 -1
  13. package/build/index.d.ts +2 -0
  14. package/build/index.d.ts.map +1 -1
  15. package/build/index.js +3 -1
  16. package/build/index.js.map +1 -1
  17. package/build/modules/AMapPermissions.d.ts +27 -0
  18. package/build/modules/AMapPermissions.d.ts.map +1 -0
  19. package/build/modules/AMapPermissions.js +31 -0
  20. package/build/modules/AMapPermissions.js.map +1 -0
  21. package/build/modules/AMapView.d.ts +7 -2
  22. package/build/modules/AMapView.d.ts.map +1 -1
  23. package/build/modules/AMapView.js +15 -3
  24. package/build/modules/AMapView.js.map +1 -1
  25. package/build/types/common.types.d.ts +1 -0
  26. package/build/types/common.types.d.ts.map +1 -1
  27. package/build/types/common.types.js +1 -0
  28. package/build/types/common.types.js.map +1 -1
  29. package/docs/API.md +5 -1
  30. package/docs/ARCHITECTURE.md +421 -0
  31. package/docs/EXAMPLES.md +166 -24
  32. package/docs/INITIALIZATION.md +335 -0
  33. package/ios/ExpoGaodeMapModule.swift +95 -9
  34. package/ios/ExpoGaodeMapView.swift +88 -6
  35. package/ios/managers/CameraManager.swift +58 -0
  36. package/ios/managers/OverlayManager.swift +105 -29
  37. package/ios/managers/UIManager.swift +73 -1
  38. package/ios/modules/LocationManager.swift +109 -3
  39. package/ios/overlays/CircleView.swift +53 -0
  40. package/ios/overlays/HeatMapView.swift +27 -0
  41. package/ios/overlays/MarkerView.swift +29 -1
  42. package/ios/overlays/PolygonView.swift +51 -0
  43. package/ios/overlays/PolylineView.swift +61 -14
  44. package/ios/utils/PermissionManager.swift +58 -0
  45. package/package.json +1 -1
  46. package/src/ExpoGaodeMapView.tsx +2 -2
  47. package/src/index.ts +9 -1
  48. package/src/modules/AMapPermissions.ts +48 -0
  49. package/src/modules/AMapView.ts +15 -3
  50. package/src/types/common.types.ts +1 -0
@@ -1,17 +1,39 @@
1
1
  import ExpoModulesCore
2
2
  import MAMapKit
3
3
 
4
+ /**
5
+ * 高德地图视图组件
6
+ *
7
+ * 负责:
8
+ * - 地图视图的创建和管理
9
+ * - 相机控制和手势交互
10
+ * - 覆盖物的添加和管理
11
+ * - 地图事件的派发
12
+ */
4
13
  class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
14
+ // MARK: - 属性
15
+
16
+ /// 地图类型 (0:标准 1:卫星 2:夜间 3:导航)
5
17
  var mapType: Int = 0
18
+ /// 初始相机位置
6
19
  var initialCameraPosition: [String: Any]?
20
+ /// 是否显示缩放控件
7
21
  var showsZoomControls: Bool = true
22
+ /// 是否显示指南针
8
23
  var showsCompass: Bool = true
24
+ /// 是否显示比例尺
9
25
  var showsScale: Bool = true
26
+ /// 是否启用缩放手势
10
27
  var isZoomEnabled: Bool = true
28
+ /// 是否启用滚动手势
11
29
  var isScrollEnabled: Bool = true
30
+ /// 是否启用旋转手势
12
31
  var isRotateEnabled: Bool = true
32
+ /// 是否启用倾斜手势
13
33
  var isTiltEnabled: Bool = true
34
+ /// 是否显示用户位置
14
35
  var showsUserLocation: Bool = false
36
+ /// 是否跟随用户位置
15
37
  var followUserLocation: Bool = false {
16
38
  didSet {
17
39
  if showsUserLocation {
@@ -19,23 +41,40 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
19
41
  }
20
42
  }
21
43
  }
44
+ /// 用户位置样式配置
22
45
  var userLocationRepresentation: [String: Any]?
46
+ /// 是否显示交通路况
23
47
  var showsTraffic: Bool = false
48
+ /// 是否显示建筑物
24
49
  var showsBuildings: Bool = false
50
+ /// 是否显示室内地图
25
51
  var showsIndoorMap: Bool = false
52
+ /// 最大缩放级别
26
53
  var maxZoomLevel: CGFloat = 20
54
+ /// 最小缩放级别
27
55
  var minZoomLevel: CGFloat = 3
28
56
 
57
+ // MARK: - 事件派发器
58
+
29
59
  let onMapPress = EventDispatcher()
30
60
  let onMapLongPress = EventDispatcher()
31
61
  let onLoad = EventDispatcher()
32
62
 
63
+ // MARK: - 私有属性
64
+
65
+ /// 高德地图视图实例
33
66
  private var mapView: MAMapView!
67
+ /// 相机管理器
34
68
  private var cameraManager: CameraManager!
69
+ /// UI 管理器
35
70
  private var uiManager: UIManager!
71
+ /// 覆盖物管理器
36
72
  private var overlayManager: OverlayManager!
73
+ /// 地图是否已加载完成
37
74
  private var isMapLoaded = false
38
75
 
76
+ // MARK: - 初始化
77
+
39
78
  required init(appContext: AppContext? = nil) {
40
79
  super.init(appContext: appContext)
41
80
 
@@ -60,10 +99,13 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
60
99
  mapView.frame = bounds
61
100
  }
62
101
 
102
+ /**
103
+ * 添加子视图时自动连接到地图
104
+ * 将地图实例传递给覆盖物子视图
105
+ */
63
106
  override func addSubview(_ view: UIView) {
64
107
  super.addSubview(view)
65
108
 
66
- // 自动将地图实例传递给覆盖物子视图
67
109
  if let markerView = view as? MarkerView {
68
110
  markerView.setMap(mapView)
69
111
  } else if let circleView = view as? CircleView {
@@ -81,6 +123,9 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
81
123
  }
82
124
  }
83
125
 
126
+ /**
127
+ * 设置默认配置
128
+ */
84
129
  private func setupDefaultConfig() {
85
130
  uiManager.setMapType(0)
86
131
  uiManager.setShowsScale(showsScale)
@@ -92,6 +137,10 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
92
137
  uiManager.setShowsUserLocation(showsUserLocation, followUser: followUserLocation)
93
138
  }
94
139
 
140
+ /**
141
+ * 应用所有属性配置
142
+ * 在 Props 更新时调用
143
+ */
95
144
  func applyProps() {
96
145
  uiManager.setMapType(mapType)
97
146
 
@@ -111,6 +160,8 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
111
160
  uiManager.setShowsIndoorMap(showsIndoorMap)
112
161
  }
113
162
 
163
+ // MARK: - 缩放控制
164
+
114
165
  func setMaxZoom(_ maxZoom: Double) {
115
166
  cameraManager.setMaxZoomLevel(CGFloat(maxZoom))
116
167
  }
@@ -119,6 +170,8 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
119
170
  cameraManager.setMinZoomLevel(CGFloat(minZoom))
120
171
  }
121
172
 
173
+ // MARK: - 相机控制
174
+
122
175
  func moveCamera(position: [String: Any], duration: Int) {
123
176
  cameraManager.moveCamera(position: position, duration: duration)
124
177
  }
@@ -139,6 +192,8 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
139
192
  return cameraManager.getCameraPosition()
140
193
  }
141
194
 
195
+ // MARK: - 覆盖物管理
196
+
142
197
  func addCircle(id: String, props: [String: Any]) {
143
198
  overlayManager.addCircle(id: id, props: props)
144
199
  }
@@ -187,6 +242,8 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
187
242
  overlayManager.updatePolygon(id: id, props: props)
188
243
  }
189
244
 
245
+ // MARK: - 图层控制
246
+
190
247
  func setShowsTraffic(_ show: Bool) {
191
248
  showsTraffic = show
192
249
  uiManager.setShowsTraffic(show)
@@ -204,7 +261,6 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
204
261
 
205
262
  func setFollowUserLocation(_ follow: Bool) {
206
263
  followUserLocation = follow
207
- // 如果定位已开启,立即应用新设置
208
264
  uiManager.setShowsUserLocation(showsUserLocation, followUser: follow)
209
265
  }
210
266
 
@@ -223,13 +279,29 @@ class ExpoGaodeMapView: ExpoView, MAMapViewDelegate {
223
279
  }
224
280
  }
225
281
 
282
+ /**
283
+ * 应用用户位置样式
284
+ */
226
285
  private func applyUserLocationStyle() {
227
286
  guard let config = userLocationRepresentation else { return }
228
287
  uiManager.setUserLocationRepresentation(config)
229
288
  }
289
+
290
+ /**
291
+ * 析构函数 - 清理资源
292
+ */
293
+ deinit {
294
+ mapView?.delegate = nil
295
+ overlayManager?.clear()
296
+ }
230
297
  }
231
298
 
299
+ // MARK: - MAMapViewDelegate
300
+
232
301
  extension ExpoGaodeMapView {
302
+ /**
303
+ * 地图加载完成回调
304
+ */
233
305
  public func mapViewDidFinishLoadingMap(_ mapView: MAMapView) {
234
306
  guard !isMapLoaded else { return }
235
307
  isMapLoaded = true
@@ -239,16 +311,25 @@ extension ExpoGaodeMapView {
239
311
  onLoad(["loaded": true])
240
312
  }
241
313
 
314
+ /**
315
+ * 地图单击事件
316
+ */
242
317
  public func mapView(_ mapView: MAMapView, didSingleTappedAt coordinate: CLLocationCoordinate2D) {
243
318
  onMapPress(["latitude": coordinate.latitude, "longitude": coordinate.longitude])
244
319
  }
245
320
 
321
+ /**
322
+ * 地图长按事件
323
+ */
246
324
  public func mapView(_ mapView: MAMapView, didLongPressedAt coordinate: CLLocationCoordinate2D) {
247
325
  onMapLongPress(["latitude": coordinate.latitude, "longitude": coordinate.longitude])
248
326
  }
249
327
 
328
+ /**
329
+ * 创建标注视图
330
+ * 定位蓝点返回 nil 使用系统默认样式
331
+ */
250
332
  public func mapView(_ mapView: MAMapView, viewFor annotation: MAAnnotation) -> MAAnnotationView? {
251
- // 定位蓝点返回 nil,使用系统默认样式
252
333
  if annotation.isKind(of: MAUserLocation.self) {
253
334
  return nil
254
335
  }
@@ -265,8 +346,11 @@ extension ExpoGaodeMapView {
265
346
  return nil
266
347
  }
267
348
 
349
+ /**
350
+ * 创建覆盖物渲染器
351
+ * 优先使用子视图的渲染器,否则使用 OverlayManager 的渲染器
352
+ */
268
353
  public func mapView(_ mapView: MAMapView, rendererFor overlay: MAOverlay) -> MAOverlayRenderer {
269
- // 首先检查是否是通过子视图添加的覆盖物
270
354
  for subview in subviews {
271
355
  if let circleView = subview as? CircleView, circleView.circle === overlay {
272
356
  return circleView.getRenderer()
@@ -277,8 +361,6 @@ extension ExpoGaodeMapView {
277
361
  }
278
362
  }
279
363
 
280
- // 否则使用 OverlayManager 的渲染器
281
364
  return overlayManager.getRenderer(for: overlay) ?? MAOverlayRenderer(overlay: overlay)
282
365
  }
283
366
  }
284
-
@@ -1,21 +1,47 @@
1
1
  import ExpoModulesCore
2
2
  import MAMapKit
3
3
 
4
+ /**
5
+ * 相机管理器
6
+ *
7
+ * 负责:
8
+ * - 相机位置和视角控制
9
+ * - 缩放级别管理
10
+ * - 坐标转换
11
+ */
4
12
  class CameraManager {
13
+ /// 弱引用地图视图,避免循环引用
5
14
  private weak var mapView: MAMapView?
6
15
 
7
16
  init(mapView: MAMapView) {
8
17
  self.mapView = mapView
9
18
  }
10
19
 
20
+ // MARK: - 缩放级别控制
21
+
22
+ /**
23
+ * 设置最大缩放级别
24
+ * @param maxZoom 最大缩放级别 (3-20)
25
+ */
11
26
  func setMaxZoomLevel(_ maxZoom: CGFloat) {
12
27
  mapView?.maxZoomLevel = maxZoom
13
28
  }
14
29
 
30
+ /**
31
+ * 设置最小缩放级别
32
+ * @param minZoom 最小缩放级别 (3-20)
33
+ */
15
34
  func setMinZoomLevel(_ minZoom: CGFloat) {
16
35
  mapView?.minZoomLevel = minZoom
17
36
  }
18
37
 
38
+ // MARK: - 相机位置控制
39
+
40
+ /**
41
+ * 设置初始相机位置
42
+ * 不带动画,用于地图初始化
43
+ * @param position 包含 target、zoom、bearing、tilt 的字典
44
+ */
19
45
  func setInitialCameraPosition(_ position: [String: Any]) {
20
46
  guard let mapView = mapView else { return }
21
47
  let status = MAMapStatus()
@@ -41,10 +67,18 @@ class CameraManager {
41
67
  mapView.setMapStatus(status, animated: false, duration: 0)
42
68
  }
43
69
 
70
+ /**
71
+ * 移动相机到指定位置
72
+ * 支持动画效果
73
+ * @param position 目标位置信息
74
+ * @param duration 动画时长(毫秒)
75
+ */
44
76
  func moveCamera(position: [String: Any], duration: Int) {
45
77
  guard let mapView = mapView else { return }
78
+
46
79
  let status = MAMapStatus()
47
80
 
81
+ // 设置中心点,如果未提供则保持当前值
48
82
  if let target = position["target"] as? [String: Double],
49
83
  let latitude = target["latitude"],
50
84
  let longitude = target["longitude"] {
@@ -53,18 +87,21 @@ class CameraManager {
53
87
  status.centerCoordinate = mapView.centerCoordinate
54
88
  }
55
89
 
90
+ // 设置缩放级别
56
91
  if let zoom = position["zoom"] as? Double {
57
92
  status.zoomLevel = CGFloat(zoom)
58
93
  } else {
59
94
  status.zoomLevel = mapView.zoomLevel
60
95
  }
61
96
 
97
+ // 设置旋转角度
62
98
  if let bearing = position["bearing"] as? Double {
63
99
  status.rotationDegree = CGFloat(bearing)
64
100
  } else {
65
101
  status.rotationDegree = mapView.rotationDegree
66
102
  }
67
103
 
104
+ // 设置倾斜角度
68
105
  if let tilt = position["tilt"] as? Double {
69
106
  status.cameraDegree = CGFloat(tilt)
70
107
  } else {
@@ -74,6 +111,11 @@ class CameraManager {
74
111
  mapView.setMapStatus(status, animated: duration > 0, duration: TimeInterval(duration) / 1000.0)
75
112
  }
76
113
 
114
+ /**
115
+ * 设置地图中心点
116
+ * @param center 中心点坐标
117
+ * @param animated 是否使用动画
118
+ */
77
119
  func setCenter(center: [String: Double], animated: Bool) {
78
120
  guard let mapView = mapView,
79
121
  let latitude = center["latitude"],
@@ -81,10 +123,21 @@ class CameraManager {
81
123
  mapView.setCenter(CLLocationCoordinate2D(latitude: latitude, longitude: longitude), animated: animated)
82
124
  }
83
125
 
126
+ /**
127
+ * 设置缩放级别
128
+ * @param zoom 缩放级别 (3-20)
129
+ * @param animated 是否使用动画
130
+ */
84
131
  func setZoomLevel(zoom: CGFloat, animated: Bool) {
85
132
  mapView?.setZoomLevel(zoom, animated: animated)
86
133
  }
87
134
 
135
+ // MARK: - 相机信息获取
136
+
137
+ /**
138
+ * 获取当前相机位置信息
139
+ * @return 包含 target、zoom、bearing、tilt 的字典
140
+ */
88
141
  func getCameraPosition() -> [String: Any] {
89
142
  guard let mapView = mapView else { return [:] }
90
143
  let center = mapView.centerCoordinate
@@ -96,6 +149,11 @@ class CameraManager {
96
149
  ]
97
150
  }
98
151
 
152
+ /**
153
+ * 将屏幕坐标转换为地理坐标
154
+ * @param point 屏幕坐标点 {x, y}
155
+ * @return 地理坐标 {latitude, longitude}
156
+ */
99
157
  func getLatLng(point: [String: Double]) -> [String: Double] {
100
158
  guard let mapView = mapView,
101
159
  let x = point["x"],
@@ -1,17 +1,39 @@
1
1
  import MAMapKit
2
2
 
3
+ /**
4
+ * 覆盖物管理器
5
+ *
6
+ * 负责:
7
+ * - 管理地图覆盖物(圆形、折线、多边形)
8
+ * - 管理标记点(Marker)
9
+ * - 处理覆盖物样式和渲染
10
+ * - 支持纹理贴图
11
+ */
3
12
  class OverlayManager {
13
+ /// 地图视图弱引用
4
14
  private weak var mapView: MAMapView?
15
+ /// 覆盖物字典 (id -> overlay)
5
16
  private var overlays: [String: MAOverlay] = [:]
17
+ /// 覆盖物样式字典 (id -> style)
6
18
  private var overlayStyles: [String: [String: Any]] = [:]
19
+ /// 标记点字典 (id -> annotation)
7
20
  private var annotations: [String: MAPointAnnotation] = [:]
8
21
 
22
+ /**
23
+ * 初始化覆盖物管理器
24
+ * @param mapView 地图视图实例
25
+ */
9
26
  init(mapView: MAMapView) {
10
27
  self.mapView = mapView
11
28
  }
12
29
 
13
- // MARK: - Circle
30
+ // MARK: - Circle 圆形
14
31
 
32
+ /**
33
+ * 添加圆形覆盖物
34
+ * @param id 圆形唯一标识
35
+ * @param props 圆形属性(center, radius, fillColor, strokeColor, strokeWidth)
36
+ */
15
37
  func addCircle(id: String, props: [String: Any]) {
16
38
  guard let mapView = mapView,
17
39
  let center = props["center"] as? [String: Double],
@@ -25,6 +47,10 @@ class OverlayManager {
25
47
  overlays[id] = circle
26
48
  }
27
49
 
50
+ /**
51
+ * 移除圆形覆盖物
52
+ * @param id 圆形唯一标识
53
+ */
28
54
  func removeCircle(id: String) {
29
55
  guard let mapView = mapView, let circle = overlays[id] else { return }
30
56
  mapView.remove(circle)
@@ -32,13 +58,23 @@ class OverlayManager {
32
58
  overlayStyles.removeValue(forKey: id)
33
59
  }
34
60
 
61
+ /**
62
+ * 更新圆形覆盖物
63
+ * @param id 圆形唯一标识
64
+ * @param props 新的圆形属性
65
+ */
35
66
  func updateCircle(id: String, props: [String: Any]) {
36
67
  removeCircle(id: id)
37
68
  addCircle(id: id, props: props)
38
69
  }
39
70
 
40
- // MARK: - Marker
71
+ // MARK: - Marker 标记点
41
72
 
73
+ /**
74
+ * 添加标记点
75
+ * @param id 标记点唯一标识
76
+ * @param props 标记点属性(position, title, description)
77
+ */
42
78
  func addMarker(id: String, props: [String: Any]) {
43
79
  guard let mapView = mapView,
44
80
  let position = props["position"] as? [String: Double],
@@ -53,25 +89,36 @@ class OverlayManager {
53
89
  annotations[id] = annotation
54
90
  }
55
91
 
92
+ /**
93
+ * 移除标记点
94
+ * @param id 标记点唯一标识
95
+ */
56
96
  func removeMarker(id: String) {
57
97
  guard let mapView = mapView, let annotation = annotations[id] else { return }
58
98
  mapView.removeAnnotation(annotation)
59
99
  annotations.removeValue(forKey: id)
60
100
  }
61
101
 
102
+ /**
103
+ * 更新标记点
104
+ * @param id 标记点唯一标识
105
+ * @param props 新的标记点属性
106
+ */
62
107
  func updateMarker(id: String, props: [String: Any]) {
63
108
  removeMarker(id: id)
64
109
  addMarker(id: id, props: props)
65
110
  }
66
111
 
67
- // MARK: - Polyline
112
+ // MARK: - Polyline 折线
68
113
 
114
+ /**
115
+ * 添加折线覆盖物
116
+ * @param id 折线唯一标识
117
+ * @param props 折线属性(points, strokeWidth, strokeColor, texture)
118
+ */
69
119
  func addPolyline(id: String, props: [String: Any]) {
70
- print("📏 OverlayManager.addPolyline - id: \(id), props: \(props)")
71
-
72
120
  guard let mapView = mapView,
73
121
  let points = props["points"] as? [[String: Double]] else {
74
- print("❌ OverlayManager.addPolyline - mapView 或 points 为空")
75
122
  return
76
123
  }
77
124
 
@@ -81,7 +128,6 @@ class OverlayManager {
81
128
  coordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lng))
82
129
  }
83
130
  guard coordinates.count >= 2 else {
84
- print("❌ OverlayManager.addPolyline - 坐标点数量不足: \(coordinates.count)")
85
131
  return
86
132
  }
87
133
 
@@ -90,12 +136,13 @@ class OverlayManager {
90
136
  // 先保存样式和 overlay,再添加到地图
91
137
  overlayStyles[id] = props
92
138
  overlays[id] = polyline
93
-
94
- print("✅ OverlayManager.addPolyline - 准备添加到地图,id: \(id)")
95
139
  mapView.add(polyline)
96
- print("✅ OverlayManager.addPolyline - 已添加到地图")
97
140
  }
98
141
 
142
+ /**
143
+ * 移除折线覆盖物
144
+ * @param id 折线唯一标识
145
+ */
99
146
  func removePolyline(id: String) {
100
147
  guard let mapView = mapView, let polyline = overlays[id] else { return }
101
148
  mapView.remove(polyline)
@@ -103,13 +150,23 @@ class OverlayManager {
103
150
  overlayStyles.removeValue(forKey: id)
104
151
  }
105
152
 
153
+ /**
154
+ * 更新折线覆盖物
155
+ * @param id 折线唯一标识
156
+ * @param props 新的折线属性
157
+ */
106
158
  func updatePolyline(id: String, props: [String: Any]) {
107
159
  removePolyline(id: id)
108
160
  addPolyline(id: id, props: props)
109
161
  }
110
162
 
111
- // MARK: - Polygon
163
+ // MARK: - Polygon 多边形
112
164
 
165
+ /**
166
+ * 添加多边形覆盖物
167
+ * @param id 多边形唯一标识
168
+ * @param props 多边形属性(points, fillColor, strokeColor, strokeWidth)
169
+ */
113
170
  func addPolygon(id: String, props: [String: Any]) {
114
171
  guard let mapView = mapView,
115
172
  let points = props["points"] as? [[String: Double]] else { return }
@@ -125,6 +182,10 @@ class OverlayManager {
125
182
  overlays[id] = polygon
126
183
  }
127
184
 
185
+ /**
186
+ * 移除多边形覆盖物
187
+ * @param id 多边形唯一标识
188
+ */
128
189
  func removePolygon(id: String) {
129
190
  guard let mapView = mapView, let polygon = overlays[id] else { return }
130
191
  mapView.remove(polygon)
@@ -132,30 +193,41 @@ class OverlayManager {
132
193
  overlayStyles.removeValue(forKey: id)
133
194
  }
134
195
 
196
+ /**
197
+ * 更新多边形覆盖物
198
+ * @param id 多边形唯一标识
199
+ * @param props 新的多边形属性
200
+ */
135
201
  func updatePolygon(id: String, props: [String: Any]) {
136
202
  removePolygon(id: id)
137
203
  addPolygon(id: id, props: props)
138
204
  }
139
205
 
140
- // MARK: - Renderer
206
+ // MARK: - Renderer 渲染器
141
207
 
208
+ /**
209
+ * 获取覆盖物渲染器
210
+ * @param overlay 覆盖物对象
211
+ * @return 对应的渲染器
212
+ */
142
213
  func getRenderer(for overlay: MAOverlay) -> MAOverlayRenderer? {
143
214
  let id = overlays.first(where: { $0.value === overlay })?.key
144
215
  let style = id != nil ? overlayStyles[id!] : nil
145
216
 
146
- print("🎨 OverlayManager.getRenderer - overlay类型: \(type(of: overlay)), id: \(id ?? "nil"), style: \(style ?? [:])")
147
-
148
217
  if let circle = overlay as? MACircle {
149
218
  guard let renderer = MACircleRenderer(circle: circle) else {
150
219
  return nil
151
220
  }
152
221
 
222
+ // 设置填充颜色
153
223
  if let fillColor = style?["fillColor"] {
154
224
  renderer.fillColor = ColorParser.parseColor(fillColor)
155
225
  }
226
+ // 设置边框颜色
156
227
  if let strokeColor = style?["strokeColor"] {
157
228
  renderer.strokeColor = ColorParser.parseColor(strokeColor)
158
229
  }
230
+ // 设置边框宽度
159
231
  if let strokeWidth = style?["strokeWidth"] as? Double {
160
232
  renderer.lineWidth = CGFloat(strokeWidth)
161
233
  }
@@ -182,17 +254,12 @@ class OverlayManager {
182
254
  loadPolylineTexture(url: textureUrl, renderer: renderer)
183
255
  } else {
184
256
  if let color = style?["color"] {
185
- print("🎨 color 原始值: \(color), 类型: \(type(of: color))")
186
257
  let parsedColor = ColorParser.parseColor(color)
187
- print("🎨 解析后的颜色: \(String(describing: parsedColor))")
188
258
  renderer.strokeColor = parsedColor ?? .red
189
259
  } else if let strokeColor = style?["strokeColor"] {
190
- print("🎨 strokeColor 原始值: \(strokeColor), 类型: \(type(of: strokeColor))")
191
260
  let parsedColor = ColorParser.parseColor(strokeColor)
192
- print("🎨 解析后的颜色: \(String(describing: parsedColor))")
193
261
  renderer.strokeColor = parsedColor ?? .red
194
262
  } else {
195
- print("⚠️ 没有找到 color 或 strokeColor,使用默认红色")
196
263
  renderer.strokeColor = .red
197
264
  }
198
265
  }
@@ -203,12 +270,15 @@ class OverlayManager {
203
270
  return nil
204
271
  }
205
272
 
273
+ // 设置填充颜色
206
274
  if let fillColor = style?["fillColor"] {
207
275
  renderer.fillColor = ColorParser.parseColor(fillColor)
208
276
  }
277
+ // 设置边框颜色
209
278
  if let strokeColor = style?["strokeColor"] {
210
279
  renderer.strokeColor = ColorParser.parseColor(strokeColor)
211
280
  }
281
+ // 设置边框宽度
212
282
  if let strokeWidth = style?["strokeWidth"] as? Double {
213
283
  renderer.lineWidth = CGFloat(strokeWidth)
214
284
  }
@@ -219,48 +289,54 @@ class OverlayManager {
219
289
  return nil
220
290
  }
221
291
 
292
+ /**
293
+ * 加载折线纹理图片
294
+ * @param url 图片 URL (支持 http/https/file/本地资源)
295
+ * @param renderer 折线渲染器
296
+ */
222
297
  private func loadPolylineTexture(url: String, renderer: MAPolylineRenderer) {
223
298
  if url.hasPrefix("http://") || url.hasPrefix("https://") {
299
+ // 网络图片
224
300
  guard let imageUrl = URL(string: url) else {
225
- print("❌ OverlayManager: 无效的 URL: \(url)")
226
301
  return
227
302
  }
228
303
  URLSession.shared.dataTask(with: imageUrl) { [weak self] data, _, error in
229
304
  if let error = error {
230
- print("❌ OverlayManager: 下载图片失败: \(error)")
231
305
  return
232
306
  }
233
307
  guard let data = data, let image = UIImage(data: data) else {
234
- print("❌ OverlayManager: 无法创建图片")
235
308
  return
236
309
  }
237
- print("✅ OverlayManager: 图片下载成功,大小: \(image.size)")
238
310
  DispatchQueue.main.async {
239
311
  self?.applyPolylineTexture(image: image, to: renderer)
240
312
  }
241
313
  }.resume()
242
314
  } else if url.hasPrefix("file://") {
315
+ // 本地文件
243
316
  let path = String(url.dropFirst(7))
244
317
  if let image = UIImage(contentsOfFile: path) {
245
- print("✅ OverlayManager: 本地图片加载成功")
246
318
  applyPolylineTexture(image: image, to: renderer)
247
- } else {
248
- print("❌ OverlayManager: 本地图片加载失败: \(path)")
249
319
  }
250
320
  } else {
321
+ // 资源文件
251
322
  if let image = UIImage(named: url) {
252
- print("✅ OverlayManager: 资源图片加载成功")
253
323
  applyPolylineTexture(image: image, to: renderer)
254
- } else {
255
- print("❌ OverlayManager: 资源图片加载失败: \(url)")
256
324
  }
257
325
  }
258
326
  }
259
327
 
328
+ /**
329
+ * 应用纹理到折线渲染器
330
+ * @param image 纹理图片
331
+ * @param renderer 折线渲染器
332
+ */
260
333
  private func applyPolylineTexture(image: UIImage, to renderer: MAPolylineRenderer) {
261
334
  renderer.strokeImage = image
262
335
  }
263
336
 
337
+ /**
338
+ * 清除所有覆盖物和标记点
339
+ */
264
340
  func clear() {
265
341
  guard let mapView = mapView else { return }
266
342
  for overlay in overlays.values {