expo-gaode-map 0.1.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 (132) hide show
  1. package/.eslintrc.js +5 -0
  2. package/PUBLISHING.md +244 -0
  3. package/README.md +990 -0
  4. package/android/build.gradle +48 -0
  5. package/android/src/main/AndroidManifest.xml +40 -0
  6. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +455 -0
  7. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +337 -0
  8. package/android/src/main/java/expo/modules/gaodemap/managers/CameraManager.kt +128 -0
  9. package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +324 -0
  10. package/android/src/main/java/expo/modules/gaodemap/managers/UIManager.kt +122 -0
  11. package/android/src/main/java/expo/modules/gaodemap/modules/LocationManager.kt +247 -0
  12. package/android/src/main/java/expo/modules/gaodemap/modules/SDKInitializer.kt +45 -0
  13. package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +151 -0
  14. package/android/src/main/java/expo/modules/gaodemap/overlays/ClusterView.kt +127 -0
  15. package/android/src/main/java/expo/modules/gaodemap/overlays/HeatMapView.kt +97 -0
  16. package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerView.kt +204 -0
  17. package/android/src/main/java/expo/modules/gaodemap/overlays/MultiPointView.kt +103 -0
  18. package/android/src/main/java/expo/modules/gaodemap/overlays/PolygonView.kt +114 -0
  19. package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +138 -0
  20. package/build/ExpoGaodeMap.types.d.ts +24 -0
  21. package/build/ExpoGaodeMap.types.d.ts.map +1 -0
  22. package/build/ExpoGaodeMap.types.js +14 -0
  23. package/build/ExpoGaodeMap.types.js.map +1 -0
  24. package/build/ExpoGaodeMapModule.d.ts +7 -0
  25. package/build/ExpoGaodeMapModule.d.ts.map +1 -0
  26. package/build/ExpoGaodeMapModule.js +14 -0
  27. package/build/ExpoGaodeMapModule.js.map +1 -0
  28. package/build/ExpoGaodeMapView.d.ts +31 -0
  29. package/build/ExpoGaodeMapView.d.ts.map +1 -0
  30. package/build/ExpoGaodeMapView.js +141 -0
  31. package/build/ExpoGaodeMapView.js.map +1 -0
  32. package/build/components/overlays/Circle.d.ts +18 -0
  33. package/build/components/overlays/Circle.d.ts.map +1 -0
  34. package/build/components/overlays/Circle.js +63 -0
  35. package/build/components/overlays/Circle.js.map +1 -0
  36. package/build/components/overlays/Cluster.d.ts +22 -0
  37. package/build/components/overlays/Cluster.d.ts.map +1 -0
  38. package/build/components/overlays/Cluster.js +35 -0
  39. package/build/components/overlays/Cluster.js.map +1 -0
  40. package/build/components/overlays/HeatMap.d.ts +21 -0
  41. package/build/components/overlays/HeatMap.d.ts.map +1 -0
  42. package/build/components/overlays/HeatMap.js +34 -0
  43. package/build/components/overlays/HeatMap.js.map +1 -0
  44. package/build/components/overlays/Marker.d.ts +17 -0
  45. package/build/components/overlays/Marker.d.ts.map +1 -0
  46. package/build/components/overlays/Marker.js +57 -0
  47. package/build/components/overlays/Marker.js.map +1 -0
  48. package/build/components/overlays/MultiPoint.d.ts +21 -0
  49. package/build/components/overlays/MultiPoint.d.ts.map +1 -0
  50. package/build/components/overlays/MultiPoint.js +34 -0
  51. package/build/components/overlays/MultiPoint.js.map +1 -0
  52. package/build/components/overlays/Polygon.d.ts +22 -0
  53. package/build/components/overlays/Polygon.d.ts.map +1 -0
  54. package/build/components/overlays/Polygon.js +100 -0
  55. package/build/components/overlays/Polygon.js.map +1 -0
  56. package/build/components/overlays/Polyline.d.ts +20 -0
  57. package/build/components/overlays/Polyline.d.ts.map +1 -0
  58. package/build/components/overlays/Polyline.js +60 -0
  59. package/build/components/overlays/Polyline.js.map +1 -0
  60. package/build/components/overlays/index.d.ts +8 -0
  61. package/build/components/overlays/index.d.ts.map +1 -0
  62. package/build/components/overlays/index.js +18 -0
  63. package/build/components/overlays/index.js.map +1 -0
  64. package/build/index.d.ts +10 -0
  65. package/build/index.d.ts.map +1 -0
  66. package/build/index.js +28 -0
  67. package/build/index.js.map +1 -0
  68. package/build/modules/AMapLocation.d.ts +58 -0
  69. package/build/modules/AMapLocation.d.ts.map +1 -0
  70. package/build/modules/AMapLocation.js +141 -0
  71. package/build/modules/AMapLocation.js.map +1 -0
  72. package/build/modules/AMapSDK.d.ts +27 -0
  73. package/build/modules/AMapSDK.d.ts.map +1 -0
  74. package/build/modules/AMapSDK.js +43 -0
  75. package/build/modules/AMapSDK.js.map +1 -0
  76. package/build/modules/AMapView.d.ts +39 -0
  77. package/build/modules/AMapView.d.ts.map +1 -0
  78. package/build/modules/AMapView.js +61 -0
  79. package/build/modules/AMapView.js.map +1 -0
  80. package/build/types/common.types.d.ts +133 -0
  81. package/build/types/common.types.d.ts.map +1 -0
  82. package/build/types/common.types.js +31 -0
  83. package/build/types/common.types.js.map +1 -0
  84. package/build/types/index.d.ts +12 -0
  85. package/build/types/index.d.ts.map +1 -0
  86. package/build/types/index.js +17 -0
  87. package/build/types/index.js.map +1 -0
  88. package/build/types/location.types.d.ts +306 -0
  89. package/build/types/location.types.d.ts.map +1 -0
  90. package/build/types/location.types.js +93 -0
  91. package/build/types/location.types.js.map +1 -0
  92. package/build/types/map-view.types.d.ts +213 -0
  93. package/build/types/map-view.types.d.ts.map +1 -0
  94. package/build/types/map-view.types.js +6 -0
  95. package/build/types/map-view.types.js.map +1 -0
  96. package/build/types/overlays.types.d.ts +296 -0
  97. package/build/types/overlays.types.d.ts.map +1 -0
  98. package/build/types/overlays.types.js +6 -0
  99. package/build/types/overlays.types.js.map +1 -0
  100. package/build/types/sdk.types.d.ts +113 -0
  101. package/build/types/sdk.types.d.ts.map +1 -0
  102. package/build/types/sdk.types.js +6 -0
  103. package/build/types/sdk.types.js.map +1 -0
  104. package/docs/followUserLocation.md +186 -0
  105. package/expo-module.config.json +9 -0
  106. package/ios/ExpoGaodeMap.podspec +29 -0
  107. package/ios/ExpoGaodeMapModule.swift +48 -0
  108. package/ios/ExpoGaodeMapView.swift +38 -0
  109. package/package.json +45 -0
  110. package/src/ExpoGaodeMap.types.ts +68 -0
  111. package/src/ExpoGaodeMapModule.ts +21 -0
  112. package/src/ExpoGaodeMapView.tsx +151 -0
  113. package/src/components/overlays/Circle.tsx +73 -0
  114. package/src/components/overlays/Cluster.tsx +38 -0
  115. package/src/components/overlays/HeatMap.tsx +37 -0
  116. package/src/components/overlays/Marker.tsx +66 -0
  117. package/src/components/overlays/MultiPoint.tsx +37 -0
  118. package/src/components/overlays/Polygon.tsx +107 -0
  119. package/src/components/overlays/Polyline.tsx +69 -0
  120. package/src/components/overlays/index.ts +18 -0
  121. package/src/index.ts +55 -0
  122. package/src/modules/AMapLocation.ts +164 -0
  123. package/src/modules/AMapSDK.ts +48 -0
  124. package/src/modules/AMapView.ts +68 -0
  125. package/src/types/README.md +186 -0
  126. package/src/types/common.types.ts +155 -0
  127. package/src/types/index.ts +74 -0
  128. package/src/types/location.types.ts +364 -0
  129. package/src/types/map-view.types.ts +249 -0
  130. package/src/types/overlays.types.ts +346 -0
  131. package/src/types/sdk.types.ts +128 -0
  132. package/tsconfig.json +9 -0
@@ -0,0 +1,324 @@
1
+ package expo.modules.gaodemap.managers
2
+
3
+ import android.util.Log
4
+ import com.amap.api.maps.AMap
5
+ import com.amap.api.maps.model.LatLng
6
+
7
+ /**
8
+ * 覆盖物管理器
9
+ * 负责地图上所有覆盖物的添加、删除、更新
10
+ */
11
+ class OverlayManager(private val aMap: AMap) {
12
+
13
+ companion object {
14
+ private const val TAG = "OverlayManager"
15
+ }
16
+
17
+ // 覆盖物存储
18
+ private val circles = mutableMapOf<String, com.amap.api.maps.model.Circle>()
19
+ private val markers = mutableMapOf<String, com.amap.api.maps.model.Marker>()
20
+ private val polylines = mutableMapOf<String, com.amap.api.maps.model.Polyline>()
21
+ private val polygons = mutableMapOf<String, com.amap.api.maps.model.Polygon>()
22
+
23
+ // ==================== 圆形覆盖物 ====================
24
+
25
+ fun addCircle(id: String, props: Map<String, Any>) {
26
+ Log.d(TAG, "🔵 addCircle: id=$id")
27
+
28
+ @Suppress("UNCHECKED_CAST")
29
+ val center = props["center"] as? Map<String, Double>
30
+ val radius = (props["radius"] as? Number)?.toDouble() ?: 1000.0
31
+ val fillColor = (props["fillColor"] as? Number)?.toInt() ?: android.graphics.Color.argb(50, 0, 0, 255)
32
+ val strokeColor = (props["strokeColor"] as? Number)?.toInt() ?: android.graphics.Color.BLUE
33
+ val strokeWidth = (props["strokeWidth"] as? Number)?.toFloat() ?: 10f
34
+
35
+ if (center != null) {
36
+ val lat = center["latitude"] ?: 0.0
37
+ val lng = center["longitude"] ?: 0.0
38
+ val latLng = LatLng(lat, lng)
39
+
40
+ val options = com.amap.api.maps.model.CircleOptions()
41
+ .center(latLng)
42
+ .radius(radius)
43
+ .fillColor(fillColor)
44
+ .strokeColor(strokeColor)
45
+ .strokeWidth(strokeWidth)
46
+
47
+ val circle = aMap.addCircle(options)
48
+ circles[id] = circle
49
+ Log.d(TAG, "✅ 圆形创建成功")
50
+ }
51
+ }
52
+
53
+ fun removeCircle(id: String) {
54
+ circles[id]?.let { circle ->
55
+ circle.remove()
56
+ circles.remove(id)
57
+ Log.d(TAG, "✅ 圆形已移除: $id")
58
+ }
59
+ }
60
+
61
+ fun updateCircle(id: String, props: Map<String, Any>) {
62
+ circles[id]?.let { circle ->
63
+ @Suppress("UNCHECKED_CAST")
64
+ val center = props["center"] as? Map<String, Double>
65
+ val radius = (props["radius"] as? Number)?.toDouble()
66
+ val fillColor = (props["fillColor"] as? Number)?.toInt()
67
+ val strokeColor = (props["strokeColor"] as? Number)?.toInt()
68
+ val strokeWidth = (props["strokeWidth"] as? Number)?.toFloat()
69
+
70
+ center?.let {
71
+ val lat = it["latitude"] ?: 0.0
72
+ val lng = it["longitude"] ?: 0.0
73
+ circle.center = LatLng(lat, lng)
74
+ }
75
+
76
+ radius?.let { circle.radius = it }
77
+ fillColor?.let { circle.fillColor = it }
78
+ strokeColor?.let { circle.strokeColor = it }
79
+ strokeWidth?.let { circle.strokeWidth = it }
80
+
81
+ Log.d(TAG, "✅ 圆形已更新: $id")
82
+ }
83
+ }
84
+
85
+ // ==================== 标记点 ====================
86
+
87
+ fun addMarker(id: String, props: Map<String, Any>) {
88
+ Log.d(TAG, "📍 addMarker: id=$id")
89
+
90
+ @Suppress("UNCHECKED_CAST")
91
+ val position = props["position"] as? Map<String, Double>
92
+ val title = props["title"] as? String
93
+ val draggable = props["draggable"] as? Boolean ?: false
94
+
95
+ if (position != null) {
96
+ val lat = position["latitude"] ?: 0.0
97
+ val lng = position["longitude"] ?: 0.0
98
+ val latLng = LatLng(lat, lng)
99
+
100
+ val options = com.amap.api.maps.model.MarkerOptions()
101
+ .position(latLng)
102
+ .draggable(draggable)
103
+
104
+ title?.let { options.title(it) }
105
+
106
+ val marker = aMap.addMarker(options)
107
+
108
+ if (!title.isNullOrEmpty()) {
109
+ marker?.showInfoWindow()
110
+ }
111
+
112
+ markers[id] = marker
113
+ Log.d(TAG, "✅ 标记点创建成功")
114
+ }
115
+ }
116
+
117
+ fun removeMarker(id: String) {
118
+ markers[id]?.let { marker ->
119
+ marker.remove()
120
+ markers.remove(id)
121
+ Log.d(TAG, "✅ 标记点已移除: $id")
122
+ }
123
+ }
124
+
125
+ fun updateMarker(id: String, props: Map<String, Any>) {
126
+ markers[id]?.let { marker ->
127
+ @Suppress("UNCHECKED_CAST")
128
+ val position = props["position"] as? Map<String, Double>
129
+ val title = props["title"] as? String
130
+ val draggable = props["draggable"] as? Boolean
131
+
132
+ position?.let {
133
+ val lat = it["latitude"] ?: 0.0
134
+ val lng = it["longitude"] ?: 0.0
135
+ marker.position = LatLng(lat, lng)
136
+ }
137
+
138
+ title?.let { marker.title = it }
139
+ draggable?.let { marker.isDraggable = it }
140
+
141
+ Log.d(TAG, "✅ 标记点已更新: $id")
142
+ }
143
+ }
144
+
145
+ // ==================== 折线 ====================
146
+
147
+ fun addPolyline(id: String, props: Map<String, Any>) {
148
+ Log.d(TAG, "📏 addPolyline: id=$id")
149
+
150
+ @Suppress("UNCHECKED_CAST")
151
+ val points = props["points"] as? List<Map<String, Double>>
152
+ val width = (props["width"] as? Number)?.toFloat() ?: 10f
153
+
154
+ val colorValue = props["color"]
155
+ val color = when (colorValue) {
156
+ is Long -> colorValue.toInt()
157
+ is Int -> colorValue
158
+ is Double -> colorValue.toInt()
159
+ else -> android.graphics.Color.RED
160
+ }
161
+
162
+ if (points != null && points.isNotEmpty()) {
163
+ val latLngs = points.map { point ->
164
+ val lat = point["latitude"] ?: 0.0
165
+ val lng = point["longitude"] ?: 0.0
166
+ LatLng(lat, lng)
167
+ }
168
+
169
+ val options = com.amap.api.maps.model.PolylineOptions()
170
+ .addAll(latLngs)
171
+ .width(width)
172
+ .color(color)
173
+
174
+ val polyline = aMap.addPolyline(options)
175
+ polylines[id] = polyline
176
+ Log.d(TAG, "✅ 折线创建成功")
177
+ }
178
+ }
179
+
180
+ fun removePolyline(id: String) {
181
+ polylines[id]?.let { polyline ->
182
+ polyline.remove()
183
+ polylines.remove(id)
184
+ Log.d(TAG, "✅ 折线已移除: $id")
185
+ }
186
+ }
187
+
188
+ fun updatePolyline(id: String, props: Map<String, Any>) {
189
+ polylines[id]?.let { polyline ->
190
+ @Suppress("UNCHECKED_CAST")
191
+ val points = props["points"] as? List<Map<String, Double>>
192
+ val width = (props["width"] as? Number)?.toFloat()
193
+ val color = (props["color"] as? Number)?.toInt()
194
+
195
+ points?.let {
196
+ val latLngs = it.map { point ->
197
+ val lat = point["latitude"] ?: 0.0
198
+ val lng = point["longitude"] ?: 0.0
199
+ LatLng(lat, lng)
200
+ }
201
+ polyline.points = latLngs
202
+ }
203
+
204
+ width?.let { polyline.width = it }
205
+ color?.let { polyline.color = it }
206
+
207
+ Log.d(TAG, "✅ 折线已更新: $id")
208
+ }
209
+ }
210
+
211
+ // ==================== 多边形 ====================
212
+
213
+ fun addPolygon(id: String, props: Map<String, Any>) {
214
+ Log.d(TAG, "🔷 addPolygon: id=$id")
215
+
216
+ @Suppress("UNCHECKED_CAST")
217
+ val points = props["points"] as? List<Map<String, Double>>
218
+
219
+ val fillColorValue = props["fillColor"]
220
+ val fillColor = when (fillColorValue) {
221
+ is Long -> fillColorValue.toInt()
222
+ is Int -> fillColorValue
223
+ is Double -> fillColorValue.toInt()
224
+ else -> android.graphics.Color.argb(50, 0, 0, 255)
225
+ }
226
+
227
+ val strokeColorValue = props["strokeColor"]
228
+ val strokeColor = when (strokeColorValue) {
229
+ is Long -> strokeColorValue.toInt()
230
+ is Int -> strokeColorValue
231
+ is Double -> strokeColorValue.toInt()
232
+ else -> android.graphics.Color.BLUE
233
+ }
234
+
235
+ val strokeWidth = (props["strokeWidth"] as? Number)?.toFloat() ?: 10f
236
+ val zIndex = (props["zIndex"] as? Number)?.toFloat() ?: 0f
237
+
238
+ if (points != null && points.size >= 3) {
239
+ val latLngs = points.map { point ->
240
+ val lat = point["latitude"] ?: 0.0
241
+ val lng = point["longitude"] ?: 0.0
242
+ LatLng(lat, lng)
243
+ }
244
+
245
+ val options = com.amap.api.maps.model.PolygonOptions()
246
+ .addAll(latLngs)
247
+ .fillColor(fillColor)
248
+ .strokeColor(strokeColor)
249
+ .strokeWidth(strokeWidth)
250
+ .zIndex(zIndex)
251
+
252
+ val polygon = aMap.addPolygon(options)
253
+ polygons[id] = polygon
254
+ Log.d(TAG, "✅ 多边形创建成功")
255
+ }
256
+ }
257
+
258
+ fun removePolygon(id: String) {
259
+ polygons[id]?.let { polygon ->
260
+ polygon.remove()
261
+ polygons.remove(id)
262
+ Log.d(TAG, "✅ 多边形已移除: $id")
263
+ }
264
+ }
265
+
266
+ fun updatePolygon(id: String, props: Map<String, Any>) {
267
+ polygons[id]?.let { polygon ->
268
+ @Suppress("UNCHECKED_CAST")
269
+ val points = props["points"] as? List<Map<String, Double>>
270
+
271
+ val fillColorValue = props["fillColor"]
272
+ val fillColor = when (fillColorValue) {
273
+ is Long -> fillColorValue.toInt()
274
+ is Int -> fillColorValue
275
+ is Double -> fillColorValue.toInt()
276
+ else -> null
277
+ }
278
+
279
+ val strokeColorValue = props["strokeColor"]
280
+ val strokeColor = when (strokeColorValue) {
281
+ is Long -> strokeColorValue.toInt()
282
+ is Int -> strokeColorValue
283
+ is Double -> strokeColorValue.toInt()
284
+ else -> null
285
+ }
286
+
287
+ val strokeWidth = (props["strokeWidth"] as? Number)?.toFloat()
288
+ val zIndex = (props["zIndex"] as? Number)?.toFloat()
289
+
290
+ points?.let {
291
+ val latLngs = it.map { point ->
292
+ val lat = point["latitude"] ?: 0.0
293
+ val lng = point["longitude"] ?: 0.0
294
+ LatLng(lat, lng)
295
+ }
296
+ polygon.points = latLngs
297
+ }
298
+
299
+ fillColor?.let { polygon.fillColor = it }
300
+ strokeColor?.let { polygon.strokeColor = it }
301
+ strokeWidth?.let { polygon.strokeWidth = it }
302
+ zIndex?.let { polygon.zIndex = it }
303
+
304
+ Log.d(TAG, "✅ 多边形已更新: $id")
305
+ }
306
+ }
307
+
308
+ /**
309
+ * 清理所有覆盖物
310
+ */
311
+ fun clear() {
312
+ circles.values.forEach { it.remove() }
313
+ circles.clear()
314
+
315
+ markers.values.forEach { it.remove() }
316
+ markers.clear()
317
+
318
+ polylines.values.forEach { it.remove() }
319
+ polylines.clear()
320
+
321
+ polygons.values.forEach { it.remove() }
322
+ polygons.clear()
323
+ }
324
+ }
@@ -0,0 +1,122 @@
1
+ package expo.modules.gaodemap.managers
2
+
3
+ import com.amap.api.maps.AMap
4
+ import com.amap.api.maps.model.MyLocationStyle
5
+
6
+ /**
7
+ * UI 和手势管理器
8
+ * 负责地图控件显示、手势控制、图层显示等
9
+ */
10
+ class UIManager(private val aMap: AMap) {
11
+
12
+ // ==================== 控件显示 ====================
13
+
14
+ /**
15
+ * 设置是否显示缩放控件
16
+ */
17
+ fun setShowsZoomControls(show: Boolean) {
18
+ aMap.uiSettings.isZoomControlsEnabled = show
19
+ }
20
+
21
+ /**
22
+ * 设置是否显示指南针
23
+ */
24
+ fun setShowsCompass(show: Boolean) {
25
+ aMap.uiSettings.isCompassEnabled = show
26
+ }
27
+
28
+ /**
29
+ * 设置是否显示比例尺
30
+ */
31
+ fun setShowsScale(show: Boolean) {
32
+ aMap.uiSettings.isScaleControlsEnabled = show
33
+ }
34
+
35
+ // ==================== 手势控制 ====================
36
+
37
+ /**
38
+ * 设置是否启用缩放手势
39
+ */
40
+ fun setZoomEnabled(enabled: Boolean) {
41
+ aMap.uiSettings.isZoomGesturesEnabled = enabled
42
+ }
43
+
44
+ /**
45
+ * 设置是否启用滚动手势
46
+ */
47
+ fun setScrollEnabled(enabled: Boolean) {
48
+ aMap.uiSettings.isScrollGesturesEnabled = enabled
49
+ }
50
+
51
+ /**
52
+ * 设置是否启用旋转手势
53
+ */
54
+ fun setRotateEnabled(enabled: Boolean) {
55
+ aMap.uiSettings.isRotateGesturesEnabled = enabled
56
+ }
57
+
58
+ /**
59
+ * 设置是否启用倾斜手势
60
+ */
61
+ fun setTiltEnabled(enabled: Boolean) {
62
+ aMap.uiSettings.isTiltGesturesEnabled = enabled
63
+ }
64
+
65
+ // ==================== 图层显示 ====================
66
+
67
+ /**
68
+ * 设置是否显示用户位置
69
+ * @param show 是否显示
70
+ * @param followUserLocation 是否跟随用户位置(默认 false,只显示不移动地图)
71
+ */
72
+ fun setShowsUserLocation(show: Boolean, followUserLocation: Boolean = false) {
73
+ if (show) {
74
+ val myLocationStyle = MyLocationStyle()
75
+ // 根据参数选择定位类型
76
+ val locationType = if (followUserLocation) {
77
+ MyLocationStyle.LOCATION_TYPE_FOLLOW // 跟随用户位置
78
+ } else {
79
+ MyLocationStyle.LOCATION_TYPE_SHOW // 只显示,不移动地图
80
+ }
81
+ myLocationStyle.myLocationType(locationType)
82
+ aMap.myLocationStyle = myLocationStyle
83
+ aMap.isMyLocationEnabled = true
84
+ } else {
85
+ aMap.isMyLocationEnabled = false
86
+ }
87
+ }
88
+
89
+ /**
90
+ * 设置是否显示交通路况
91
+ */
92
+ fun setShowsTraffic(show: Boolean) {
93
+ aMap.isTrafficEnabled = show
94
+ }
95
+
96
+ /**
97
+ * 设置是否显示建筑物
98
+ */
99
+ fun setShowsBuildings(show: Boolean) {
100
+ aMap.showBuildings(show)
101
+ }
102
+
103
+ /**
104
+ * 设置是否显示室内地图
105
+ */
106
+ fun setShowsIndoorMap(show: Boolean) {
107
+ aMap.showIndoorMap(show)
108
+ }
109
+
110
+ /**
111
+ * 设置地图类型
112
+ */
113
+ fun setMapType(type: Int) {
114
+ aMap.mapType = when (type) {
115
+ 1 -> AMap.MAP_TYPE_SATELLITE // 卫星地图
116
+ 2 -> AMap.MAP_TYPE_NIGHT // 夜间地图
117
+ 3 -> AMap.MAP_TYPE_NAVI // 导航地图
118
+ 4 -> AMap.MAP_TYPE_BUS // 公交地图
119
+ else -> AMap.MAP_TYPE_NORMAL // 标准地图
120
+ }
121
+ }
122
+ }
@@ -0,0 +1,247 @@
1
+ package expo.modules.gaodemap.modules
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import com.amap.api.location.AMapLocation
6
+ import com.amap.api.location.AMapLocationClient
7
+ import com.amap.api.location.AMapLocationClientOption
8
+ import com.amap.api.maps.model.LatLng
9
+ import expo.modules.kotlin.Promise
10
+
11
+ /**
12
+ * 定位管理器
13
+ */
14
+ class LocationManager(private val context: Context) {
15
+ companion object {
16
+ private const val TAG = "LocationManager"
17
+ }
18
+
19
+ private var locationClient: AMapLocationClient? = null
20
+ private var locationOption: AMapLocationClientOption? = null
21
+ private var isLocationStarted = false
22
+ private var onLocationUpdate: ((Map<String, Any?>) -> Unit)? = null
23
+
24
+ init {
25
+ initLocationClient()
26
+ }
27
+
28
+ /**
29
+ * 设置定位更新回调
30
+ */
31
+ fun setOnLocationUpdate(callback: (Map<String, Any?>) -> Unit) {
32
+ onLocationUpdate = callback
33
+ }
34
+
35
+ /**
36
+ * 开始连续定位
37
+ */
38
+ fun start() {
39
+ if (locationClient == null) {
40
+ initLocationClient()
41
+ }
42
+ locationClient?.startLocation()
43
+ isLocationStarted = true
44
+ }
45
+
46
+ /**
47
+ * 停止定位
48
+ */
49
+ fun stop() {
50
+ locationClient?.stopLocation()
51
+ isLocationStarted = false
52
+ }
53
+
54
+ /**
55
+ * 是否正在定位
56
+ */
57
+ fun isStarted(): Boolean = isLocationStarted
58
+
59
+ /**
60
+ * 获取当前位置(单次定位)
61
+ */
62
+ fun getCurrentLocation(promise: Promise) {
63
+ val onceOption = AMapLocationClientOption().apply {
64
+ isOnceLocation = true
65
+ locationOption?.let { opt ->
66
+ locationMode = opt.locationMode
67
+ isNeedAddress = opt.isNeedAddress
68
+ httpTimeOut = opt.httpTimeOut
69
+ }
70
+ }
71
+
72
+ val tempClient = AMapLocationClient(context)
73
+ tempClient.setLocationOption(onceOption)
74
+ tempClient.setLocationListener { location ->
75
+ if (location != null && location.errorCode == 0) {
76
+ promise.resolve(formatLocation(location))
77
+ } else {
78
+ promise.reject("LOCATION_ERROR", location?.errorInfo ?: "定位失败", null)
79
+ }
80
+ tempClient.stopLocation()
81
+ tempClient.onDestroy()
82
+ }
83
+ tempClient.startLocation()
84
+ }
85
+
86
+ /**
87
+ * 坐标转换
88
+ */
89
+ fun coordinateConvert(
90
+ coordinate: Map<String, Double>,
91
+ type: Int,
92
+ promise: Promise
93
+ ) {
94
+ val lat = coordinate["latitude"] ?: 0.0
95
+ val lng = coordinate["longitude"] ?: 0.0
96
+
97
+ try {
98
+ val sourceLatLng = LatLng(lat, lng)
99
+ // 高德 SDK 会自动处理坐标转换
100
+ promise.resolve(
101
+ mapOf(
102
+ "latitude" to sourceLatLng.latitude,
103
+ "longitude" to sourceLatLng.longitude
104
+ )
105
+ )
106
+ } catch (e: Exception) {
107
+ promise.reject("CONVERT_ERROR", "坐标转换失败: ${e.message}", e)
108
+ }
109
+ }
110
+
111
+ // ==================== 配置方法 ====================
112
+
113
+ fun setLocatingWithReGeocode(isReGeocode: Boolean) {
114
+ getOrCreateLocationOption().isNeedAddress = isReGeocode
115
+ applyLocationOption()
116
+ }
117
+
118
+ fun setLocationMode(mode: Int) {
119
+ val locationMode = when (mode) {
120
+ 1 -> AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
121
+ 2 -> AMapLocationClientOption.AMapLocationMode.Battery_Saving
122
+ 3 -> AMapLocationClientOption.AMapLocationMode.Device_Sensors
123
+ else -> AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
124
+ }
125
+ getOrCreateLocationOption().locationMode = locationMode
126
+ applyLocationOption()
127
+ }
128
+
129
+ fun setInterval(interval: Int) {
130
+ getOrCreateLocationOption().interval = interval.toLong()
131
+ applyLocationOption()
132
+ }
133
+
134
+ fun setOnceLocation(isOnceLocation: Boolean) {
135
+ getOrCreateLocationOption().isOnceLocation = isOnceLocation
136
+ applyLocationOption()
137
+ }
138
+
139
+ fun setSensorEnable(sensorEnable: Boolean) {
140
+ getOrCreateLocationOption().isSensorEnable = sensorEnable
141
+ applyLocationOption()
142
+ }
143
+
144
+ fun setWifiScan(wifiScan: Boolean) {
145
+ getOrCreateLocationOption().isWifiScan = wifiScan
146
+ applyLocationOption()
147
+ }
148
+
149
+ fun setGpsFirst(gpsFirst: Boolean) {
150
+ getOrCreateLocationOption().isGpsFirst = gpsFirst
151
+ applyLocationOption()
152
+ }
153
+
154
+ fun setOnceLocationLatest(onceLocationLatest: Boolean) {
155
+ getOrCreateLocationOption().isOnceLocationLatest = onceLocationLatest
156
+ applyLocationOption()
157
+ }
158
+
159
+ fun setGeoLanguage(language: String) {
160
+ val geoLanguage = when (language) {
161
+ "EN" -> AMapLocationClientOption.GeoLanguage.EN
162
+ "ZH" -> AMapLocationClientOption.GeoLanguage.ZH
163
+ else -> AMapLocationClientOption.GeoLanguage.DEFAULT
164
+ }
165
+ getOrCreateLocationOption().geoLanguage = geoLanguage
166
+ applyLocationOption()
167
+ }
168
+
169
+ fun setLocationCacheEnable(locationCacheEnable: Boolean) {
170
+ getOrCreateLocationOption().isLocationCacheEnable = locationCacheEnable
171
+ applyLocationOption()
172
+ }
173
+
174
+ fun setHttpTimeOut(httpTimeOut: Int) {
175
+ getOrCreateLocationOption().httpTimeOut = httpTimeOut.toLong()
176
+ applyLocationOption()
177
+ }
178
+
179
+ /**
180
+ * 销毁资源
181
+ */
182
+ fun destroy() {
183
+ locationClient?.stopLocation()
184
+ locationClient?.onDestroy()
185
+ locationClient = null
186
+ locationOption = null
187
+ }
188
+
189
+ // ==================== 私有方法 ====================
190
+
191
+ private fun initLocationClient() {
192
+ if (locationClient == null) {
193
+ locationClient = AMapLocationClient(context).apply {
194
+ setLocationListener { location ->
195
+ if (location != null && location.errorCode == 0) {
196
+ onLocationUpdate?.invoke(formatLocation(location))
197
+ }
198
+ }
199
+ }
200
+
201
+ locationOption = AMapLocationClientOption().apply {
202
+ locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
203
+ isNeedAddress = true
204
+ interval = 2000
205
+ httpTimeOut = 30000
206
+ }
207
+ locationClient?.setLocationOption(locationOption)
208
+ }
209
+ }
210
+
211
+ private fun getOrCreateLocationOption(): AMapLocationClientOption {
212
+ if (locationOption == null) {
213
+ locationOption = AMapLocationClientOption()
214
+ }
215
+ return locationOption!!
216
+ }
217
+
218
+ private fun applyLocationOption() {
219
+ locationClient?.setLocationOption(locationOption)
220
+ }
221
+
222
+ private fun formatLocation(location: AMapLocation): Map<String, Any?> {
223
+ return mapOf(
224
+ "latitude" to location.latitude,
225
+ "longitude" to location.longitude,
226
+ "altitude" to location.altitude,
227
+ "accuracy" to location.accuracy,
228
+ "heading" to location.bearing,
229
+ "speed" to location.speed,
230
+ "timestamp" to location.time,
231
+ "address" to location.address,
232
+ "country" to location.country,
233
+ "province" to location.province,
234
+ "city" to location.city,
235
+ "district" to location.district,
236
+ "cityCode" to location.cityCode,
237
+ "adCode" to location.adCode,
238
+ "street" to location.street,
239
+ "streetNumber" to location.streetNum,
240
+ "poiName" to location.poiName,
241
+ "aoiName" to location.aoiName,
242
+ "description" to location.locationDetail,
243
+ "coordType" to location.coordType,
244
+ "buildingId" to location.buildingId
245
+ )
246
+ }
247
+ }