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.
- package/PUBLISHING.md +1 -1
- package/README.md +57 -9
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +121 -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 +37 -24
- 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/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +54 -3
- package/build/ExpoGaodeMapView.js +2 -2
- package/build/ExpoGaodeMapView.js.map +1 -1
- package/build/components/overlays/Polyline.d.ts.map +1 -1
- package/build/components/overlays/Polyline.js +12 -14
- package/build/components/overlays/Polyline.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/build/types/overlays.types.d.ts +5 -0
- package/build/types/overlays.types.d.ts.map +1 -1
- package/build/types/overlays.types.js.map +1 -1
- package/docs/API.md +5 -1
- package/docs/ARCHITECTURE.md +421 -0
- package/docs/EXAMPLES.md +232 -29
- package/docs/INITIALIZATION.md +342 -0
- package/ios/ExpoGaodeMapModule.swift +99 -9
- package/ios/ExpoGaodeMapView.swift +88 -6
- package/ios/managers/CameraManager.swift +58 -0
- package/ios/managers/OverlayManager.swift +172 -30
- 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 +110 -1
- package/ios/{ColorParser.swift → utils/ColorParser.swift} +13 -7
- package/ios/utils/PermissionManager.swift +58 -0
- package/package.json +1 -1
- package/src/ExpoGaodeMapView.tsx +2 -2
- package/src/components/overlays/Polyline.tsx +13 -16
- 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
- package/src/types/overlays.types.ts +6 -0
- 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
|
-
|
|
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
|
}
|
|
@@ -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["
|
|
154
|
-
val
|
|
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.
|
|
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["
|
|
187
|
-
val color = props["
|
|
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
|
|