expo-gaode-map 1.0.3 → 1.0.5
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/android/src/main/AndroidManifest.xml +13 -1
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +76 -5
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +90 -6
- package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +87 -0
- package/android/src/main/java/expo/modules/gaodemap/modules/LocationManager.kt +25 -0
- package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +16 -0
- package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerView.kt +2 -0
- package/android/src/main/java/expo/modules/gaodemap/overlays/MultiPointView.kt +1 -1
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolygonView.kt +22 -2
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +83 -17
- package/android/src/main/java/expo/modules/gaodemap/services/LocationForegroundService.kt +78 -0
- package/build/ExpoGaodeMapModule.d.ts +33 -0
- package/build/ExpoGaodeMapModule.d.ts.map +1 -1
- package/build/ExpoGaodeMapModule.js +0 -1
- package/build/ExpoGaodeMapModule.js.map +1 -1
- package/build/ExpoGaodeMapView.d.ts +6 -15
- package/build/ExpoGaodeMapView.d.ts.map +1 -1
- package/build/ExpoGaodeMapView.js +40 -55
- package/build/ExpoGaodeMapView.js.map +1 -1
- package/build/components/overlays/Circle.d.ts.map +1 -1
- package/build/components/overlays/Circle.js +7 -0
- package/build/components/overlays/Circle.js.map +1 -1
- package/build/components/overlays/Marker.js +10 -0
- package/build/components/overlays/Marker.js.map +1 -1
- package/build/components/overlays/Polygon.d.ts +1 -0
- package/build/components/overlays/Polygon.d.ts.map +1 -1
- package/build/components/overlays/Polygon.js +22 -3
- package/build/components/overlays/Polygon.js.map +1 -1
- package/build/components/overlays/Polyline.d.ts +1 -0
- package/build/components/overlays/Polyline.d.ts.map +1 -1
- package/build/components/overlays/Polyline.js +25 -3
- package/build/components/overlays/Polyline.js.map +1 -1
- package/build/modules/AMapLocation.d.ts +2 -19
- package/build/modules/AMapLocation.d.ts.map +1 -1
- package/build/modules/AMapLocation.js +36 -73
- package/build/modules/AMapLocation.js.map +1 -1
- package/build/types/location.types.d.ts +0 -1
- package/build/types/location.types.d.ts.map +1 -1
- package/build/types/location.types.js.map +1 -1
- package/build/types/map-view.types.d.ts +12 -0
- package/build/types/map-view.types.d.ts.map +1 -1
- package/build/types/map-view.types.js.map +1 -1
- package/build/types/overlays.types.d.ts +6 -0
- package/build/types/overlays.types.d.ts.map +1 -1
- package/build/types/overlays.types.js.map +1 -1
- package/build/utils/EventManager.d.ts +11 -0
- package/build/utils/EventManager.d.ts.map +1 -0
- package/build/utils/EventManager.js +21 -0
- package/build/utils/EventManager.js.map +1 -0
- package/docs/API.md +91 -7
- package/docs/INITIALIZATION.md +14 -4
- package/ios/ExpoGaodeMapModule.swift +91 -5
- package/ios/ExpoGaodeMapView.swift +157 -11
- package/ios/managers/OverlayManager.swift +116 -8
- package/ios/modules/LocationManager.swift +5 -2
- package/ios/overlays/PolygonView.swift +2 -0
- package/ios/overlays/PolylineView.swift +14 -0
- package/ios/utils/PermissionManager.swift +62 -7
- package/package.json +1 -1
- package/src/ExpoGaodeMapModule.ts +39 -5
- package/src/ExpoGaodeMapView.tsx +53 -84
- package/src/components/overlays/Circle.tsx +8 -0
- package/src/components/overlays/Marker.tsx +11 -0
- package/src/components/overlays/Polygon.tsx +24 -3
- package/src/components/overlays/Polyline.tsx +27 -3
- package/src/modules/AMapLocation.ts +38 -73
- package/src/types/location.types.ts +0 -1
- package/src/types/map-view.types.ts +10 -0
- package/src/types/overlays.types.ts +6 -0
- package/src/utils/EventManager.ts +23 -0
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
<!-- Android 10及以上需要后台定位权限 -->
|
|
22
22
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
|
23
23
|
|
|
24
|
+
<!-- 前台服务权限 (Android 9+) -->
|
|
25
|
+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
26
|
+
<!-- Android 14+ 需要指定前台服务类型 -->
|
|
27
|
+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
|
28
|
+
|
|
24
29
|
<!-- 写入扩展存储,用于缓存地图数据 -->
|
|
25
30
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
26
31
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
@@ -30,11 +35,18 @@
|
|
|
30
35
|
|
|
31
36
|
<application>
|
|
32
37
|
<!-- 高德地图 API Key(这里只是示例,实际会通过代码设置) -->
|
|
33
|
-
<!--
|
|
38
|
+
<!--
|
|
34
39
|
<meta-data
|
|
35
40
|
android:name="com.amap.api.v2.apikey"
|
|
36
41
|
android:value="YOUR_API_KEY_HERE"/>
|
|
37
42
|
-->
|
|
43
|
+
|
|
44
|
+
<!-- 定位前台服务 -->
|
|
45
|
+
<service
|
|
46
|
+
android:name="expo.modules.gaodemap.services.LocationForegroundService"
|
|
47
|
+
android:enabled="true"
|
|
48
|
+
android:exported="false"
|
|
49
|
+
android:foregroundServiceType="location" />
|
|
38
50
|
</application>
|
|
39
51
|
|
|
40
52
|
</manifest>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package expo.modules.gaodemap
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
import expo.modules.kotlin.modules.Module
|
|
5
5
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
6
6
|
import expo.modules.gaodemap.modules.SDKInitializer
|
|
@@ -17,9 +17,7 @@ import expo.modules.gaodemap.overlays.*
|
|
|
17
17
|
* - 地图视图和覆盖物注册
|
|
18
18
|
*/
|
|
19
19
|
class ExpoGaodeMapModule : Module() {
|
|
20
|
-
|
|
21
|
-
private const val TAG = "ExpoGaodeMapModule"
|
|
22
|
-
}
|
|
20
|
+
|
|
23
21
|
|
|
24
22
|
/** 定位管理器实例 */
|
|
25
23
|
private var locationManager: LocationManager? = null
|
|
@@ -181,6 +179,63 @@ class ExpoGaodeMapModule : Module() {
|
|
|
181
179
|
getLocationManager().setHttpTimeOut(httpTimeOut)
|
|
182
180
|
}
|
|
183
181
|
|
|
182
|
+
/**
|
|
183
|
+
* 设置定位精度 (iOS 专用,Android 空实现)
|
|
184
|
+
* @param accuracy 精度级别
|
|
185
|
+
*/
|
|
186
|
+
Function("setDesiredAccuracy") { _: Int ->
|
|
187
|
+
// Android 不支持此配置
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 设置定位超时时间 (iOS 专用,Android 空实现)
|
|
192
|
+
* @param timeout 超时时间(秒)
|
|
193
|
+
*/
|
|
194
|
+
Function("setLocationTimeout") { _: Int ->
|
|
195
|
+
// Android 不支持此配置
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* 设置逆地理超时时间 (iOS 专用,Android 空实现)
|
|
200
|
+
* @param timeout 超时时间(秒)
|
|
201
|
+
*/
|
|
202
|
+
Function("setReGeocodeTimeout") { _: Int ->
|
|
203
|
+
// Android 不支持此配置
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 设置距离过滤器 (iOS 专用,Android 空实现)
|
|
208
|
+
* @param distance 最小距离变化(米)
|
|
209
|
+
*/
|
|
210
|
+
Function("setDistanceFilter") { _: Double ->
|
|
211
|
+
// Android 不支持此配置
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 设置是否自动暂停定位更新 (iOS 专用,Android 空实现)
|
|
216
|
+
* @param pauses 是否自动暂停
|
|
217
|
+
*/
|
|
218
|
+
Function("setPausesLocationUpdatesAutomatically") { _: Boolean ->
|
|
219
|
+
// Android 不支持此配置
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 设置是否允许后台定位
|
|
224
|
+
* Android 通过前台服务实现,iOS 通过系统配置实现
|
|
225
|
+
* @param allows 是否允许后台定位
|
|
226
|
+
*/
|
|
227
|
+
Function("setAllowsBackgroundLocationUpdates") { allows: Boolean ->
|
|
228
|
+
getLocationManager().setAllowsBackgroundLocationUpdates(allows)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 设置定位协议 (未实现)
|
|
233
|
+
* @param protocol 协议类型
|
|
234
|
+
*/
|
|
235
|
+
Function("setLocationProtocol") { _: Int ->
|
|
236
|
+
// 未实现
|
|
237
|
+
}
|
|
238
|
+
|
|
184
239
|
// ==================== 权限管理 ====================
|
|
185
240
|
|
|
186
241
|
/**
|
|
@@ -271,7 +326,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
271
326
|
View(ExpoGaodeMapView::class) {
|
|
272
327
|
|
|
273
328
|
// 事件
|
|
274
|
-
Events("onMapPress", "onMapLongPress", "onLoad", "onMarkerPress", "onMarkerDragStart", "onMarkerDrag", "onMarkerDragEnd", "onCirclePress")
|
|
329
|
+
Events("onMapPress", "onMapLongPress", "onLoad", "onMarkerPress", "onMarkerDragStart", "onMarkerDrag", "onMarkerDragEnd", "onCirclePress", "onPolygonPress", "onPolylinePress")
|
|
275
330
|
|
|
276
331
|
// 地图类型
|
|
277
332
|
Prop<Int>("mapType") { view, type ->
|
|
@@ -457,6 +512,10 @@ class ExpoGaodeMapModule : Module() {
|
|
|
457
512
|
Prop<Float>("strokeWidth") { view, width ->
|
|
458
513
|
view.setStrokeWidth(width)
|
|
459
514
|
}
|
|
515
|
+
|
|
516
|
+
Prop<Float>("zIndex") { view, zIndex ->
|
|
517
|
+
view.setZIndex(zIndex)
|
|
518
|
+
}
|
|
460
519
|
}
|
|
461
520
|
|
|
462
521
|
// Polyline - 折线
|
|
@@ -478,6 +537,18 @@ class ExpoGaodeMapModule : Module() {
|
|
|
478
537
|
Prop<String?>("texture") { view: PolylineView, texture ->
|
|
479
538
|
view.setTexture(texture)
|
|
480
539
|
}
|
|
540
|
+
|
|
541
|
+
Prop<Boolean>("dotted") { view: PolylineView, dotted ->
|
|
542
|
+
view.setDotted(dotted)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
Prop<Boolean>("geodesic") { view: PolylineView, geodesic ->
|
|
546
|
+
view.setGeodesic(geodesic)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
Prop<Float>("zIndex") { view: PolylineView, zIndex ->
|
|
550
|
+
view.setZIndex(zIndex)
|
|
551
|
+
}
|
|
481
552
|
}
|
|
482
553
|
|
|
483
554
|
// Polygon - 多边形
|
|
@@ -6,6 +6,7 @@ import android.view.View
|
|
|
6
6
|
import com.amap.api.maps.AMap
|
|
7
7
|
import com.amap.api.maps.MapView
|
|
8
8
|
import com.amap.api.maps.MapsInitializer
|
|
9
|
+
import com.amap.api.maps.model.LatLng
|
|
9
10
|
import expo.modules.kotlin.AppContext
|
|
10
11
|
import expo.modules.kotlin.viewevent.EventDispatcher
|
|
11
12
|
import expo.modules.kotlin.views.ExpoView
|
|
@@ -50,6 +51,8 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
50
51
|
private val onMarkerDrag by EventDispatcher()
|
|
51
52
|
private val onMarkerDragEnd by EventDispatcher()
|
|
52
53
|
private val onCirclePress by EventDispatcher()
|
|
54
|
+
private val onPolygonPress by EventDispatcher()
|
|
55
|
+
private val onPolylinePress by EventDispatcher()
|
|
53
56
|
|
|
54
57
|
// 高德地图视图
|
|
55
58
|
private lateinit var mapView: MapView
|
|
@@ -114,6 +117,20 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
114
117
|
"longitude" to lng
|
|
115
118
|
))
|
|
116
119
|
}
|
|
120
|
+
onPolygonPress = { id, lat, lng ->
|
|
121
|
+
this@ExpoGaodeMapView.onPolygonPress(mapOf(
|
|
122
|
+
"polygonId" to id,
|
|
123
|
+
"latitude" to lat,
|
|
124
|
+
"longitude" to lng
|
|
125
|
+
))
|
|
126
|
+
}
|
|
127
|
+
onPolylinePress = { id, lat, lng ->
|
|
128
|
+
this@ExpoGaodeMapView.onPolylinePress(mapOf(
|
|
129
|
+
"polylineId" to id,
|
|
130
|
+
"latitude" to lat,
|
|
131
|
+
"longitude" to lng
|
|
132
|
+
))
|
|
133
|
+
}
|
|
117
134
|
}
|
|
118
135
|
|
|
119
136
|
// 添加地图视图到布局
|
|
@@ -149,16 +166,47 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
149
166
|
*/
|
|
150
167
|
private fun setupMapListeners() {
|
|
151
168
|
aMap.setOnMapClickListener { latLng ->
|
|
152
|
-
//
|
|
169
|
+
// 检查声明式 PolylineView
|
|
170
|
+
if (checkDeclarativePolylinePress(latLng)) {
|
|
171
|
+
return@setOnMapClickListener
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 检查声明式 PolygonView
|
|
175
|
+
if (checkDeclarativePolygonPress(latLng)) {
|
|
176
|
+
return@setOnMapClickListener
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 检查声明式 CircleView
|
|
180
|
+
if (checkDeclarativeCirclePress(latLng)) {
|
|
181
|
+
return@setOnMapClickListener
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 检查命令式圆形
|
|
153
185
|
val circleId = overlayManager.checkCirclePress(latLng)
|
|
154
186
|
if (circleId != null) {
|
|
155
187
|
overlayManager.onCirclePress?.invoke(circleId, latLng.latitude, latLng.longitude)
|
|
156
|
-
|
|
157
|
-
onMapPress(mapOf(
|
|
158
|
-
"latitude" to latLng.latitude,
|
|
159
|
-
"longitude" to latLng.longitude
|
|
160
|
-
))
|
|
188
|
+
return@setOnMapClickListener
|
|
161
189
|
}
|
|
190
|
+
|
|
191
|
+
// 检查命令式多边形
|
|
192
|
+
val polygonId = overlayManager.checkPolygonPress(latLng)
|
|
193
|
+
if (polygonId != null) {
|
|
194
|
+
overlayManager.onPolygonPress?.invoke(polygonId, latLng.latitude, latLng.longitude)
|
|
195
|
+
return@setOnMapClickListener
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 检查命令式折线
|
|
199
|
+
val polylineId = overlayManager.checkPolylinePress(latLng)
|
|
200
|
+
if (polylineId != null) {
|
|
201
|
+
overlayManager.onPolylinePress?.invoke(polylineId, latLng.latitude, latLng.longitude)
|
|
202
|
+
return@setOnMapClickListener
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 如果都没点击,触发地图点击事件
|
|
206
|
+
onMapPress(mapOf(
|
|
207
|
+
"latitude" to latLng.latitude,
|
|
208
|
+
"longitude" to latLng.longitude
|
|
209
|
+
))
|
|
162
210
|
}
|
|
163
211
|
|
|
164
212
|
aMap.setOnMapLongClickListener { latLng ->
|
|
@@ -447,6 +495,42 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
447
495
|
}
|
|
448
496
|
}
|
|
449
497
|
|
|
498
|
+
private fun checkDeclarativePolylinePress(latLng: LatLng): Boolean {
|
|
499
|
+
for (i in 0 until childCount) {
|
|
500
|
+
val child = getChildAt(i)
|
|
501
|
+
if (child is PolylineView) {
|
|
502
|
+
if (child.checkPress(latLng)) {
|
|
503
|
+
return true
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return false
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
private fun checkDeclarativePolygonPress(latLng: LatLng): Boolean {
|
|
511
|
+
for (i in 0 until childCount) {
|
|
512
|
+
val child = getChildAt(i)
|
|
513
|
+
if (child is PolygonView) {
|
|
514
|
+
if (child.checkPress(latLng)) {
|
|
515
|
+
return true
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return false
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
private fun checkDeclarativeCirclePress(latLng: LatLng): Boolean {
|
|
523
|
+
for (i in 0 until childCount) {
|
|
524
|
+
val child = getChildAt(i)
|
|
525
|
+
if (child is CircleView) {
|
|
526
|
+
if (child.checkPress(latLng)) {
|
|
527
|
+
return true
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return false
|
|
532
|
+
}
|
|
533
|
+
|
|
450
534
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
451
535
|
super.onLayout(changed, left, top, right, bottom)
|
|
452
536
|
}
|
|
@@ -32,12 +32,20 @@ class OverlayManager(private val aMap: AMap, private val context: Context) {
|
|
|
32
32
|
// Circle ID 映射
|
|
33
33
|
private val circleIdMap = mutableMapOf<com.amap.api.maps.model.Circle, String>()
|
|
34
34
|
|
|
35
|
+
// Polygon ID 映射
|
|
36
|
+
private val polygonIdMap = mutableMapOf<com.amap.api.maps.model.Polygon, String>()
|
|
37
|
+
|
|
38
|
+
// Polyline ID 映射
|
|
39
|
+
private val polylineIdMap = mutableMapOf<com.amap.api.maps.model.Polyline, String>()
|
|
40
|
+
|
|
35
41
|
// 事件回调
|
|
36
42
|
var onMarkerPress: ((String, Double, Double) -> Unit)? = null
|
|
37
43
|
var onMarkerDragStart: ((String, Double, Double) -> Unit)? = null
|
|
38
44
|
var onMarkerDrag: ((String, Double, Double) -> Unit)? = null
|
|
39
45
|
var onMarkerDragEnd: ((String, Double, Double) -> Unit)? = null
|
|
40
46
|
var onCirclePress: ((String, Double, Double) -> Unit)? = null
|
|
47
|
+
var onPolygonPress: ((String, Double, Double) -> Unit)? = null
|
|
48
|
+
var onPolylinePress: ((String, Double, Double) -> Unit)? = null
|
|
41
49
|
|
|
42
50
|
private val mainHandler = android.os.Handler(android.os.Looper.getMainLooper())
|
|
43
51
|
|
|
@@ -345,11 +353,13 @@ class OverlayManager(private val aMap: AMap, private val context: Context) {
|
|
|
345
353
|
}
|
|
346
354
|
|
|
347
355
|
polylines[id] = polyline
|
|
356
|
+
polylineIdMap[polyline] = id
|
|
348
357
|
}
|
|
349
358
|
}
|
|
350
359
|
|
|
351
360
|
fun removePolyline(id: String) {
|
|
352
361
|
polylines[id]?.let { polyline ->
|
|
362
|
+
polylineIdMap.remove(polyline)
|
|
353
363
|
polyline.remove()
|
|
354
364
|
polylines.remove(id)
|
|
355
365
|
}
|
|
@@ -404,12 +414,14 @@ class OverlayManager(private val aMap: AMap, private val context: Context) {
|
|
|
404
414
|
|
|
405
415
|
val polygon = aMap.addPolygon(options)
|
|
406
416
|
polygons[id] = polygon
|
|
417
|
+
polygonIdMap[polygon] = id
|
|
407
418
|
Log.d(TAG, "✅ 多边形创建成功")
|
|
408
419
|
}
|
|
409
420
|
}
|
|
410
421
|
|
|
411
422
|
fun removePolygon(id: String) {
|
|
412
423
|
polygons[id]?.let { polygon ->
|
|
424
|
+
polygonIdMap.remove(polygon)
|
|
413
425
|
polygon.remove()
|
|
414
426
|
polygons.remove(id)
|
|
415
427
|
}
|
|
@@ -456,6 +468,78 @@ class OverlayManager(private val aMap: AMap, private val context: Context) {
|
|
|
456
468
|
return null
|
|
457
469
|
}
|
|
458
470
|
|
|
471
|
+
/**
|
|
472
|
+
* 检查点击位置是否在某个多边形内
|
|
473
|
+
*/
|
|
474
|
+
fun checkPolygonPress(latLng: LatLng): String? {
|
|
475
|
+
for ((polygon, id) in polygonIdMap) {
|
|
476
|
+
if (polygon.contains(latLng)) {
|
|
477
|
+
return id
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return null
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* 检查点击位置是否在某条折线附近
|
|
485
|
+
*/
|
|
486
|
+
fun checkPolylinePress(latLng: LatLng): String? {
|
|
487
|
+
val threshold = 20.0 // 20米容差
|
|
488
|
+
for ((polyline, id) in polylineIdMap) {
|
|
489
|
+
val points = polyline.points
|
|
490
|
+
if (points.size < 2) continue
|
|
491
|
+
|
|
492
|
+
for (i in 0 until points.size - 1) {
|
|
493
|
+
val distance = distanceToSegment(latLng, points[i], points[i + 1])
|
|
494
|
+
if (distance <= threshold) {
|
|
495
|
+
return id
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return null
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* 计算点到线段的距离(米)
|
|
504
|
+
*/
|
|
505
|
+
private fun distanceToSegment(point: LatLng, start: LatLng, end: LatLng): Double {
|
|
506
|
+
val p = android.location.Location("").apply {
|
|
507
|
+
latitude = point.latitude
|
|
508
|
+
longitude = point.longitude
|
|
509
|
+
}
|
|
510
|
+
val a = android.location.Location("").apply {
|
|
511
|
+
latitude = start.latitude
|
|
512
|
+
longitude = start.longitude
|
|
513
|
+
}
|
|
514
|
+
val b = android.location.Location("").apply {
|
|
515
|
+
latitude = end.latitude
|
|
516
|
+
longitude = end.longitude
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
val ab = a.distanceTo(b).toDouble()
|
|
520
|
+
if (ab == 0.0) return a.distanceTo(p).toDouble()
|
|
521
|
+
|
|
522
|
+
val ap = a.distanceTo(p).toDouble()
|
|
523
|
+
val bp = b.distanceTo(p).toDouble()
|
|
524
|
+
|
|
525
|
+
val t = maxOf(0.0, minOf(1.0,
|
|
526
|
+
((point.latitude - start.latitude) * (end.latitude - start.latitude) +
|
|
527
|
+
(point.longitude - start.longitude) * (end.longitude - start.longitude)) / (ab * ab)
|
|
528
|
+
))
|
|
529
|
+
|
|
530
|
+
val projection = LatLng(
|
|
531
|
+
start.latitude + t * (end.latitude - start.latitude),
|
|
532
|
+
start.longitude + t * (end.longitude - start.longitude)
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
val proj = android.location.Location("").apply {
|
|
536
|
+
latitude = projection.latitude
|
|
537
|
+
longitude = projection.longitude
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return p.distanceTo(proj).toDouble()
|
|
541
|
+
}
|
|
542
|
+
|
|
459
543
|
fun clear() {
|
|
460
544
|
circles.values.forEach { it.remove() }
|
|
461
545
|
circles.clear()
|
|
@@ -469,6 +553,9 @@ class OverlayManager(private val aMap: AMap, private val context: Context) {
|
|
|
469
553
|
|
|
470
554
|
polygons.values.forEach { it.remove() }
|
|
471
555
|
polygons.clear()
|
|
556
|
+
polygonIdMap.clear()
|
|
557
|
+
|
|
558
|
+
polylineIdMap.clear()
|
|
472
559
|
}
|
|
473
560
|
|
|
474
561
|
/**
|
|
@@ -7,6 +7,7 @@ import com.amap.api.location.AMapLocationClient
|
|
|
7
7
|
import com.amap.api.location.AMapLocationClientOption
|
|
8
8
|
import com.amap.api.maps.model.LatLng
|
|
9
9
|
import expo.modules.kotlin.Promise
|
|
10
|
+
import expo.modules.gaodemap.services.LocationForegroundService
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* 定位管理器
|
|
@@ -32,6 +33,8 @@ class LocationManager(context: Context) {
|
|
|
32
33
|
private var isLocationStarted = false
|
|
33
34
|
/** 定位更新回调 */
|
|
34
35
|
private var onLocationUpdate: ((Map<String, Any?>) -> Unit)? = null
|
|
36
|
+
/** 是否启用后台定位 */
|
|
37
|
+
private var allowsBackgroundLocationUpdates = false
|
|
35
38
|
|
|
36
39
|
init {
|
|
37
40
|
initLocationClient()
|
|
@@ -52,6 +55,12 @@ class LocationManager(context: Context) {
|
|
|
52
55
|
if (locationClient == null) {
|
|
53
56
|
initLocationClient()
|
|
54
57
|
}
|
|
58
|
+
|
|
59
|
+
// 如果启用后台定位,启动前台服务
|
|
60
|
+
if (allowsBackgroundLocationUpdates) {
|
|
61
|
+
LocationForegroundService.start(appContext)
|
|
62
|
+
}
|
|
63
|
+
|
|
55
64
|
locationClient?.startLocation()
|
|
56
65
|
isLocationStarted = true
|
|
57
66
|
}
|
|
@@ -62,6 +71,11 @@ class LocationManager(context: Context) {
|
|
|
62
71
|
fun stop() {
|
|
63
72
|
locationClient?.stopLocation()
|
|
64
73
|
isLocationStarted = false
|
|
74
|
+
|
|
75
|
+
// 停止前台服务
|
|
76
|
+
if (allowsBackgroundLocationUpdates) {
|
|
77
|
+
LocationForegroundService.stop(appContext)
|
|
78
|
+
}
|
|
65
79
|
}
|
|
66
80
|
|
|
67
81
|
/**
|
|
@@ -205,6 +219,11 @@ class LocationManager(context: Context) {
|
|
|
205
219
|
applyLocationOption()
|
|
206
220
|
}
|
|
207
221
|
|
|
222
|
+
/** 设置是否允许后台定位 */
|
|
223
|
+
fun setAllowsBackgroundLocationUpdates(allows: Boolean) {
|
|
224
|
+
allowsBackgroundLocationUpdates = allows
|
|
225
|
+
}
|
|
226
|
+
|
|
208
227
|
/**
|
|
209
228
|
* 销毁资源
|
|
210
229
|
*/
|
|
@@ -214,6 +233,11 @@ class LocationManager(context: Context) {
|
|
|
214
233
|
locationClient?.onDestroy()
|
|
215
234
|
locationClient = null
|
|
216
235
|
locationOption = null
|
|
236
|
+
|
|
237
|
+
// 确保停止前台服务
|
|
238
|
+
if (allowsBackgroundLocationUpdates) {
|
|
239
|
+
LocationForegroundService.stop(appContext)
|
|
240
|
+
}
|
|
217
241
|
}
|
|
218
242
|
|
|
219
243
|
// ==================== 私有方法 ====================
|
|
@@ -229,6 +253,7 @@ class LocationManager(context: Context) {
|
|
|
229
253
|
onLocationUpdate?.invoke(formatLocation(location))
|
|
230
254
|
}
|
|
231
255
|
}
|
|
256
|
+
|
|
232
257
|
}
|
|
233
258
|
|
|
234
259
|
locationOption = AMapLocationClientOption().apply {
|
|
@@ -103,6 +103,22 @@ class CircleView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* 检查点击位置是否在圆形内
|
|
108
|
+
*/
|
|
109
|
+
fun checkPress(latLng: LatLng): Boolean {
|
|
110
|
+
circle?.let { c ->
|
|
111
|
+
if (c.contains(latLng)) {
|
|
112
|
+
onPress(mapOf(
|
|
113
|
+
"latitude" to latLng.latitude,
|
|
114
|
+
"longitude" to latLng.longitude
|
|
115
|
+
))
|
|
116
|
+
return true
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
|
|
106
122
|
/**
|
|
107
123
|
* 移除圆形
|
|
108
124
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package expo.modules.gaodemap.overlays
|
|
2
2
|
|
|
3
|
+
import android.annotation.SuppressLint
|
|
3
4
|
import android.content.Context
|
|
4
5
|
import android.graphics.Bitmap
|
|
5
6
|
import android.graphics.Canvas
|
|
@@ -95,6 +96,7 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
95
96
|
/**
|
|
96
97
|
* 设置锚点
|
|
97
98
|
*/
|
|
99
|
+
@SuppressLint("SuspiciousIndentation")
|
|
98
100
|
fun setAnchor(anchor: Map<String, Float>) {
|
|
99
101
|
val x = anchor["x"] ?: 0.5f
|
|
100
102
|
val y = anchor["y"] ?: 1.0f
|
|
@@ -80,7 +80,7 @@ class MultiPointView(context: Context, appContext: AppContext) : ExpoView(contex
|
|
|
80
80
|
|
|
81
81
|
// 创建海量点覆盖物
|
|
82
82
|
multiPointOverlay = map.addMultiPointOverlay(overlayOptions)
|
|
83
|
-
|
|
83
|
+
multiPointOverlay?.items = points
|
|
84
84
|
|
|
85
85
|
// 注意:MultiPointOverlay 在高德地图 Android SDK 中不直接支持点击事件
|
|
86
86
|
// 如果需要点击事件,需要使用 Marker 或其他方式实现
|
|
@@ -17,6 +17,7 @@ class PolygonView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
17
17
|
private var polygon: Polygon? = null
|
|
18
18
|
private var aMap: AMap? = null
|
|
19
19
|
private var points: List<LatLng> = emptyList()
|
|
20
|
+
private var strokeWidth: Float = 10f
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* 设置地图实例
|
|
@@ -65,8 +66,11 @@ class PolygonView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
65
66
|
* 设置边框宽度
|
|
66
67
|
*/
|
|
67
68
|
fun setStrokeWidth(width: Float) {
|
|
69
|
+
// Android 需要乘以屏幕密度以匹配 iOS 的视觉效果
|
|
70
|
+
val density = context.resources.displayMetrics.density
|
|
71
|
+
strokeWidth = width * density
|
|
68
72
|
polygon?.let {
|
|
69
|
-
it.strokeWidth =
|
|
73
|
+
it.strokeWidth = strokeWidth
|
|
70
74
|
} ?: createOrUpdatePolygon()
|
|
71
75
|
}
|
|
72
76
|
|
|
@@ -89,7 +93,7 @@ class PolygonView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
89
93
|
.addAll(points)
|
|
90
94
|
.fillColor(Color.argb(50, 0, 0, 255))
|
|
91
95
|
.strokeColor(Color.BLUE)
|
|
92
|
-
.strokeWidth(
|
|
96
|
+
.strokeWidth(strokeWidth)
|
|
93
97
|
|
|
94
98
|
polygon = map.addPolygon(options)
|
|
95
99
|
|
|
@@ -99,6 +103,22 @@ class PolygonView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
105
|
|
|
106
|
+
/**
|
|
107
|
+
* 检查点击位置是否在多边形内
|
|
108
|
+
*/
|
|
109
|
+
fun checkPress(latLng: LatLng): Boolean {
|
|
110
|
+
polygon?.let { poly ->
|
|
111
|
+
if (poly.contains(latLng)) {
|
|
112
|
+
onPress(mapOf(
|
|
113
|
+
"latitude" to latLng.latitude,
|
|
114
|
+
"longitude" to latLng.longitude
|
|
115
|
+
))
|
|
116
|
+
return true
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
121
|
+
|
|
102
122
|
/**
|
|
103
123
|
* 移除多边形
|
|
104
124
|
*/
|