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
@@ -14,6 +14,15 @@ import expo.modules.gaodemap.managers.UIManager
14
14
  import expo.modules.gaodemap.managers.OverlayManager
15
15
  import expo.modules.gaodemap.overlays.*
16
16
 
17
+ /**
18
+ * 高德地图视图组件
19
+ *
20
+ * 负责:
21
+ * - 地图视图的创建和管理
22
+ * - 地图事件的派发
23
+ * - 相机控制和覆盖物管理
24
+ * - 生命周期管理
25
+ */
17
26
  @Suppress("ViewConstructor")
18
27
  class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
19
28
 
@@ -22,11 +31,14 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
22
31
  }
23
32
 
24
33
  // Props 存储
34
+ /** 地图类型 */
25
35
  internal var mapType: Int = 0
36
+ /** 初始相机位置 */
26
37
  internal var initialCameraPosition: Map<String, Any?>? = null
38
+ /** 是否跟随用户位置 */
27
39
  internal var followUserLocation: Boolean = false
28
40
 
29
- // Handler for posting to main thread
41
+ /** 主线程 Handler */
30
42
  private val mainHandler = android.os.Handler(android.os.Looper.getMainLooper())
31
43
 
32
44
  // 事件派发器
@@ -48,56 +60,44 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
48
60
  private var isMapLoaded = false
49
61
 
50
62
  init {
51
- Log.d(TAG, "ExpoGaodeMapView 初始化开始")
52
-
53
63
  try {
54
64
  // 确保隐私合规已设置
55
65
  MapsInitializer.updatePrivacyShow(context, true, true)
56
66
  MapsInitializer.updatePrivacyAgree(context, true)
57
- Log.d(TAG, "地图隐私合规已确认")
58
67
 
59
68
  // 创建地图视图
60
69
  mapView = MapView(context)
61
70
  mapView.onCreate(null)
62
71
  aMap = mapView.map
63
- Log.d(TAG, "MapView 创建成功")
64
72
 
65
73
  // 初始化管理器
66
74
  cameraManager = CameraManager(aMap)
67
75
  uiManager = UIManager(aMap, context)
68
76
  overlayManager = OverlayManager(aMap)
69
- Log.d(TAG, "管理器初始化完成")
70
77
 
71
78
  // 添加地图视图到布局
72
79
  addView(mapView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
73
- Log.d(TAG, "MapView 已添加到布局")
74
80
 
75
81
  // 设置地图事件监听
76
82
  setupMapListeners()
77
- Log.d(TAG, "地图事件监听已设置")
78
83
 
79
84
  // 地图加载完成回调
80
85
  aMap.setOnMapLoadedListener {
81
- Log.d(TAG, "🎉 地图加载完成")
82
86
  isMapLoaded = true
83
87
 
84
88
  // 应用缓存的 Props
85
89
  if (mapType != 0) {
86
- Log.d(TAG, "应用 mapType: $mapType")
87
90
  setMapType(mapType)
88
91
  }
89
92
 
90
93
  val positionToApply = initialCameraPosition ?: pendingCameraPosition
91
94
  positionToApply?.let { position ->
92
- Log.d(TAG, "应用初始相机位置")
93
95
  applyInitialCameraPosition(position)
94
96
  pendingCameraPosition = null
95
97
  }
96
98
 
97
99
  onLoad(mapOf("loaded" to true))
98
100
  }
99
-
100
- Log.d(TAG, "ExpoGaodeMapView 初始化完成")
101
101
  } catch (e: Exception) {
102
102
  Log.e(TAG, "ExpoGaodeMapView 初始化失败", e)
103
103
  }
@@ -126,166 +126,217 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
126
126
 
127
127
  /**
128
128
  * 设置地图类型
129
+ * @param type 地图类型
129
130
  */
130
131
  fun setMapType(type: Int) {
131
- Log.d(TAG, "🎯 setMapType: $type")
132
132
  mainHandler.post {
133
133
  uiManager.setMapType(type)
134
- Log.d(TAG, "✅ setMapType 完成")
135
134
  }
136
135
  }
137
136
 
138
137
  /**
139
138
  * 设置初始相机位置
139
+ * @param position 相机位置配置
140
140
  */
141
141
  fun setInitialCameraPosition(position: Map<String, Any?>) {
142
- Log.d(TAG, "🎯 setInitialCameraPosition")
143
- mainHandler.post {
144
- applyInitialCameraPosition(position)
142
+ initialCameraPosition = position
143
+
144
+ // 如果地图已加载,立即应用;否则缓存等待地图加载完成
145
+ if (isMapLoaded) {
146
+ mainHandler.post {
147
+ applyInitialCameraPosition(position)
148
+ }
149
+ } else {
150
+ pendingCameraPosition = position
145
151
  }
146
152
  }
147
153
 
148
154
  /**
149
155
  * 实际应用相机位置
156
+ * @param position 相机位置配置
150
157
  */
151
158
  private fun applyInitialCameraPosition(position: Map<String, Any?>) {
152
159
  cameraManager.setInitialCameraPosition(position)
153
- Log.d(TAG, "相机位置设置完成")
154
160
  }
155
161
 
156
162
  // ==================== UI 控件和手势 ====================
157
163
 
164
+ /** 设置是否显示缩放控件 */
158
165
  fun setShowsZoomControls(show: Boolean) = uiManager.setShowsZoomControls(show)
166
+ /** 设置是否显示指南针 */
159
167
  fun setShowsCompass(show: Boolean) = uiManager.setShowsCompass(show)
168
+ /** 设置是否显示比例尺 */
160
169
  fun setShowsScale(show: Boolean) = uiManager.setShowsScale(show)
161
170
 
171
+ /** 设置是否启用缩放手势 */
162
172
  fun setZoomEnabled(enabled: Boolean) = uiManager.setZoomEnabled(enabled)
173
+ /** 设置是否启用滚动手势 */
163
174
  fun setScrollEnabled(enabled: Boolean) = uiManager.setScrollEnabled(enabled)
175
+ /** 设置是否启用旋转手势 */
164
176
  fun setRotateEnabled(enabled: Boolean) = uiManager.setRotateEnabled(enabled)
177
+ /** 设置是否启用倾斜手势 */
165
178
  fun setTiltEnabled(enabled: Boolean) = uiManager.setTiltEnabled(enabled)
166
179
 
180
+ /** 设置最大缩放级别 */
167
181
  fun setMaxZoom(maxZoom: Float) = cameraManager.setMaxZoomLevel(maxZoom)
182
+ /** 设置最小缩放级别 */
168
183
  fun setMinZoom(minZoom: Float) = cameraManager.setMinZoomLevel(minZoom)
169
184
 
185
+ /** 设置是否显示用户位置 */
170
186
  fun setShowsUserLocation(show: Boolean) = uiManager.setShowsUserLocation(show, followUserLocation)
171
187
 
188
+ /**
189
+ * 设置是否跟随用户位置
190
+ * @param follow 是否跟随
191
+ */
172
192
  fun setFollowUserLocation(follow: Boolean) {
173
193
  followUserLocation = follow
174
194
  // 如果定位已开启,立即应用新设置
175
195
  uiManager.setShowsUserLocation(true, follow)
176
196
  }
177
197
 
198
+ /**
199
+ * 设置用户位置样式
200
+ * @param representation 样式配置
201
+ */
178
202
  fun setUserLocationRepresentation(representation: Map<String, Any>) {
179
203
  uiManager.setUserLocationRepresentation(representation)
180
204
  }
181
205
 
206
+ /** 设置是否显示交通路况 */
182
207
  fun setShowsTraffic(show: Boolean) = uiManager.setShowsTraffic(show)
208
+ /** 设置是否显示建筑物 */
183
209
  fun setShowsBuildings(show: Boolean) = uiManager.setShowsBuildings(show)
210
+ /** 设置是否显示室内地图 */
184
211
  fun setShowsIndoorMap(show: Boolean) = uiManager.setShowsIndoorMap(show)
185
212
 
186
213
  // ==================== 相机控制方法 ====================
187
214
 
215
+ /**
216
+ * 移动相机
217
+ * @param position 目标位置
218
+ * @param duration 动画时长(毫秒)
219
+ */
188
220
  fun moveCamera(position: Map<String, Any>, duration: Int) {
189
221
  cameraManager.moveCamera(position, duration)
190
222
  }
191
223
 
224
+ /**
225
+ * 获取屏幕坐标对应的地理坐标
226
+ * @param point 屏幕坐标
227
+ * @return 地理坐标
228
+ */
192
229
  fun getLatLng(point: Map<String, Double>): Map<String, Double> {
193
230
  return cameraManager.getLatLng(point)
194
231
  }
195
232
 
233
+ /**
234
+ * 设置地图中心点
235
+ * @param center 中心点坐标
236
+ * @param animated 是否动画
237
+ */
196
238
  fun setCenter(center: Map<String, Double>, animated: Boolean) {
197
239
  cameraManager.setCenter(center, animated)
198
240
  }
199
241
 
242
+ /**
243
+ * 设置地图缩放级别
244
+ * @param zoom 缩放级别
245
+ * @param animated 是否动画
246
+ */
200
247
  fun setZoomLevel(zoom: Float, animated: Boolean) {
201
248
  cameraManager.setZoomLevel(zoom, animated)
202
249
  }
203
250
 
251
+ /**
252
+ * 获取当前相机位置
253
+ * @return 相机位置信息
254
+ */
204
255
  fun getCameraPosition(): Map<String, Any> {
205
256
  return cameraManager.getCameraPosition()
206
257
  }
207
258
 
208
259
  // ==================== 覆盖物管理 ====================
209
260
 
261
+ /** 添加圆形覆盖物 */
210
262
  fun addCircle(id: String, props: Map<String, Any>) {
211
- Log.d(TAG, "🔵 addCircle: id=$id")
212
263
  mainHandler.post {
213
264
  overlayManager.addCircle(id, props)
214
265
  }
215
266
  }
216
267
 
268
+ /** 移除圆形覆盖物 */
217
269
  fun removeCircle(id: String) {
218
- Log.d(TAG, "🔴 removeCircle: id=$id")
219
270
  mainHandler.post {
220
271
  overlayManager.removeCircle(id)
221
272
  }
222
273
  }
223
274
 
275
+ /** 更新圆形覆盖物 */
224
276
  fun updateCircle(id: String, props: Map<String, Any>) {
225
- Log.d(TAG, "🔄 updateCircle: id=$id")
226
277
  mainHandler.post {
227
278
  overlayManager.updateCircle(id, props)
228
279
  }
229
280
  }
230
281
 
282
+ /** 添加标记点 */
231
283
  fun addMarker(id: String, props: Map<String, Any>) {
232
- Log.d(TAG, "📍 addMarker: id=$id")
233
284
  mainHandler.post {
234
285
  overlayManager.addMarker(id, props)
235
286
  }
236
287
  }
237
288
 
289
+ /** 移除标记点 */
238
290
  fun removeMarker(id: String) {
239
- Log.d(TAG, "🗑️ removeMarker: id=$id")
240
291
  mainHandler.post {
241
292
  overlayManager.removeMarker(id)
242
293
  }
243
294
  }
244
295
 
296
+ /** 更新标记点 */
245
297
  fun updateMarker(id: String, props: Map<String, Any>) {
246
- Log.d(TAG, "🔄 updateMarker: id=$id")
247
298
  mainHandler.post {
248
299
  overlayManager.updateMarker(id, props)
249
300
  }
250
301
  }
251
302
 
303
+ /** 添加折线 */
252
304
  fun addPolyline(id: String, props: Map<String, Any>) {
253
- Log.d(TAG, "📏 addPolyline: id=$id")
254
305
  mainHandler.post {
255
306
  overlayManager.addPolyline(id, props)
256
307
  }
257
308
  }
258
309
 
310
+ /** 移除折线 */
259
311
  fun removePolyline(id: String) {
260
- Log.d(TAG, "🗑️ removePolyline: id=$id")
261
312
  mainHandler.post {
262
313
  overlayManager.removePolyline(id)
263
314
  }
264
315
  }
265
316
 
317
+ /** 更新折线 */
266
318
  fun updatePolyline(id: String, props: Map<String, Any>) {
267
- Log.d(TAG, "🔄 updatePolyline: id=$id")
268
319
  mainHandler.post {
269
320
  overlayManager.updatePolyline(id, props)
270
321
  }
271
322
  }
272
323
 
324
+ /** 添加多边形 */
273
325
  fun addPolygon(id: String, props: Map<String, Any>) {
274
- Log.d(TAG, "🔷 addPolygon: id=$id")
275
326
  mainHandler.post {
276
327
  overlayManager.addPolygon(id, props)
277
328
  }
278
329
  }
279
330
 
331
+ /** 移除多边形 */
280
332
  fun removePolygon(id: String) {
281
- Log.d(TAG, "🗑️ removePolygon: id=$id")
282
333
  mainHandler.post {
283
334
  overlayManager.removePolygon(id)
284
335
  }
285
336
  }
286
337
 
338
+ /** 更新多边形 */
287
339
  fun updatePolygon(id: String, props: Map<String, Any>) {
288
- Log.d(TAG, "🔄 updatePolygon: id=$id")
289
340
  mainHandler.post {
290
341
  overlayManager.updatePolygon(id, props)
291
342
  }
@@ -293,22 +344,37 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
293
344
 
294
345
  // ==================== 生命周期方法 ====================
295
346
 
347
+ /** 恢复地图 */
296
348
  @Suppress("unused")
297
349
  fun onResume() {
298
350
  mapView.onResume()
299
351
  }
300
352
 
353
+ /** 暂停地图 */
301
354
  @Suppress("unused")
302
355
  fun onPause() {
303
356
  mapView.onPause()
304
357
  }
305
358
 
359
+ /** 销毁地图 */
306
360
  @Suppress("unused")
307
361
  fun onDestroy() {
362
+ // 清理 Handler 回调,防止内存泄露
363
+ mainHandler.removeCallbacksAndMessages(null)
364
+
365
+ // 清理地图监听器
366
+ aMap.setOnMapClickListener(null)
367
+ aMap.setOnMapLongClickListener(null)
368
+ aMap.setOnMapLoadedListener(null)
369
+
370
+ // 清理覆盖物
308
371
  overlayManager.clear()
372
+
373
+ // 销毁地图
309
374
  mapView.onDestroy()
310
375
  }
311
376
 
377
+ /** 保存实例状态 */
312
378
  @Suppress("unused")
313
379
  fun onSaveInstanceState(outState: android.os.Bundle) {
314
380
  mapView.onSaveInstanceState(outState)
@@ -318,7 +384,6 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
318
384
  * 添加子视图时自动连接到地图
319
385
  */
320
386
  override fun addView(child: View?, index: Int) {
321
- Log.d(TAG, "addView - child: ${child?.javaClass?.simpleName}")
322
387
  super.addView(child, index)
323
388
 
324
389
  // 自动将地图实例传递给覆盖物子视图
@@ -331,15 +396,11 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
331
396
  is HeatMapView -> it.setMap(aMap)
332
397
  is MultiPointView -> it.setMap(aMap)
333
398
  is ClusterView -> it.setMap(aMap)
334
- else -> Log.d(TAG, "未识别的子视图类型: ${it.javaClass.name}")
335
399
  }
336
400
  }
337
401
  }
338
402
 
339
403
  override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
340
404
  super.onLayout(changed, left, top, right, bottom)
341
- if (changed) {
342
- Log.d(TAG, "onLayout - bounds: ($left,$top,$right,$bottom)")
343
- }
344
405
  }
345
406
  }
@@ -1,6 +1,8 @@
1
1
  package expo.modules.gaodemap.managers
2
2
 
3
3
  import android.graphics.Point
4
+ import android.os.Handler
5
+ import android.os.Looper
4
6
  import com.amap.api.maps.AMap
5
7
  import com.amap.api.maps.CameraUpdateFactory
6
8
  import com.amap.api.maps.model.CameraPosition
@@ -12,6 +14,8 @@ import com.amap.api.maps.model.LatLng
12
14
  */
13
15
  class CameraManager(private val aMap: AMap) {
14
16
 
17
+ private val mainHandler = Handler(Looper.getMainLooper())
18
+
15
19
  /**
16
20
  * 设置最大缩放级别
17
21
  */
@@ -56,28 +60,30 @@ class CameraManager(private val aMap: AMap) {
56
60
  * 移动相机
57
61
  */
58
62
  fun moveCamera(position: Map<String, Any>, duration: Int) {
59
- @Suppress("UNCHECKED_CAST")
60
- val target = position["target"] as? Map<String, Double>
61
- val zoom = (position["zoom"] as? Number)?.toFloat()
62
- val tilt = (position["tilt"] as? Number)?.toFloat()
63
- val bearing = (position["bearing"] as? Number)?.toFloat()
64
-
65
- if (target != null) {
66
- val lat = target["latitude"] ?: 0.0
67
- val lng = target["longitude"] ?: 0.0
68
- val latLng = LatLng(lat, lng)
69
-
70
- val builder = CameraPosition.Builder().target(latLng)
71
- zoom?.let { builder.zoom(it) }
72
- tilt?.let { builder.tilt(it) }
73
- bearing?.let { builder.bearing(it) }
74
-
75
- val cameraUpdate = CameraUpdateFactory.newCameraPosition(builder.build())
63
+ mainHandler.post {
64
+ @Suppress("UNCHECKED_CAST")
65
+ val target = position["target"] as? Map<String, Double>
66
+ val zoom = (position["zoom"] as? Number)?.toFloat()
67
+ val tilt = (position["tilt"] as? Number)?.toFloat()
68
+ val bearing = (position["bearing"] as? Number)?.toFloat()
76
69
 
77
- if (duration > 0) {
78
- aMap.animateCamera(cameraUpdate, duration.toLong(), null)
79
- } else {
80
- aMap.moveCamera(cameraUpdate)
70
+ if (target != null) {
71
+ val lat = target["latitude"] ?: 0.0
72
+ val lng = target["longitude"] ?: 0.0
73
+ val latLng = LatLng(lat, lng)
74
+
75
+ val builder = CameraPosition.Builder().target(latLng)
76
+ zoom?.let { builder.zoom(it) }
77
+ tilt?.let { builder.tilt(it) }
78
+ bearing?.let { builder.bearing(it) }
79
+
80
+ val cameraUpdate = CameraUpdateFactory.newCameraPosition(builder.build())
81
+
82
+ if (duration > 0) {
83
+ aMap.animateCamera(cameraUpdate, duration.toLong(), null)
84
+ } else {
85
+ aMap.moveCamera(cameraUpdate)
86
+ }
81
87
  }
82
88
  }
83
89
  }
@@ -1,9 +1,12 @@
1
1
  package expo.modules.gaodemap.managers
2
2
 
3
3
  import android.util.Log
4
+ import android.graphics.BitmapFactory
4
5
  import com.amap.api.maps.AMap
5
6
  import com.amap.api.maps.model.LatLng
7
+ import com.amap.api.maps.model.BitmapDescriptorFactory
6
8
  import expo.modules.gaodemap.utils.ColorParser
9
+ import java.net.URL
7
10
 
8
11
  /**
9
12
  * 覆盖物管理器
@@ -24,7 +27,6 @@ class OverlayManager(private val aMap: AMap) {
24
27
  // ==================== 圆形覆盖物 ====================
25
28
 
26
29
  fun addCircle(id: String, props: Map<String, Any>) {
27
- Log.d(TAG, "🔵 addCircle: id=$id")
28
30
 
29
31
  @Suppress("UNCHECKED_CAST")
30
32
  val center = props["center"] as? Map<String, Double>
@@ -47,7 +49,6 @@ class OverlayManager(private val aMap: AMap) {
47
49
 
48
50
  val circle = aMap.addCircle(options)
49
51
  circles[id] = circle
50
- Log.d(TAG, "✅ 圆形创建成功")
51
52
  }
52
53
  }
53
54
 
@@ -55,7 +56,6 @@ class OverlayManager(private val aMap: AMap) {
55
56
  circles[id]?.let { circle ->
56
57
  circle.remove()
57
58
  circles.remove(id)
58
- Log.d(TAG, "✅ 圆形已移除: $id")
59
59
  }
60
60
  }
61
61
 
@@ -78,15 +78,12 @@ class OverlayManager(private val aMap: AMap) {
78
78
  fillColor?.let { circle.fillColor = it }
79
79
  strokeColor?.let { circle.strokeColor = it }
80
80
  strokeWidth?.let { circle.strokeWidth = it }
81
-
82
- Log.d(TAG, "✅ 圆形已更新: $id")
83
81
  }
84
82
  }
85
83
 
86
84
  // ==================== 标记点 ====================
87
85
 
88
86
  fun addMarker(id: String, props: Map<String, Any>) {
89
- Log.d(TAG, "📍 addMarker: id=$id")
90
87
 
91
88
  @Suppress("UNCHECKED_CAST")
92
89
  val position = props["position"] as? Map<String, Double>
@@ -111,7 +108,6 @@ class OverlayManager(private val aMap: AMap) {
111
108
  }
112
109
 
113
110
  markers[id] = marker
114
- Log.d(TAG, "✅ 标记点创建成功")
115
111
  }
116
112
  }
117
113
 
@@ -119,7 +115,6 @@ class OverlayManager(private val aMap: AMap) {
119
115
  markers[id]?.let { marker ->
120
116
  marker.remove()
121
117
  markers.remove(id)
122
- Log.d(TAG, "✅ 标记点已移除: $id")
123
118
  }
124
119
  }
125
120
 
@@ -138,22 +133,24 @@ class OverlayManager(private val aMap: AMap) {
138
133
 
139
134
  title?.let { marker.title = it }
140
135
  draggable?.let { marker.isDraggable = it }
141
-
142
- Log.d(TAG, "✅ 标记点已更新: $id")
143
136
  }
144
137
  }
145
138
 
146
139
  // ==================== 折线 ====================
147
140
 
148
141
  fun addPolyline(id: String, props: Map<String, Any>) {
149
- Log.d(TAG, "📏 addPolyline: id=$id")
150
142
 
151
143
  @Suppress("UNCHECKED_CAST")
152
144
  val points = props["points"] as? List<Map<String, Double>>
153
- val width = (props["width"] as? Number)?.toFloat() ?: 10f
154
- val color = ColorParser.parseColor(props["color"])
145
+ val width = (props["strokeWidth"] as? Number)?.toFloat() ?: 10f
146
+ val texture = props["texture"] as? String
147
+ val color = if (!texture.isNullOrEmpty()) {
148
+ android.graphics.Color.TRANSPARENT
149
+ } else {
150
+ ColorParser.parseColor(props["strokeColor"])
151
+ }
155
152
 
156
- if (points != null && points.isNotEmpty()) {
153
+ if (points != null && points.size >= 2) {
157
154
  val latLngs = points.map { point ->
158
155
  val lat = point["latitude"] ?: 0.0
159
156
  val lng = point["longitude"] ?: 0.0
@@ -166,8 +163,31 @@ class OverlayManager(private val aMap: AMap) {
166
163
  .color(color)
167
164
 
168
165
  val polyline = aMap.addPolyline(options)
166
+
167
+ // 处理纹理
168
+ if (!texture.isNullOrEmpty()) {
169
+ Thread {
170
+ try {
171
+ val bitmap = if (texture.startsWith("http://") || texture.startsWith("https://")) {
172
+ BitmapFactory.decodeStream(URL(texture).openStream())
173
+ } else if (texture.startsWith("file://")) {
174
+ BitmapFactory.decodeFile(texture.substring(7))
175
+ } else {
176
+ null
177
+ }
178
+
179
+ bitmap?.let {
180
+ val descriptor = BitmapDescriptorFactory.fromBitmap(it)
181
+ polyline.setCustomTexture(descriptor)
182
+ Log.d(TAG, "✅ 纹理设置成功")
183
+ }
184
+ } catch (e: Exception) {
185
+ Log.e(TAG, "纹理加载失败: ${e.message}")
186
+ }
187
+ }.start()
188
+ }
189
+
169
190
  polylines[id] = polyline
170
- Log.d(TAG, "✅ 折线创建成功")
171
191
  }
172
192
  }
173
193
 
@@ -175,7 +195,6 @@ class OverlayManager(private val aMap: AMap) {
175
195
  polylines[id]?.let { polyline ->
176
196
  polyline.remove()
177
197
  polylines.remove(id)
178
- Log.d(TAG, "✅ 折线已移除: $id")
179
198
  }
180
199
  }
181
200
 
@@ -183,8 +202,8 @@ class OverlayManager(private val aMap: AMap) {
183
202
  polylines[id]?.let { polyline ->
184
203
  @Suppress("UNCHECKED_CAST")
185
204
  val points = props["points"] as? List<Map<String, Double>>
186
- val width = (props["width"] as? Number)?.toFloat()
187
- val color = props["color"]?.let { ColorParser.parseColor(it) }
205
+ val width = (props["strokeWidth"] as? Number)?.toFloat()
206
+ val color = props["strokeColor"]?.let { ColorParser.parseColor(it) }
188
207
 
189
208
  points?.let {
190
209
  val latLngs = it.map { point ->
@@ -197,15 +216,12 @@ class OverlayManager(private val aMap: AMap) {
197
216
 
198
217
  width?.let { polyline.width = it }
199
218
  color?.let { polyline.color = it }
200
-
201
- Log.d(TAG, "✅ 折线已更新: $id")
202
219
  }
203
220
  }
204
221
 
205
222
  // ==================== 多边形 ====================
206
223
 
207
224
  fun addPolygon(id: String, props: Map<String, Any>) {
208
- Log.d(TAG, "🔷 addPolygon: id=$id")
209
225
 
210
226
  @Suppress("UNCHECKED_CAST")
211
227
  val points = props["points"] as? List<Map<String, Double>>
@@ -239,7 +255,6 @@ class OverlayManager(private val aMap: AMap) {
239
255
  polygons[id]?.let { polygon ->
240
256
  polygon.remove()
241
257
  polygons.remove(id)
242
- Log.d(TAG, "✅ 多边形已移除: $id")
243
258
  }
244
259
  }
245
260
 
@@ -266,8 +281,6 @@ class OverlayManager(private val aMap: AMap) {
266
281
  strokeColor?.let { polygon.strokeColor = it }
267
282
  strokeWidth?.let { polygon.strokeWidth = it }
268
283
  zIndex?.let { polygon.zIndex = it }
269
-
270
- Log.d(TAG, "✅ 多边形已更新: $id")
271
284
  }
272
285
  }
273
286