expo-gaode-map 1.0.3 → 1.0.4

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 (39) hide show
  1. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +71 -5
  2. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +90 -6
  3. package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +87 -0
  4. package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +16 -0
  5. package/android/src/main/java/expo/modules/gaodemap/overlays/PolygonView.kt +22 -2
  6. package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +83 -17
  7. package/build/ExpoGaodeMapView.d.ts +20 -0
  8. package/build/ExpoGaodeMapView.d.ts.map +1 -1
  9. package/build/ExpoGaodeMapView.js +55 -3
  10. package/build/ExpoGaodeMapView.js.map +1 -1
  11. package/build/components/overlays/Polygon.d.ts +1 -0
  12. package/build/components/overlays/Polygon.d.ts.map +1 -1
  13. package/build/components/overlays/Polygon.js +15 -3
  14. package/build/components/overlays/Polygon.js.map +1 -1
  15. package/build/components/overlays/Polyline.d.ts +1 -0
  16. package/build/components/overlays/Polyline.d.ts.map +1 -1
  17. package/build/components/overlays/Polyline.js +18 -3
  18. package/build/components/overlays/Polyline.js.map +1 -1
  19. package/build/types/map-view.types.d.ts +12 -0
  20. package/build/types/map-view.types.d.ts.map +1 -1
  21. package/build/types/map-view.types.js.map +1 -1
  22. package/build/types/overlays.types.d.ts +6 -0
  23. package/build/types/overlays.types.d.ts.map +1 -1
  24. package/build/types/overlays.types.js.map +1 -1
  25. package/docs/API.md +81 -7
  26. package/docs/INITIALIZATION.md +14 -4
  27. package/ios/ExpoGaodeMapModule.swift +91 -5
  28. package/ios/ExpoGaodeMapView.swift +157 -11
  29. package/ios/managers/OverlayManager.swift +116 -8
  30. package/ios/modules/LocationManager.swift +3 -0
  31. package/ios/overlays/PolygonView.swift +2 -0
  32. package/ios/overlays/PolylineView.swift +14 -0
  33. package/ios/utils/PermissionManager.swift +62 -7
  34. package/package.json +1 -1
  35. package/src/ExpoGaodeMapView.tsx +87 -11
  36. package/src/components/overlays/Polygon.tsx +16 -3
  37. package/src/components/overlays/Polyline.tsx +19 -3
  38. package/src/types/map-view.types.ts +10 -0
  39. package/src/types/overlays.types.ts +6 -0
@@ -1,6 +1,6 @@
1
1
  package expo.modules.gaodemap
2
2
 
3
- import android.util.Log
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
- companion object {
21
- private const val TAG = "ExpoGaodeMapModule"
22
- }
20
+
23
21
 
24
22
  /** 定位管理器实例 */
25
23
  private var locationManager: LocationManager? = null
@@ -181,6 +179,62 @@ 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
+ * 设置是否允许后台定位 (iOS 专用,Android 空实现)
224
+ * @param allows 是否允许后台定位
225
+ */
226
+ Function("setAllowsBackgroundLocationUpdates") { _: Boolean ->
227
+ // Android 不支持此配置
228
+ }
229
+
230
+ /**
231
+ * 设置定位协议 (未实现)
232
+ * @param protocol 协议类型
233
+ */
234
+ Function("setLocationProtocol") { _: Int ->
235
+ // 未实现
236
+ }
237
+
184
238
  // ==================== 权限管理 ====================
185
239
 
186
240
  /**
@@ -271,7 +325,7 @@ class ExpoGaodeMapModule : Module() {
271
325
  View(ExpoGaodeMapView::class) {
272
326
 
273
327
  // 事件
274
- Events("onMapPress", "onMapLongPress", "onLoad", "onMarkerPress", "onMarkerDragStart", "onMarkerDrag", "onMarkerDragEnd", "onCirclePress")
328
+ Events("onMapPress", "onMapLongPress", "onLoad", "onMarkerPress", "onMarkerDragStart", "onMarkerDrag", "onMarkerDragEnd", "onCirclePress", "onPolygonPress", "onPolylinePress")
275
329
 
276
330
  // 地图类型
277
331
  Prop<Int>("mapType") { view, type ->
@@ -478,6 +532,18 @@ class ExpoGaodeMapModule : Module() {
478
532
  Prop<String?>("texture") { view: PolylineView, texture ->
479
533
  view.setTexture(texture)
480
534
  }
535
+
536
+ Prop<Boolean>("dotted") { view: PolylineView, dotted ->
537
+ view.setDotted(dotted)
538
+ }
539
+
540
+ Prop<Boolean>("geodesic") { view: PolylineView, geodesic ->
541
+ view.setGeodesic(geodesic)
542
+ }
543
+
544
+ Prop<Float>("zIndex") { view: PolylineView, zIndex ->
545
+ view.setZIndex(zIndex)
546
+ }
481
547
  }
482
548
 
483
549
  // 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
- } else {
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
  /**
@@ -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
  */
@@ -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 = width
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(10f)
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
  */
@@ -7,6 +7,8 @@ import com.amap.api.maps.model.BitmapDescriptorFactory
7
7
  import com.amap.api.maps.model.LatLng
8
8
  import com.amap.api.maps.model.Polyline
9
9
  import com.amap.api.maps.model.PolylineOptions
10
+ import com.amap.api.maps.model.PolylineOptions.LineCapType
11
+ import com.amap.api.maps.model.PolylineOptions.LineJoinType
10
12
  import expo.modules.kotlin.AppContext
11
13
  import expo.modules.kotlin.viewevent.EventDispatcher
12
14
  import expo.modules.kotlin.views.ExpoView
@@ -19,6 +21,10 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
19
21
  private var polyline: Polyline? = null
20
22
  private var aMap: AMap? = null
21
23
  private var points: List<LatLng> = emptyList()
24
+ private var strokeWidth: Float = 10f
25
+ private var strokeColor: Int = Color.BLUE
26
+ private var isDotted: Boolean = false
27
+ private var isGeodesic: Boolean = false
22
28
  private var textureUrl: String? = null
23
29
 
24
30
  /**
@@ -50,8 +56,11 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
50
56
  * 设置线宽
51
57
  */
52
58
  fun setStrokeWidth(width: Float) {
59
+ // Android 需要乘以屏幕密度以匹配 iOS 的视觉效果
60
+ val density = context.resources.displayMetrics.density
61
+ strokeWidth = width * density
53
62
  polyline?.let {
54
- it.width = width
63
+ it.width = strokeWidth
55
64
  } ?: createOrUpdatePolyline()
56
65
  }
57
66
 
@@ -59,6 +68,7 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
59
68
  * 设置线条颜色
60
69
  */
61
70
  fun setStrokeColor(color: Int) {
71
+ strokeColor = color
62
72
  polyline?.let {
63
73
  it.color = color
64
74
  } ?: createOrUpdatePolyline()
@@ -67,19 +77,17 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
67
77
  /**
68
78
  * 设置是否虚线
69
79
  */
70
- fun setDashed(dashed: Boolean) {
71
- polyline?.let {
72
- it.isDottedLine = dashed
73
- } ?: createOrUpdatePolyline()
80
+ fun setDotted(dotted: Boolean) {
81
+ isDotted = dotted
82
+ createOrUpdatePolyline()
74
83
  }
75
84
 
76
85
  /**
77
- * 设置是否使用渐变色
86
+ * 设置是否绘制大地线
78
87
  */
79
- fun setGradient(gradient: Boolean) {
80
- polyline?.let {
81
- it.isGeodesic = gradient
82
- } ?: createOrUpdatePolyline()
88
+ fun setGeodesic(geodesic: Boolean) {
89
+ isGeodesic = geodesic
90
+ createOrUpdatePolyline()
83
91
  }
84
92
 
85
93
  /**
@@ -122,8 +130,14 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
122
130
  if (points.isNotEmpty()) {
123
131
  val options = PolylineOptions()
124
132
  .addAll(points)
125
- .width(10f)
126
- .color(Color.BLUE)
133
+ .width(strokeWidth)
134
+ .color(strokeColor)
135
+ .geodesic(isGeodesic)
136
+
137
+ // 设置虚线样式
138
+ if (isDotted) {
139
+ options.dottedLineType = PolylineOptions.DOTTEDLINE_TYPE_SQUARE
140
+ }
127
141
 
128
142
  // 设置纹理
129
143
  textureUrl?.let { url ->
@@ -164,14 +178,66 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
164
178
  }
165
179
 
166
180
  polyline = map.addPolyline(options)
167
-
168
- map.setOnPolylineClickListener { clickedPolyline ->
169
- if (clickedPolyline == polyline) {
170
- onPress(mapOf("id" to clickedPolyline.id))
171
- }
181
+ }
182
+ }
183
+ }
184
+
185
+ /**
186
+ * 检查点击位置是否在折线附近
187
+ */
188
+ fun checkPress(latLng: LatLng): Boolean {
189
+ polyline?.let { line ->
190
+ val threshold = 20.0 // 20米容差
191
+ val linePoints = line.points
192
+ if (linePoints.size < 2) return false
193
+
194
+ for (i in 0 until linePoints.size - 1) {
195
+ val distance = distanceToSegment(latLng, linePoints[i], linePoints[i + 1])
196
+ if (distance <= threshold) {
197
+ onPress(mapOf(
198
+ "latitude" to latLng.latitude,
199
+ "longitude" to latLng.longitude
200
+ ))
201
+ return true
172
202
  }
173
203
  }
174
204
  }
205
+ return false
206
+ }
207
+
208
+ private fun distanceToSegment(point: LatLng, start: LatLng, end: LatLng): Double {
209
+ val p = android.location.Location("").apply {
210
+ latitude = point.latitude
211
+ longitude = point.longitude
212
+ }
213
+ val a = android.location.Location("").apply {
214
+ latitude = start.latitude
215
+ longitude = start.longitude
216
+ }
217
+ val b = android.location.Location("").apply {
218
+ latitude = end.latitude
219
+ longitude = end.longitude
220
+ }
221
+
222
+ val ab = a.distanceTo(b).toDouble()
223
+ if (ab == 0.0) return a.distanceTo(p).toDouble()
224
+
225
+ val t = maxOf(0.0, minOf(1.0,
226
+ ((point.latitude - start.latitude) * (end.latitude - start.latitude) +
227
+ (point.longitude - start.longitude) * (end.longitude - start.longitude)) / (ab * ab)
228
+ ))
229
+
230
+ val projection = LatLng(
231
+ start.latitude + t * (end.latitude - start.latitude),
232
+ start.longitude + t * (end.longitude - start.longitude)
233
+ )
234
+
235
+ val proj = android.location.Location("").apply {
236
+ latitude = projection.latitude
237
+ longitude = projection.longitude
238
+ }
239
+
240
+ return p.distanceTo(proj).toDouble()
175
241
  }
176
242
 
177
243
  /**
@@ -27,6 +27,26 @@ declare class CircleEventManager {
27
27
  trigger(circleId: string, eventType: keyof CircleEventCallbacks): void;
28
28
  }
29
29
  export declare const CircleEventContext: React.Context<CircleEventManager | null>;
30
+ type PolygonEventCallbacks = {
31
+ onPress?: () => void;
32
+ };
33
+ declare class PolygonEventManager {
34
+ private callbacks;
35
+ register(polygonId: string, callbacks: PolygonEventCallbacks): void;
36
+ unregister(polygonId: string): void;
37
+ trigger(polygonId: string, eventType: keyof PolygonEventCallbacks): void;
38
+ }
39
+ export declare const PolygonEventContext: React.Context<PolygonEventManager | null>;
40
+ type PolylineEventCallbacks = {
41
+ onPress?: () => void;
42
+ };
43
+ declare class PolylineEventManager {
44
+ private callbacks;
45
+ register(polylineId: string, callbacks: PolylineEventCallbacks): void;
46
+ unregister(polylineId: string): void;
47
+ trigger(polylineId: string, eventType: keyof PolylineEventCallbacks): void;
48
+ }
49
+ export declare const PolylineEventContext: React.Context<PolylineEventManager | null>;
30
50
  /**
31
51
  * 高德地图视图组件,提供地图操作API和覆盖物管理功能
32
52
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoGaodeMapView.d.ts","sourceRoot":"","sources":["../src/ExpoGaodeMapView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EAGV,MAAM,EAMP,MAAM,SAAS,CAAC;AAGjB,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAK1C,eAAO,MAAM,UAAU,0DAAuE,CAAC;AAG/F,KAAK,oBAAoB,GAAG;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,cAAM,kBAAkB;IACtB,OAAO,CAAC,SAAS,CAA2C;IAE5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB;IAI1D,UAAU,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,oBAAoB,EAAE,IAAI,CAAC,EAAE,GAAG;CAM5E;AAED,eAAO,MAAM,kBAAkB,0CAAuD,CAAC;AAGvF,KAAK,oBAAoB,GAAG;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,cAAM,kBAAkB;IACtB,OAAO,CAAC,SAAS,CAA2C;IAE5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB;IAI1D,UAAU,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,oBAAoB;CAMhE;AAED,eAAO,MAAM,kBAAkB,0CAAuD,CAAC;AAEvF;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,gBAAgB,iFA4QpB,CAAC;AAIH,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"ExpoGaodeMapView.d.ts","sourceRoot":"","sources":["../src/ExpoGaodeMapView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EAGV,MAAM,EAMP,MAAM,SAAS,CAAC;AAGjB,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAK1C,eAAO,MAAM,UAAU,0DAAuE,CAAC;AAG/F,KAAK,oBAAoB,GAAG;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,cAAM,kBAAkB;IACtB,OAAO,CAAC,SAAS,CAA2C;IAE5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB;IAI1D,UAAU,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,oBAAoB,EAAE,IAAI,CAAC,EAAE,GAAG;CAM5E;AAED,eAAO,MAAM,kBAAkB,0CAAuD,CAAC;AAGvF,KAAK,oBAAoB,GAAG;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,cAAM,kBAAkB;IACtB,OAAO,CAAC,SAAS,CAA2C;IAE5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB;IAI1D,UAAU,CAAC,QAAQ,EAAE,MAAM;IAI3B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,oBAAoB;CAMhE;AAED,eAAO,MAAM,kBAAkB,0CAAuD,CAAC;AAGvF,KAAK,qBAAqB,GAAG;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,cAAM,mBAAmB;IACvB,OAAO,CAAC,SAAS,CAA4C;IAE7D,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,qBAAqB;IAI5D,UAAU,CAAC,SAAS,EAAE,MAAM;IAI5B,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,qBAAqB;CAMlE;AAED,eAAO,MAAM,mBAAmB,2CAAwD,CAAC;AAGzF,KAAK,sBAAsB,GAAG;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,cAAM,oBAAoB;IACxB,OAAO,CAAC,SAAS,CAA6C;IAE9D,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,sBAAsB;IAI9D,UAAU,CAAC,UAAU,EAAE,MAAM;IAI7B,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,sBAAsB;CAMpE;AAED,eAAO,MAAM,oBAAoB,4CAAyD,CAAC;AAE3F;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,gBAAgB,iFAoSpB,CAAC;AAIH,eAAe,gBAAgB,CAAC"}