expo-gaode-map 0.1.5 → 1.0.0

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 (61) hide show
  1. package/PUBLISHING.md +1 -1
  2. package/README.md +57 -9
  3. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +121 -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 +37 -24
  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/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +54 -3
  12. package/build/ExpoGaodeMapView.js +2 -2
  13. package/build/ExpoGaodeMapView.js.map +1 -1
  14. package/build/components/overlays/Polyline.d.ts.map +1 -1
  15. package/build/components/overlays/Polyline.js +12 -14
  16. package/build/components/overlays/Polyline.js.map +1 -1
  17. package/build/index.d.ts +2 -0
  18. package/build/index.d.ts.map +1 -1
  19. package/build/index.js +3 -1
  20. package/build/index.js.map +1 -1
  21. package/build/modules/AMapPermissions.d.ts +27 -0
  22. package/build/modules/AMapPermissions.d.ts.map +1 -0
  23. package/build/modules/AMapPermissions.js +31 -0
  24. package/build/modules/AMapPermissions.js.map +1 -0
  25. package/build/modules/AMapView.d.ts +7 -2
  26. package/build/modules/AMapView.d.ts.map +1 -1
  27. package/build/modules/AMapView.js +15 -3
  28. package/build/modules/AMapView.js.map +1 -1
  29. package/build/types/common.types.d.ts +1 -0
  30. package/build/types/common.types.d.ts.map +1 -1
  31. package/build/types/common.types.js +1 -0
  32. package/build/types/common.types.js.map +1 -1
  33. package/build/types/overlays.types.d.ts +5 -0
  34. package/build/types/overlays.types.d.ts.map +1 -1
  35. package/build/types/overlays.types.js.map +1 -1
  36. package/docs/API.md +5 -1
  37. package/docs/ARCHITECTURE.md +421 -0
  38. package/docs/EXAMPLES.md +232 -29
  39. package/docs/INITIALIZATION.md +342 -0
  40. package/ios/ExpoGaodeMapModule.swift +99 -9
  41. package/ios/ExpoGaodeMapView.swift +88 -6
  42. package/ios/managers/CameraManager.swift +58 -0
  43. package/ios/managers/OverlayManager.swift +172 -30
  44. package/ios/managers/UIManager.swift +73 -1
  45. package/ios/modules/LocationManager.swift +109 -3
  46. package/ios/overlays/CircleView.swift +53 -0
  47. package/ios/overlays/HeatMapView.swift +27 -0
  48. package/ios/overlays/MarkerView.swift +29 -1
  49. package/ios/overlays/PolygonView.swift +51 -0
  50. package/ios/overlays/PolylineView.swift +110 -1
  51. package/ios/{ColorParser.swift → utils/ColorParser.swift} +13 -7
  52. package/ios/utils/PermissionManager.swift +58 -0
  53. package/package.json +1 -1
  54. package/src/ExpoGaodeMapView.tsx +2 -2
  55. package/src/components/overlays/Polyline.tsx +13 -16
  56. package/src/index.ts +9 -1
  57. package/src/modules/AMapPermissions.ts +48 -0
  58. package/src/modules/AMapView.ts +15 -3
  59. package/src/types/common.types.ts +1 -0
  60. package/src/types/overlays.types.ts +6 -0
  61. package/ios/UIColorExtension.swift +0 -11
@@ -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,42 +89,60 @@ 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
120
  guard let mapView = mapView,
71
- let points = props["points"] as? [[String: Double]] else { return }
121
+ let points = props["points"] as? [[String: Double]] else {
122
+ return
123
+ }
124
+
72
125
  var coordinates: [CLLocationCoordinate2D] = []
73
126
  for point in points {
74
127
  guard let lat = point["latitude"], let lng = point["longitude"] else { continue }
75
128
  coordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lng))
76
129
  }
77
- guard !coordinates.isEmpty else { return }
130
+ guard coordinates.count >= 2 else {
131
+ return
132
+ }
78
133
 
79
- let polyline = MAMultiPolyline()
80
- polyline.setPolylineWithCoordinates(&coordinates, count: coordinates.count)
134
+ let polyline = MAPolyline(coordinates: &coordinates, count: UInt(coordinates.count))!
81
135
 
136
+ // 先保存样式和 overlay,再添加到地图
82
137
  overlayStyles[id] = props
83
138
  overlays[id] = polyline
84
139
  mapView.add(polyline)
85
-
86
- // 强制刷新地图渲染
87
- DispatchQueue.main.async {
88
- mapView.setNeedsDisplay()
89
- }
90
140
  }
91
141
 
142
+ /**
143
+ * 移除折线覆盖物
144
+ * @param id 折线唯一标识
145
+ */
92
146
  func removePolyline(id: String) {
93
147
  guard let mapView = mapView, let polyline = overlays[id] else { return }
94
148
  mapView.remove(polyline)
@@ -96,13 +150,23 @@ class OverlayManager {
96
150
  overlayStyles.removeValue(forKey: id)
97
151
  }
98
152
 
153
+ /**
154
+ * 更新折线覆盖物
155
+ * @param id 折线唯一标识
156
+ * @param props 新的折线属性
157
+ */
99
158
  func updatePolyline(id: String, props: [String: Any]) {
100
159
  removePolyline(id: id)
101
160
  addPolyline(id: id, props: props)
102
161
  }
103
162
 
104
- // MARK: - Polygon
163
+ // MARK: - Polygon 多边形
105
164
 
165
+ /**
166
+ * 添加多边形覆盖物
167
+ * @param id 多边形唯一标识
168
+ * @param props 多边形属性(points, fillColor, strokeColor, strokeWidth)
169
+ */
106
170
  func addPolygon(id: String, props: [String: Any]) {
107
171
  guard let mapView = mapView,
108
172
  let points = props["points"] as? [[String: Double]] else { return }
@@ -118,6 +182,10 @@ class OverlayManager {
118
182
  overlays[id] = polygon
119
183
  }
120
184
 
185
+ /**
186
+ * 移除多边形覆盖物
187
+ * @param id 多边形唯一标识
188
+ */
121
189
  func removePolygon(id: String) {
122
190
  guard let mapView = mapView, let polygon = overlays[id] else { return }
123
191
  mapView.remove(polygon)
@@ -125,66 +193,92 @@ class OverlayManager {
125
193
  overlayStyles.removeValue(forKey: id)
126
194
  }
127
195
 
196
+ /**
197
+ * 更新多边形覆盖物
198
+ * @param id 多边形唯一标识
199
+ * @param props 新的多边形属性
200
+ */
128
201
  func updatePolygon(id: String, props: [String: Any]) {
129
202
  removePolygon(id: id)
130
203
  addPolygon(id: id, props: props)
131
204
  }
132
205
 
133
- // MARK: - Renderer
206
+ // MARK: - Renderer 渲染器
134
207
 
208
+ /**
209
+ * 获取覆盖物渲染器
210
+ * @param overlay 覆盖物对象
211
+ * @return 对应的渲染器
212
+ */
135
213
  func getRenderer(for overlay: MAOverlay) -> MAOverlayRenderer? {
136
214
  let id = overlays.first(where: { $0.value === overlay })?.key
137
215
  let style = id != nil ? overlayStyles[id!] : nil
138
216
 
139
- print("🎨 OverlayManager.getRenderer - overlay类型: \(type(of: overlay)), id: \(id ?? "nil"), style: \(style ?? [:])")
140
-
141
217
  if let circle = overlay as? MACircle {
142
218
  guard let renderer = MACircleRenderer(circle: circle) else {
143
219
  return nil
144
220
  }
145
221
 
222
+ // 设置填充颜色
146
223
  if let fillColor = style?["fillColor"] {
147
224
  renderer.fillColor = ColorParser.parseColor(fillColor)
148
225
  }
226
+ // 设置边框颜色
149
227
  if let strokeColor = style?["strokeColor"] {
150
228
  renderer.strokeColor = ColorParser.parseColor(strokeColor)
151
229
  }
230
+ // 设置边框宽度
152
231
  if let strokeWidth = style?["strokeWidth"] as? Double {
153
232
  renderer.lineWidth = CGFloat(strokeWidth)
154
233
  }
155
234
 
156
235
  return renderer
157
- } else if let polyline = overlay as? MAMultiPolyline {
158
- let renderer = MAMultiColoredPolylineRenderer(multiPolyline: polyline)
236
+ } else if let polyline = overlay as? MAPolyline {
237
+ let renderer = MAPolylineRenderer(polyline: polyline)!
159
238
 
160
- if let color = style?["color"] {
161
- renderer?.strokeColor = ColorParser.parseColor(color) ?? .red
162
- } else if let strokeColor = style?["strokeColor"] {
163
- renderer?.strokeColor = ColorParser.parseColor(strokeColor) ?? .red
239
+ // 设置线宽
240
+ if let width = style?["width"] as? Double {
241
+ renderer.lineWidth = CGFloat(width)
242
+ } else if let strokeWidth = style?["strokeWidth"] as? Double {
243
+ renderer.lineWidth = CGFloat(strokeWidth)
164
244
  } else {
165
- renderer?.strokeColor = .red
245
+ renderer.lineWidth = 8
166
246
  }
167
247
 
168
- if let width = style?["width"] as? Double {
169
- renderer?.lineWidth = CGFloat(width)
170
- } else if let strokeWidth = style?["strokeWidth"] as? Double {
171
- renderer?.lineWidth = CGFloat(strokeWidth)
248
+ // 设置线条样式
249
+ renderer.lineJoinType = kMALineJoinRound
250
+ renderer.lineCapType = kMALineCapRound
251
+
252
+ // 设置纹理或颜色
253
+ if let textureUrl = style?["texture"] as? String, !textureUrl.isEmpty {
254
+ loadPolylineTexture(url: textureUrl, renderer: renderer)
172
255
  } else {
173
- renderer?.lineWidth = 5
256
+ if let color = style?["color"] {
257
+ let parsedColor = ColorParser.parseColor(color)
258
+ renderer.strokeColor = parsedColor ?? .red
259
+ } else if let strokeColor = style?["strokeColor"] {
260
+ let parsedColor = ColorParser.parseColor(strokeColor)
261
+ renderer.strokeColor = parsedColor ?? .red
262
+ } else {
263
+ renderer.strokeColor = .red
264
+ }
174
265
  }
175
266
 
176
- return renderer!
267
+ return renderer
177
268
  } else if let polygon = overlay as? MAPolygon {
178
269
  guard let renderer = MAPolygonRenderer(polygon: polygon) else {
179
270
  return nil
180
271
  }
181
272
 
273
+ // 设置填充颜色
182
274
  if let fillColor = style?["fillColor"] {
183
275
  renderer.fillColor = ColorParser.parseColor(fillColor)
184
276
  }
277
+ // 设置边框颜色
185
278
  if let strokeColor = style?["strokeColor"] {
186
279
  renderer.strokeColor = ColorParser.parseColor(strokeColor)
187
280
  }
281
+ // 设置边框宽度
188
282
  if let strokeWidth = style?["strokeWidth"] as? Double {
189
283
  renderer.lineWidth = CGFloat(strokeWidth)
190
284
  }
@@ -195,6 +289,54 @@ class OverlayManager {
195
289
  return nil
196
290
  }
197
291
 
292
+ /**
293
+ * 加载折线纹理图片
294
+ * @param url 图片 URL (支持 http/https/file/本地资源)
295
+ * @param renderer 折线渲染器
296
+ */
297
+ private func loadPolylineTexture(url: String, renderer: MAPolylineRenderer) {
298
+ if url.hasPrefix("http://") || url.hasPrefix("https://") {
299
+ // 网络图片
300
+ guard let imageUrl = URL(string: url) else {
301
+ return
302
+ }
303
+ URLSession.shared.dataTask(with: imageUrl) { [weak self] data, _, error in
304
+ if let error = error {
305
+ return
306
+ }
307
+ guard let data = data, let image = UIImage(data: data) else {
308
+ return
309
+ }
310
+ DispatchQueue.main.async {
311
+ self?.applyPolylineTexture(image: image, to: renderer)
312
+ }
313
+ }.resume()
314
+ } else if url.hasPrefix("file://") {
315
+ // 本地文件
316
+ let path = String(url.dropFirst(7))
317
+ if let image = UIImage(contentsOfFile: path) {
318
+ applyPolylineTexture(image: image, to: renderer)
319
+ }
320
+ } else {
321
+ // 资源文件
322
+ if let image = UIImage(named: url) {
323
+ applyPolylineTexture(image: image, to: renderer)
324
+ }
325
+ }
326
+ }
327
+
328
+ /**
329
+ * 应用纹理到折线渲染器
330
+ * @param image 纹理图片
331
+ * @param renderer 折线渲染器
332
+ */
333
+ private func applyPolylineTexture(image: UIImage, to renderer: MAPolylineRenderer) {
334
+ renderer.strokeImage = image
335
+ }
336
+
337
+ /**
338
+ * 清除所有覆盖物和标记点
339
+ */
198
340
  func clear() {
199
341
  guard let mapView = mapView else { return }
200
342
  for overlay in overlays.values {
@@ -207,4 +349,4 @@ class OverlayManager {
207
349
  overlayStyles.removeAll()
208
350
  annotations.removeAll()
209
351
  }
210
- }
352
+ }
@@ -1,49 +1,100 @@
1
1
  import MAMapKit
2
2
 
3
+ /**
4
+ * UI 和手势管理器
5
+ *
6
+ * 负责:
7
+ * - 地图类型设置
8
+ * - 控件显示控制
9
+ * - 手势交互控制
10
+ * - 图层显示管理
11
+ * - 用户位置样式配置
12
+ */
3
13
  class UIManager {
14
+ /// 弱引用地图视图,避免循环引用
4
15
  private weak var mapView: MAMapView?
5
16
 
6
17
  init(mapView: MAMapView) {
7
18
  self.mapView = mapView
8
19
  }
9
20
 
21
+ // MARK: - 地图类型
22
+
23
+ /**
24
+ * 设置地图类型
25
+ * @param type 0:标准 1:卫星 2:夜间 3:导航
26
+ */
10
27
  func setMapType(_ type: Int) {
11
28
  guard let mapView = mapView else { return }
12
29
  switch type {
13
30
  case 1: mapView.mapType = .satellite
14
31
  case 2: mapView.mapType = .standardNight
32
+ case 3: mapView.mapType = .navi
15
33
  default: mapView.mapType = .standard
16
34
  }
17
35
  }
18
36
 
37
+ // MARK: - 控件显示
38
+
39
+ /**
40
+ * 设置是否显示缩放控件
41
+ * iOS 高德地图不支持缩放控件
42
+ */
19
43
  func setShowsZoomControls(_ show: Bool) {
20
- // iOS 高德地图不支持缩放控件
44
+ // iOS 不支持
21
45
  }
22
46
 
47
+ /**
48
+ * 设置是否显示指南针
49
+ */
23
50
  func setShowsCompass(_ show: Bool) {
24
51
  mapView?.showsCompass = show
25
52
  }
26
53
 
54
+ /**
55
+ * 设置是否显示比例尺
56
+ */
27
57
  func setShowsScale(_ show: Bool) {
28
58
  mapView?.showsScale = show
29
59
  }
30
60
 
61
+ // MARK: - 手势控制
62
+
63
+ /**
64
+ * 设置是否启用缩放手势
65
+ */
31
66
  func setZoomEnabled(_ enabled: Bool) {
32
67
  mapView?.isZoomEnabled = enabled
33
68
  }
34
69
 
70
+ /**
71
+ * 设置是否启用滚动手势
72
+ */
35
73
  func setScrollEnabled(_ enabled: Bool) {
36
74
  mapView?.isScrollEnabled = enabled
37
75
  }
38
76
 
77
+ /**
78
+ * 设置是否启用旋转手势
79
+ */
39
80
  func setRotateEnabled(_ enabled: Bool) {
40
81
  mapView?.isRotateEnabled = enabled
41
82
  }
42
83
 
84
+ /**
85
+ * 设置是否启用倾斜手势
86
+ */
43
87
  func setTiltEnabled(_ enabled: Bool) {
44
88
  mapView?.isRotateCameraEnabled = enabled
45
89
  }
46
90
 
91
+ // MARK: - 用户位置
92
+
93
+ /**
94
+ * 设置是否显示用户位置
95
+ * @param show 是否显示
96
+ * @param followUser 是否跟随用户
97
+ */
47
98
  func setShowsUserLocation(_ show: Bool, followUser: Bool) {
48
99
  guard let mapView = mapView else { return }
49
100
  mapView.showsUserLocation = show
@@ -54,6 +105,10 @@ class UIManager {
54
105
  }
55
106
  }
56
107
 
108
+ /**
109
+ * 设置用户位置样式
110
+ * @param config 样式配置字典
111
+ */
57
112
  func setUserLocationRepresentation(_ config: [String: Any]) {
58
113
  guard let mapView = mapView else { return }
59
114
  let representation = MAUserLocationRepresentation()
@@ -142,6 +197,12 @@ class UIManager {
142
197
  mapView.update(representation)
143
198
  }
144
199
 
200
+ /**
201
+ * 调整图片大小
202
+ * @param image 原始图片
203
+ * @param targetSize 目标大小
204
+ * @return 调整后的图片
205
+ */
145
206
  private func resizeImage(_ image: UIImage, targetSize: CGSize) -> UIImage {
146
207
  let renderer = UIGraphicsImageRenderer(size: targetSize)
147
208
  return renderer.image { _ in
@@ -149,14 +210,25 @@ class UIManager {
149
210
  }
150
211
  }
151
212
 
213
+ // MARK: - 图层显示
214
+
215
+ /**
216
+ * 设置是否显示交通路况
217
+ */
152
218
  func setShowsTraffic(_ show: Bool) {
153
219
  mapView?.isShowTraffic = show
154
220
  }
155
221
 
222
+ /**
223
+ * 设置是否显示建筑物
224
+ */
156
225
  func setShowsBuildings(_ show: Bool) {
157
226
  mapView?.isShowsBuildings = show
158
227
  }
159
228
 
229
+ /**
230
+ * 设置是否显示室内地图
231
+ */
160
232
  func setShowsIndoorMap(_ show: Bool) {
161
233
  mapView?.isShowsIndoorMap = show
162
234
  }