expo-gaode-map 0.1.6 → 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.
- package/PUBLISHING.md +1 -1
- package/README.md +57 -9
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +117 -26
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +97 -36
- package/android/src/main/java/expo/modules/gaodemap/managers/CameraManager.kt +27 -21
- package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +4 -23
- package/android/src/main/java/expo/modules/gaodemap/managers/UIManager.kt +30 -27
- package/android/src/main/java/expo/modules/gaodemap/modules/LocationManager.kt +49 -4
- package/android/src/main/java/expo/modules/gaodemap/modules/SDKInitializer.kt +13 -5
- package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +0 -6
- package/build/ExpoGaodeMapView.js +2 -2
- package/build/ExpoGaodeMapView.js.map +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/modules/AMapPermissions.d.ts +27 -0
- package/build/modules/AMapPermissions.d.ts.map +1 -0
- package/build/modules/AMapPermissions.js +31 -0
- package/build/modules/AMapPermissions.js.map +1 -0
- package/build/modules/AMapView.d.ts +7 -2
- package/build/modules/AMapView.d.ts.map +1 -1
- package/build/modules/AMapView.js +15 -3
- package/build/modules/AMapView.js.map +1 -1
- package/build/types/common.types.d.ts +1 -0
- package/build/types/common.types.d.ts.map +1 -1
- package/build/types/common.types.js +1 -0
- package/build/types/common.types.js.map +1 -1
- package/docs/API.md +5 -1
- package/docs/ARCHITECTURE.md +421 -0
- package/docs/EXAMPLES.md +166 -24
- package/docs/INITIALIZATION.md +342 -0
- package/ios/ExpoGaodeMapModule.swift +95 -9
- package/ios/ExpoGaodeMapView.swift +88 -6
- package/ios/managers/CameraManager.swift +58 -0
- package/ios/managers/OverlayManager.swift +105 -29
- package/ios/managers/UIManager.swift +73 -1
- package/ios/modules/LocationManager.swift +109 -3
- package/ios/overlays/CircleView.swift +53 -0
- package/ios/overlays/HeatMapView.swift +27 -0
- package/ios/overlays/MarkerView.swift +29 -1
- package/ios/overlays/PolygonView.swift +51 -0
- package/ios/overlays/PolylineView.swift +61 -14
- package/ios/utils/PermissionManager.swift +58 -0
- package/package.json +1 -1
- package/src/ExpoGaodeMapView.tsx +2 -2
- package/src/index.ts +9 -1
- package/src/modules/AMapPermissions.ts +48 -0
- package/src/modules/AMapView.ts +15 -3
- package/src/types/common.types.ts +1 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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 (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
}
|
|
@@ -27,7 +27,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
27
27
|
// ==================== 圆形覆盖物 ====================
|
|
28
28
|
|
|
29
29
|
fun addCircle(id: String, props: Map<String, Any>) {
|
|
30
|
-
Log.d(TAG, "🔵 addCircle: id=$id")
|
|
31
30
|
|
|
32
31
|
@Suppress("UNCHECKED_CAST")
|
|
33
32
|
val center = props["center"] as? Map<String, Double>
|
|
@@ -50,7 +49,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
50
49
|
|
|
51
50
|
val circle = aMap.addCircle(options)
|
|
52
51
|
circles[id] = circle
|
|
53
|
-
Log.d(TAG, "✅ 圆形创建成功")
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
|
|
@@ -58,7 +56,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
58
56
|
circles[id]?.let { circle ->
|
|
59
57
|
circle.remove()
|
|
60
58
|
circles.remove(id)
|
|
61
|
-
Log.d(TAG, "✅ 圆形已移除: $id")
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
61
|
|
|
@@ -81,15 +78,12 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
81
78
|
fillColor?.let { circle.fillColor = it }
|
|
82
79
|
strokeColor?.let { circle.strokeColor = it }
|
|
83
80
|
strokeWidth?.let { circle.strokeWidth = it }
|
|
84
|
-
|
|
85
|
-
Log.d(TAG, "✅ 圆形已更新: $id")
|
|
86
81
|
}
|
|
87
82
|
}
|
|
88
83
|
|
|
89
84
|
// ==================== 标记点 ====================
|
|
90
85
|
|
|
91
86
|
fun addMarker(id: String, props: Map<String, Any>) {
|
|
92
|
-
Log.d(TAG, "📍 addMarker: id=$id")
|
|
93
87
|
|
|
94
88
|
@Suppress("UNCHECKED_CAST")
|
|
95
89
|
val position = props["position"] as? Map<String, Double>
|
|
@@ -114,7 +108,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
114
108
|
}
|
|
115
109
|
|
|
116
110
|
markers[id] = marker
|
|
117
|
-
Log.d(TAG, "✅ 标记点创建成功")
|
|
118
111
|
}
|
|
119
112
|
}
|
|
120
113
|
|
|
@@ -122,7 +115,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
122
115
|
markers[id]?.let { marker ->
|
|
123
116
|
marker.remove()
|
|
124
117
|
markers.remove(id)
|
|
125
|
-
Log.d(TAG, "✅ 标记点已移除: $id")
|
|
126
118
|
}
|
|
127
119
|
}
|
|
128
120
|
|
|
@@ -141,24 +133,21 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
141
133
|
|
|
142
134
|
title?.let { marker.title = it }
|
|
143
135
|
draggable?.let { marker.isDraggable = it }
|
|
144
|
-
|
|
145
|
-
Log.d(TAG, "✅ 标记点已更新: $id")
|
|
146
136
|
}
|
|
147
137
|
}
|
|
148
138
|
|
|
149
139
|
// ==================== 折线 ====================
|
|
150
140
|
|
|
151
141
|
fun addPolyline(id: String, props: Map<String, Any>) {
|
|
152
|
-
Log.d(TAG, "📏 addPolyline: id=$id")
|
|
153
142
|
|
|
154
143
|
@Suppress("UNCHECKED_CAST")
|
|
155
144
|
val points = props["points"] as? List<Map<String, Double>>
|
|
156
|
-
val width = (props["
|
|
145
|
+
val width = (props["strokeWidth"] as? Number)?.toFloat() ?: 10f
|
|
157
146
|
val texture = props["texture"] as? String
|
|
158
147
|
val color = if (!texture.isNullOrEmpty()) {
|
|
159
148
|
android.graphics.Color.TRANSPARENT
|
|
160
149
|
} else {
|
|
161
|
-
ColorParser.parseColor(props["
|
|
150
|
+
ColorParser.parseColor(props["strokeColor"])
|
|
162
151
|
}
|
|
163
152
|
|
|
164
153
|
if (points != null && points.size >= 2) {
|
|
@@ -199,7 +188,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
199
188
|
}
|
|
200
189
|
|
|
201
190
|
polylines[id] = polyline
|
|
202
|
-
Log.d(TAG, "✅ 折线创建成功")
|
|
203
191
|
}
|
|
204
192
|
}
|
|
205
193
|
|
|
@@ -207,7 +195,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
207
195
|
polylines[id]?.let { polyline ->
|
|
208
196
|
polyline.remove()
|
|
209
197
|
polylines.remove(id)
|
|
210
|
-
Log.d(TAG, "✅ 折线已移除: $id")
|
|
211
198
|
}
|
|
212
199
|
}
|
|
213
200
|
|
|
@@ -215,8 +202,8 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
215
202
|
polylines[id]?.let { polyline ->
|
|
216
203
|
@Suppress("UNCHECKED_CAST")
|
|
217
204
|
val points = props["points"] as? List<Map<String, Double>>
|
|
218
|
-
val width = (props["
|
|
219
|
-
val color = props["
|
|
205
|
+
val width = (props["strokeWidth"] as? Number)?.toFloat()
|
|
206
|
+
val color = props["strokeColor"]?.let { ColorParser.parseColor(it) }
|
|
220
207
|
|
|
221
208
|
points?.let {
|
|
222
209
|
val latLngs = it.map { point ->
|
|
@@ -229,15 +216,12 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
229
216
|
|
|
230
217
|
width?.let { polyline.width = it }
|
|
231
218
|
color?.let { polyline.color = it }
|
|
232
|
-
|
|
233
|
-
Log.d(TAG, "✅ 折线已更新: $id")
|
|
234
219
|
}
|
|
235
220
|
}
|
|
236
221
|
|
|
237
222
|
// ==================== 多边形 ====================
|
|
238
223
|
|
|
239
224
|
fun addPolygon(id: String, props: Map<String, Any>) {
|
|
240
|
-
Log.d(TAG, "🔷 addPolygon: id=$id")
|
|
241
225
|
|
|
242
226
|
@Suppress("UNCHECKED_CAST")
|
|
243
227
|
val points = props["points"] as? List<Map<String, Double>>
|
|
@@ -271,7 +255,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
271
255
|
polygons[id]?.let { polygon ->
|
|
272
256
|
polygon.remove()
|
|
273
257
|
polygons.remove(id)
|
|
274
|
-
Log.d(TAG, "✅ 多边形已移除: $id")
|
|
275
258
|
}
|
|
276
259
|
}
|
|
277
260
|
|
|
@@ -298,8 +281,6 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
298
281
|
strokeColor?.let { polygon.strokeColor = it }
|
|
299
282
|
strokeWidth?.let { polygon.strokeWidth = it }
|
|
300
283
|
zIndex?.let { polygon.zIndex = it }
|
|
301
|
-
|
|
302
|
-
Log.d(TAG, "✅ 多边形已更新: $id")
|
|
303
284
|
}
|
|
304
285
|
}
|
|
305
286
|
|
|
@@ -126,7 +126,6 @@ class UIManager(private val aMap: AMap, private val context: Context) {
|
|
|
126
126
|
|
|
127
127
|
// 自定义图标 (image)
|
|
128
128
|
(config["image"] as? String)?.let { imagePath ->
|
|
129
|
-
android.util.Log.d("UIManager", "设置定位图标: $imagePath")
|
|
130
129
|
|
|
131
130
|
// 将 dp 转换为 px (与 iOS points 对应)
|
|
132
131
|
val density = context.resources.displayMetrics.density
|
|
@@ -144,7 +143,6 @@ class UIManager(private val aMap: AMap, private val context: Context) {
|
|
|
144
143
|
android.graphics.Bitmap.createScaledBitmap(bitmap, imageWidth, imageHeight, true)
|
|
145
144
|
} else bitmap
|
|
146
145
|
|
|
147
|
-
android.util.Log.d("UIManager", "网络图片加载成功")
|
|
148
146
|
style.myLocationIcon(BitmapDescriptorFactory.fromBitmap(scaledBitmap))
|
|
149
147
|
aMap.myLocationStyle = style
|
|
150
148
|
} ?: android.util.Log.e("UIManager", "网络图片加载失败")
|
|
@@ -154,34 +152,39 @@ class UIManager(private val aMap: AMap, private val context: Context) {
|
|
|
154
152
|
}
|
|
155
153
|
}.start()
|
|
156
154
|
} else {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
// 本地图片也在后台线程加载,避免阻塞主线程
|
|
156
|
+
Thread {
|
|
157
|
+
try {
|
|
158
|
+
val originalBitmap = when {
|
|
159
|
+
imagePath.startsWith("file://") -> {
|
|
160
|
+
BitmapFactory.decodeFile(imagePath.substring(7))
|
|
161
|
+
}
|
|
162
|
+
else -> {
|
|
163
|
+
val resId = context.resources.getIdentifier(
|
|
164
|
+
imagePath.substringBeforeLast('.'),
|
|
165
|
+
"drawable",
|
|
166
|
+
context.packageName
|
|
167
|
+
)
|
|
168
|
+
if (resId != 0) {
|
|
169
|
+
BitmapFactory.decodeResource(context.resources, resId)
|
|
170
|
+
} else null
|
|
171
|
+
}
|
|
161
172
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
|
|
174
|
+
android.os.Handler(android.os.Looper.getMainLooper()).post {
|
|
175
|
+
originalBitmap?.let { bitmap ->
|
|
176
|
+
val scaledBitmap = if (imageWidth != null && imageHeight != null) {
|
|
177
|
+
android.graphics.Bitmap.createScaledBitmap(bitmap, imageWidth, imageHeight, true)
|
|
178
|
+
} else bitmap
|
|
179
|
+
|
|
180
|
+
style.myLocationIcon(BitmapDescriptorFactory.fromBitmap(scaledBitmap))
|
|
181
|
+
aMap.myLocationStyle = style
|
|
182
|
+
} ?: android.util.Log.e("UIManager", "本地图片加载失败")
|
|
171
183
|
}
|
|
184
|
+
} catch (e: Exception) {
|
|
185
|
+
android.util.Log.e("UIManager", "加载本地图片异常", e)
|
|
172
186
|
}
|
|
173
|
-
|
|
174
|
-
originalBitmap?.let { bitmap ->
|
|
175
|
-
val scaledBitmap = if (imageWidth != null && imageHeight != null) {
|
|
176
|
-
android.graphics.Bitmap.createScaledBitmap(bitmap, imageWidth, imageHeight, true)
|
|
177
|
-
} else bitmap
|
|
178
|
-
|
|
179
|
-
android.util.Log.d("UIManager", "本地图片加载成功")
|
|
180
|
-
style.myLocationIcon(BitmapDescriptorFactory.fromBitmap(scaledBitmap))
|
|
181
|
-
} ?: android.util.Log.e("UIManager", "本地图片加载失败")
|
|
182
|
-
} catch (e: Exception) {
|
|
183
|
-
android.util.Log.e("UIManager", "加载本地图片异常", e)
|
|
184
|
-
}
|
|
187
|
+
}.start()
|
|
185
188
|
}
|
|
186
189
|
}
|
|
187
190
|
|