expo-gaode-map 1.0.1 → 1.0.3
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/README.md +1 -0
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +17 -1
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +52 -5
- package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +184 -6
- package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +24 -51
- package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerView.kt +3 -0
- package/build/ExpoGaodeMap.types.d.ts.map +1 -1
- package/build/ExpoGaodeMap.types.js +0 -10
- package/build/ExpoGaodeMap.types.js.map +1 -1
- package/build/ExpoGaodeMapModule.d.ts.map +1 -1
- package/build/ExpoGaodeMapModule.js +0 -10
- package/build/ExpoGaodeMapModule.js.map +1 -1
- package/build/ExpoGaodeMapView.d.ts +39 -20
- package/build/ExpoGaodeMapView.d.ts.map +1 -1
- package/build/ExpoGaodeMapView.js +215 -31
- package/build/ExpoGaodeMapView.js.map +1 -1
- package/build/components/overlays/Circle.d.ts +0 -15
- package/build/components/overlays/Circle.d.ts.map +1 -1
- package/build/components/overlays/Circle.js +28 -46
- package/build/components/overlays/Circle.js.map +1 -1
- package/build/components/overlays/Cluster.d.ts +3 -15
- package/build/components/overlays/Cluster.d.ts.map +1 -1
- package/build/components/overlays/Cluster.js +3 -25
- package/build/components/overlays/Cluster.js.map +1 -1
- package/build/components/overlays/HeatMap.d.ts +3 -14
- package/build/components/overlays/HeatMap.d.ts.map +1 -1
- package/build/components/overlays/HeatMap.js +3 -24
- package/build/components/overlays/HeatMap.js.map +1 -1
- package/build/components/overlays/Marker.d.ts +2 -15
- package/build/components/overlays/Marker.d.ts.map +1 -1
- package/build/components/overlays/Marker.js +60 -46
- package/build/components/overlays/Marker.js.map +1 -1
- package/build/components/overlays/MultiPoint.d.ts +3 -14
- package/build/components/overlays/MultiPoint.d.ts.map +1 -1
- package/build/components/overlays/MultiPoint.js +3 -24
- package/build/components/overlays/MultiPoint.js.map +1 -1
- package/build/components/overlays/Polygon.d.ts +13 -16
- package/build/components/overlays/Polygon.d.ts.map +1 -1
- package/build/components/overlays/Polygon.js +41 -75
- package/build/components/overlays/Polygon.js.map +1 -1
- package/build/components/overlays/Polyline.d.ts +12 -14
- package/build/components/overlays/Polyline.d.ts.map +1 -1
- package/build/components/overlays/Polyline.js +34 -35
- package/build/components/overlays/Polyline.js.map +1 -1
- package/build/components/overlays/index.d.ts.map +1 -1
- package/build/components/overlays/index.js +0 -10
- package/build/components/overlays/index.js.map +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +0 -10
- package/build/index.js.map +1 -1
- package/build/modules/AMapLocation.d.ts +47 -10
- package/build/modules/AMapLocation.d.ts.map +1 -1
- package/build/modules/AMapLocation.js +48 -20
- package/build/modules/AMapLocation.js.map +1 -1
- package/build/modules/AMapPermissions.d.ts +3 -1
- package/build/modules/AMapPermissions.d.ts.map +1 -1
- package/build/modules/AMapPermissions.js +3 -11
- package/build/modules/AMapPermissions.js.map +1 -1
- package/build/modules/AMapSDK.d.ts +5 -4
- package/build/modules/AMapSDK.d.ts.map +1 -1
- package/build/modules/AMapSDK.js +5 -14
- package/build/modules/AMapSDK.js.map +1 -1
- package/build/modules/AMapView.d.ts.map +1 -1
- package/build/modules/AMapView.js +0 -8
- package/build/modules/AMapView.js.map +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +0 -10
- package/build/types/index.js.map +1 -1
- package/build/types/map-view.types.d.ts +30 -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 +25 -1
- package/build/types/overlays.types.d.ts.map +1 -1
- package/build/types/overlays.types.js.map +1 -1
- package/docs/API.md +40 -0
- package/docs/EXAMPLES.md +86 -2
- package/docs/RELEASE_GUIDE.md +178 -0
- package/expo-module.config.json +1 -1
- package/ios/ExpoGaodeMapModule.swift +42 -14
- package/ios/ExpoGaodeMapView.swift +210 -7
- package/ios/managers/OverlayManager.swift +78 -10
- package/ios/overlays/CircleView.swift +41 -12
- package/ios/overlays/MarkerView.swift +55 -3
- package/ios/overlays/PolygonView.swift +25 -5
- package/ios/overlays/PolylineView.swift +23 -4
- package/ios/utils/ColorParser.swift +0 -5
- package/package.json +1 -1
- package/src/ExpoGaodeMap.types.ts +1 -10
- package/src/ExpoGaodeMapModule.ts +1 -10
- package/src/ExpoGaodeMapView.tsx +257 -38
- package/src/components/overlays/Circle.tsx +32 -50
- package/src/components/overlays/Cluster.tsx +4 -26
- package/src/components/overlays/HeatMap.tsx +4 -25
- package/src/components/overlays/Marker.tsx +69 -52
- package/src/components/overlays/MultiPoint.tsx +4 -25
- package/src/components/overlays/Polygon.tsx +48 -78
- package/src/components/overlays/Polyline.tsx +41 -38
- package/src/components/overlays/index.ts +0 -11
- package/src/index.ts +0 -11
- package/src/modules/AMapLocation.ts +56 -20
- package/src/modules/AMapPermissions.ts +4 -11
- package/src/modules/AMapSDK.ts +7 -14
- package/src/modules/AMapView.ts +0 -8
- package/src/types/index.ts +1 -10
- package/src/types/map-view.types.ts +25 -0
- package/src/types/overlays.types.ts +30 -1
package/README.md
CHANGED
|
@@ -271,7 +271,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
271
271
|
View(ExpoGaodeMapView::class) {
|
|
272
272
|
|
|
273
273
|
// 事件
|
|
274
|
-
Events("onMapPress", "onMapLongPress", "onLoad")
|
|
274
|
+
Events("onMapPress", "onMapLongPress", "onLoad", "onMarkerPress", "onMarkerDragStart", "onMarkerDrag", "onMarkerDragEnd", "onCirclePress")
|
|
275
275
|
|
|
276
276
|
// 地图类型
|
|
277
277
|
Prop<Int>("mapType") { view, type ->
|
|
@@ -416,6 +416,22 @@ class ExpoGaodeMapModule : Module() {
|
|
|
416
416
|
Prop<Boolean>("draggable") { view: MarkerView, draggable ->
|
|
417
417
|
view.setDraggable(draggable)
|
|
418
418
|
}
|
|
419
|
+
|
|
420
|
+
Prop<Float>("opacity") { view: MarkerView, opacity ->
|
|
421
|
+
view.setOpacity(opacity)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
Prop<Boolean>("flat") { view: MarkerView, flat ->
|
|
425
|
+
view.setFlat(flat)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
Prop<Float>("zIndex") { view: MarkerView, zIndex ->
|
|
429
|
+
view.setZIndex(zIndex)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
Prop<Map<String, Float>>("anchor") { view: MarkerView, anchor ->
|
|
433
|
+
view.setAnchor(anchor)
|
|
434
|
+
}
|
|
419
435
|
}
|
|
420
436
|
|
|
421
437
|
// Circle - 圆形
|
|
@@ -45,6 +45,11 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
45
45
|
private val onMapPress by EventDispatcher()
|
|
46
46
|
private val onMapLongPress by EventDispatcher()
|
|
47
47
|
private val onLoad by EventDispatcher()
|
|
48
|
+
private val onMarkerPress by EventDispatcher()
|
|
49
|
+
private val onMarkerDragStart by EventDispatcher()
|
|
50
|
+
private val onMarkerDrag by EventDispatcher()
|
|
51
|
+
private val onMarkerDragEnd by EventDispatcher()
|
|
52
|
+
private val onCirclePress by EventDispatcher()
|
|
48
53
|
|
|
49
54
|
// 高德地图视图
|
|
50
55
|
private lateinit var mapView: MapView
|
|
@@ -73,7 +78,43 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
73
78
|
// 初始化管理器
|
|
74
79
|
cameraManager = CameraManager(aMap)
|
|
75
80
|
uiManager = UIManager(aMap, context)
|
|
76
|
-
overlayManager = OverlayManager(aMap)
|
|
81
|
+
overlayManager = OverlayManager(aMap, context).apply {
|
|
82
|
+
onMarkerPress = { id, lat, lng ->
|
|
83
|
+
this@ExpoGaodeMapView.onMarkerPress(mapOf(
|
|
84
|
+
"markerId" to id,
|
|
85
|
+
"latitude" to lat,
|
|
86
|
+
"longitude" to lng
|
|
87
|
+
))
|
|
88
|
+
}
|
|
89
|
+
onMarkerDragStart = { id, lat, lng ->
|
|
90
|
+
this@ExpoGaodeMapView.onMarkerDragStart(mapOf(
|
|
91
|
+
"markerId" to id,
|
|
92
|
+
"latitude" to lat,
|
|
93
|
+
"longitude" to lng
|
|
94
|
+
))
|
|
95
|
+
}
|
|
96
|
+
onMarkerDrag = { id, lat, lng ->
|
|
97
|
+
this@ExpoGaodeMapView.onMarkerDrag(mapOf(
|
|
98
|
+
"markerId" to id,
|
|
99
|
+
"latitude" to lat,
|
|
100
|
+
"longitude" to lng
|
|
101
|
+
))
|
|
102
|
+
}
|
|
103
|
+
onMarkerDragEnd = { id, lat, lng ->
|
|
104
|
+
this@ExpoGaodeMapView.onMarkerDragEnd(mapOf(
|
|
105
|
+
"markerId" to id,
|
|
106
|
+
"latitude" to lat,
|
|
107
|
+
"longitude" to lng
|
|
108
|
+
))
|
|
109
|
+
}
|
|
110
|
+
onCirclePress = { id, lat, lng ->
|
|
111
|
+
this@ExpoGaodeMapView.onCirclePress(mapOf(
|
|
112
|
+
"circleId" to id,
|
|
113
|
+
"latitude" to lat,
|
|
114
|
+
"longitude" to lng
|
|
115
|
+
))
|
|
116
|
+
}
|
|
117
|
+
}
|
|
77
118
|
|
|
78
119
|
// 添加地图视图到布局
|
|
79
120
|
addView(mapView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
|
|
@@ -108,10 +149,16 @@ class ExpoGaodeMapView(context: Context, appContext: AppContext) : ExpoView(cont
|
|
|
108
149
|
*/
|
|
109
150
|
private fun setupMapListeners() {
|
|
110
151
|
aMap.setOnMapClickListener { latLng ->
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
152
|
+
// 先检查是否点击了圆形
|
|
153
|
+
val circleId = overlayManager.checkCirclePress(latLng)
|
|
154
|
+
if (circleId != null) {
|
|
155
|
+
overlayManager.onCirclePress?.invoke(circleId, latLng.latitude, latLng.longitude)
|
|
156
|
+
} else {
|
|
157
|
+
onMapPress(mapOf(
|
|
158
|
+
"latitude" to latLng.latitude,
|
|
159
|
+
"longitude" to latLng.longitude
|
|
160
|
+
))
|
|
161
|
+
}
|
|
115
162
|
}
|
|
116
163
|
|
|
117
164
|
aMap.setOnMapLongClickListener { latLng ->
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package expo.modules.gaodemap.managers
|
|
2
2
|
|
|
3
|
+
import android.content.Context
|
|
3
4
|
import android.util.Log
|
|
5
|
+
import android.graphics.Bitmap
|
|
4
6
|
import android.graphics.BitmapFactory
|
|
5
7
|
import com.amap.api.maps.AMap
|
|
6
8
|
import com.amap.api.maps.model.LatLng
|
|
@@ -12,7 +14,7 @@ import java.net.URL
|
|
|
12
14
|
* 覆盖物管理器
|
|
13
15
|
* 负责地图上所有覆盖物的添加、删除、更新
|
|
14
16
|
*/
|
|
15
|
-
class OverlayManager(private val aMap: AMap) {
|
|
17
|
+
class OverlayManager(private val aMap: AMap, private val context: Context) {
|
|
16
18
|
|
|
17
19
|
companion object {
|
|
18
20
|
private const val TAG = "OverlayManager"
|
|
@@ -24,6 +26,21 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
24
26
|
private val polylines = mutableMapOf<String, com.amap.api.maps.model.Polyline>()
|
|
25
27
|
private val polygons = mutableMapOf<String, com.amap.api.maps.model.Polygon>()
|
|
26
28
|
|
|
29
|
+
// Marker ID 映射
|
|
30
|
+
private val markerIdMap = mutableMapOf<com.amap.api.maps.model.Marker, String>()
|
|
31
|
+
|
|
32
|
+
// Circle ID 映射
|
|
33
|
+
private val circleIdMap = mutableMapOf<com.amap.api.maps.model.Circle, String>()
|
|
34
|
+
|
|
35
|
+
// 事件回调
|
|
36
|
+
var onMarkerPress: ((String, Double, Double) -> Unit)? = null
|
|
37
|
+
var onMarkerDragStart: ((String, Double, Double) -> Unit)? = null
|
|
38
|
+
var onMarkerDrag: ((String, Double, Double) -> Unit)? = null
|
|
39
|
+
var onMarkerDragEnd: ((String, Double, Double) -> Unit)? = null
|
|
40
|
+
var onCirclePress: ((String, Double, Double) -> Unit)? = null
|
|
41
|
+
|
|
42
|
+
private val mainHandler = android.os.Handler(android.os.Looper.getMainLooper())
|
|
43
|
+
|
|
27
44
|
// ==================== 圆形覆盖物 ====================
|
|
28
45
|
|
|
29
46
|
fun addCircle(id: String, props: Map<String, Any>) {
|
|
@@ -49,11 +66,13 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
49
66
|
|
|
50
67
|
val circle = aMap.addCircle(options)
|
|
51
68
|
circles[id] = circle
|
|
69
|
+
circleIdMap[circle] = id
|
|
52
70
|
}
|
|
53
71
|
}
|
|
54
72
|
|
|
55
73
|
fun removeCircle(id: String) {
|
|
56
74
|
circles[id]?.let { circle ->
|
|
75
|
+
circleIdMap.remove(circle)
|
|
57
76
|
circle.remove()
|
|
58
77
|
circles.remove(id)
|
|
59
78
|
}
|
|
@@ -84,11 +103,22 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
84
103
|
// ==================== 标记点 ====================
|
|
85
104
|
|
|
86
105
|
fun addMarker(id: String, props: Map<String, Any>) {
|
|
106
|
+
Log.d(TAG, "addMarker 调用 - ID: $id")
|
|
107
|
+
Log.d(TAG, "addMarker props: $props")
|
|
87
108
|
|
|
88
109
|
@Suppress("UNCHECKED_CAST")
|
|
89
110
|
val position = props["position"] as? Map<String, Double>
|
|
90
111
|
val title = props["title"] as? String
|
|
112
|
+
val snippet = props["snippet"] as? String
|
|
91
113
|
val draggable = props["draggable"] as? Boolean ?: false
|
|
114
|
+
val icon = props["icon"]
|
|
115
|
+
// 将 RN 的点(points)转换为 Android 的 dp
|
|
116
|
+
val iconWidth = dpToPx((props["iconWidth"] as? Number)?.toFloat() ?: 40f)
|
|
117
|
+
val iconHeight = dpToPx((props["iconHeight"] as? Number)?.toFloat() ?: 40f)
|
|
118
|
+
val opacity = (props["opacity"] as? Number)?.toFloat() ?: 1.0f
|
|
119
|
+
val flat = props["flat"] as? Boolean ?: false
|
|
120
|
+
val zIndex = (props["zIndex"] as? Number)?.toFloat() ?: 0f
|
|
121
|
+
val anchor = props["anchor"] as? Map<String, Double>
|
|
92
122
|
|
|
93
123
|
if (position != null) {
|
|
94
124
|
val lat = position["latitude"] ?: 0.0
|
|
@@ -98,21 +128,115 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
98
128
|
val options = com.amap.api.maps.model.MarkerOptions()
|
|
99
129
|
.position(latLng)
|
|
100
130
|
.draggable(draggable)
|
|
131
|
+
.setFlat(flat)
|
|
132
|
+
.zIndex(zIndex)
|
|
101
133
|
|
|
102
134
|
title?.let { options.title(it) }
|
|
135
|
+
snippet?.let { options.snippet(it) }
|
|
136
|
+
|
|
137
|
+
anchor?.let {
|
|
138
|
+
val x = (it["x"] as? Number)?.toFloat() ?: 0.5f
|
|
139
|
+
val y = (it["y"] as? Number)?.toFloat() ?: 1.0f
|
|
140
|
+
options.anchor(x, y)
|
|
141
|
+
}
|
|
103
142
|
|
|
104
143
|
val marker = aMap.addMarker(options)
|
|
144
|
+
marker?.alpha = opacity
|
|
105
145
|
|
|
106
|
-
|
|
107
|
-
|
|
146
|
+
markers[id] = marker
|
|
147
|
+
marker?.let { markerIdMap[it] = id }
|
|
148
|
+
|
|
149
|
+
// 加载自定义图标
|
|
150
|
+
icon?.let {
|
|
151
|
+
val uri = when (it) {
|
|
152
|
+
is String -> it
|
|
153
|
+
is Map<*, *> -> it["uri"] as? String
|
|
154
|
+
else -> null
|
|
155
|
+
}
|
|
156
|
+
uri?.let { iconUri ->
|
|
157
|
+
loadMarkerIcon(iconUri, iconWidth, iconHeight) { bitmap ->
|
|
158
|
+
mainHandler.post {
|
|
159
|
+
marker?.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap))
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
108
163
|
}
|
|
109
164
|
|
|
110
|
-
|
|
165
|
+
// 设置事件监听器(只设置一次)
|
|
166
|
+
setupMarkerListeners()
|
|
111
167
|
}
|
|
112
168
|
}
|
|
113
169
|
|
|
170
|
+
private fun setupMarkerListeners() {
|
|
171
|
+
aMap.setOnMarkerClickListener { marker ->
|
|
172
|
+
markerIdMap[marker]?.let { id ->
|
|
173
|
+
onMarkerPress?.invoke(id, marker.position.latitude, marker.position.longitude)
|
|
174
|
+
}
|
|
175
|
+
false // 返回 false 允许显示 InfoWindow
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
aMap.setOnMarkerDragListener(object : AMap.OnMarkerDragListener {
|
|
179
|
+
override fun onMarkerDragStart(marker: com.amap.api.maps.model.Marker?) {
|
|
180
|
+
marker?.let { m ->
|
|
181
|
+
markerIdMap[m]?.let { id ->
|
|
182
|
+
onMarkerDragStart?.invoke(id, m.position.latitude, m.position.longitude)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
override fun onMarkerDrag(marker: com.amap.api.maps.model.Marker?) {
|
|
188
|
+
marker?.let { m ->
|
|
189
|
+
markerIdMap[m]?.let { id ->
|
|
190
|
+
onMarkerDrag?.invoke(id, m.position.latitude, m.position.longitude)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
override fun onMarkerDragEnd(marker: com.amap.api.maps.model.Marker?) {
|
|
196
|
+
marker?.let { m ->
|
|
197
|
+
markerIdMap[m]?.let { id ->
|
|
198
|
+
onMarkerDragEnd?.invoke(id, m.position.latitude, m.position.longitude)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private fun loadMarkerIcon(uri: String, width: Int, height: Int, callback: (Bitmap) -> Unit) {
|
|
206
|
+
Thread {
|
|
207
|
+
try {
|
|
208
|
+
Log.d(TAG, "开始加载图标: $uri")
|
|
209
|
+
val bitmap = when {
|
|
210
|
+
uri.startsWith("http://") || uri.startsWith("https://") -> {
|
|
211
|
+
Log.d(TAG, "加载网络图片")
|
|
212
|
+
BitmapFactory.decodeStream(URL(uri).openStream())
|
|
213
|
+
}
|
|
214
|
+
uri.startsWith("file://") -> {
|
|
215
|
+
Log.d(TAG, "加载本地文件")
|
|
216
|
+
BitmapFactory.decodeFile(uri.substring(7))
|
|
217
|
+
}
|
|
218
|
+
else -> {
|
|
219
|
+
Log.d(TAG, "未知 URI 格式")
|
|
220
|
+
null
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (bitmap == null) {
|
|
225
|
+
Log.e(TAG, "图标加载失败: bitmap 为 null")
|
|
226
|
+
} else {
|
|
227
|
+
Log.d(TAG, "图标加载成功: ${bitmap.width}x${bitmap.height}")
|
|
228
|
+
val resized = Bitmap.createScaledBitmap(bitmap, width, height, true)
|
|
229
|
+
callback(resized)
|
|
230
|
+
}
|
|
231
|
+
} catch (e: Exception) {
|
|
232
|
+
Log.e(TAG, "图标加载异常: ${e.message}", e)
|
|
233
|
+
}
|
|
234
|
+
}.start()
|
|
235
|
+
}
|
|
236
|
+
|
|
114
237
|
fun removeMarker(id: String) {
|
|
115
238
|
markers[id]?.let { marker ->
|
|
239
|
+
markerIdMap.remove(marker)
|
|
116
240
|
marker.remove()
|
|
117
241
|
markers.remove(id)
|
|
118
242
|
}
|
|
@@ -123,7 +247,15 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
123
247
|
@Suppress("UNCHECKED_CAST")
|
|
124
248
|
val position = props["position"] as? Map<String, Double>
|
|
125
249
|
val title = props["title"] as? String
|
|
250
|
+
val snippet = props["snippet"] as? String
|
|
126
251
|
val draggable = props["draggable"] as? Boolean
|
|
252
|
+
val icon = props["icon"]
|
|
253
|
+
val iconWidth = dpToPx((props["iconWidth"] as? Number)?.toFloat() ?: 40f)
|
|
254
|
+
val iconHeight = dpToPx((props["iconHeight"] as? Number)?.toFloat() ?: 40f)
|
|
255
|
+
val opacity = props["opacity"] as? Number
|
|
256
|
+
val flat = props["flat"] as? Boolean
|
|
257
|
+
val zIndex = props["zIndex"] as? Number
|
|
258
|
+
val anchor = props["anchor"] as? Map<String, Double>
|
|
127
259
|
|
|
128
260
|
position?.let {
|
|
129
261
|
val lat = it["latitude"] ?: 0.0
|
|
@@ -132,7 +264,32 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
132
264
|
}
|
|
133
265
|
|
|
134
266
|
title?.let { marker.title = it }
|
|
267
|
+
snippet?.let { marker.snippet = it }
|
|
135
268
|
draggable?.let { marker.isDraggable = it }
|
|
269
|
+
opacity?.let { marker.alpha = it.toFloat() }
|
|
270
|
+
flat?.let { marker.isFlat = it }
|
|
271
|
+
zIndex?.let { marker.zIndex = it.toFloat() }
|
|
272
|
+
|
|
273
|
+
anchor?.let {
|
|
274
|
+
val x = (it["x"] as? Number)?.toFloat() ?: 0.5f
|
|
275
|
+
val y = (it["y"] as? Number)?.toFloat() ?: 1.0f
|
|
276
|
+
marker.setAnchor(x, y)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
icon?.let {
|
|
280
|
+
val uri = when (it) {
|
|
281
|
+
is String -> it
|
|
282
|
+
is Map<*, *> -> it["uri"] as? String
|
|
283
|
+
else -> null
|
|
284
|
+
}
|
|
285
|
+
uri?.let { iconUri ->
|
|
286
|
+
loadMarkerIcon(iconUri, iconWidth, iconHeight) { bitmap ->
|
|
287
|
+
mainHandler.post {
|
|
288
|
+
marker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap))
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
136
293
|
}
|
|
137
294
|
}
|
|
138
295
|
|
|
@@ -142,12 +299,12 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
142
299
|
|
|
143
300
|
@Suppress("UNCHECKED_CAST")
|
|
144
301
|
val points = props["points"] as? List<Map<String, Double>>
|
|
145
|
-
val width = (props["strokeWidth"] as? Number)?.toFloat() ?: 10f
|
|
302
|
+
val width = (props["width"] as? Number)?.toFloat() ?: (props["strokeWidth"] as? Number)?.toFloat() ?: 10f
|
|
146
303
|
val texture = props["texture"] as? String
|
|
147
304
|
val color = if (!texture.isNullOrEmpty()) {
|
|
148
305
|
android.graphics.Color.TRANSPARENT
|
|
149
306
|
} else {
|
|
150
|
-
ColorParser.parseColor(props["strokeColor"])
|
|
307
|
+
ColorParser.parseColor(props["color"] ?: props["strokeColor"])
|
|
151
308
|
}
|
|
152
309
|
|
|
153
310
|
if (points != null && points.size >= 2) {
|
|
@@ -287,9 +444,22 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
287
444
|
/**
|
|
288
445
|
* 清理所有覆盖物
|
|
289
446
|
*/
|
|
447
|
+
/**
|
|
448
|
+
* 检查点击位置是否在某个圆形内
|
|
449
|
+
*/
|
|
450
|
+
fun checkCirclePress(latLng: LatLng): String? {
|
|
451
|
+
for ((circle, id) in circleIdMap) {
|
|
452
|
+
if (circle.contains(latLng)) {
|
|
453
|
+
return id
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return null
|
|
457
|
+
}
|
|
458
|
+
|
|
290
459
|
fun clear() {
|
|
291
460
|
circles.values.forEach { it.remove() }
|
|
292
461
|
circles.clear()
|
|
462
|
+
circleIdMap.clear()
|
|
293
463
|
|
|
294
464
|
markers.values.forEach { it.remove() }
|
|
295
465
|
markers.clear()
|
|
@@ -300,4 +470,12 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
300
470
|
polygons.values.forEach { it.remove() }
|
|
301
471
|
polygons.clear()
|
|
302
472
|
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* 将 dp 转换为 px
|
|
476
|
+
*/
|
|
477
|
+
private fun dpToPx(dp: Float): Int {
|
|
478
|
+
val density = context.resources.displayMetrics.density
|
|
479
|
+
return (dp * density + 0.5f).toInt()
|
|
480
|
+
}
|
|
303
481
|
}
|
|
@@ -19,6 +19,9 @@ class CircleView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
19
19
|
private var aMap: AMap? = null
|
|
20
20
|
private var center: LatLng? = null
|
|
21
21
|
private var radius: Double = 1000.0
|
|
22
|
+
private var fillColor: Int = Color.argb(50, 0, 0, 255)
|
|
23
|
+
private var strokeColor: Int = Color.BLUE
|
|
24
|
+
private var strokeWidth: Float = 10f
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
27
|
* 设置地图实例
|
|
@@ -26,28 +29,19 @@ class CircleView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
26
29
|
@Suppress("unused")
|
|
27
30
|
fun setMap(map: AMap) {
|
|
28
31
|
aMap = map
|
|
29
|
-
//
|
|
32
|
+
// 延迟创建圆形,确保所有 props 都已设置
|
|
33
|
+
post { createOrUpdateCircle() }
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
/**
|
|
33
37
|
* 设置圆心
|
|
34
38
|
*/
|
|
35
39
|
fun setCenter(centerMap: Map<String, Double>) {
|
|
36
|
-
android.util.Log.d("CircleView", "setCenter 被调用: $centerMap")
|
|
37
40
|
val lat = centerMap["latitude"]
|
|
38
41
|
val lng = centerMap["longitude"]
|
|
39
42
|
if (lat != null && lng != null) {
|
|
40
43
|
center = LatLng(lat, lng)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// 如果圆形已存在,更新它;否则创建新圆形
|
|
44
|
-
circle?.let {
|
|
45
|
-
android.util.Log.d("CircleView", "更新现有圆形的圆心")
|
|
46
|
-
it.center = center
|
|
47
|
-
} ?: run {
|
|
48
|
-
android.util.Log.d("CircleView", "圆形不存在,尝试创建")
|
|
49
|
-
createOrUpdateCircle()
|
|
50
|
-
}
|
|
44
|
+
circle?.center = center
|
|
51
45
|
}
|
|
52
46
|
}
|
|
53
47
|
|
|
@@ -56,77 +50,56 @@ class CircleView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
56
50
|
*/
|
|
57
51
|
fun setRadius(radiusValue: Double) {
|
|
58
52
|
radius = radiusValue
|
|
59
|
-
circle?.
|
|
60
|
-
it.radius = radius
|
|
61
|
-
}
|
|
62
|
-
// 半径可以后续更新,不需要在这里创建圆形
|
|
53
|
+
circle?.radius = radius
|
|
63
54
|
}
|
|
64
55
|
|
|
65
56
|
/**
|
|
66
57
|
* 设置填充颜色
|
|
67
58
|
*/
|
|
68
59
|
fun setFillColor(color: Int) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
60
|
+
fillColor = color
|
|
61
|
+
circle?.fillColor = color
|
|
72
62
|
}
|
|
73
63
|
|
|
74
64
|
/**
|
|
75
65
|
* 设置边框颜色
|
|
76
66
|
*/
|
|
77
67
|
fun setStrokeColor(color: Int) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
68
|
+
strokeColor = color
|
|
69
|
+
circle?.strokeColor = color
|
|
81
70
|
}
|
|
82
71
|
|
|
83
72
|
/**
|
|
84
73
|
* 设置边框宽度
|
|
85
74
|
*/
|
|
86
75
|
fun setStrokeWidth(width: Float) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
76
|
+
strokeWidth = width
|
|
77
|
+
circle?.strokeWidth = width
|
|
90
78
|
}
|
|
91
79
|
|
|
92
80
|
/**
|
|
93
81
|
* 设置 z-index
|
|
94
82
|
*/
|
|
95
83
|
fun setZIndex(zIndex: Float) {
|
|
96
|
-
circle?.
|
|
97
|
-
it.zIndex = zIndex
|
|
98
|
-
} ?: createOrUpdateCircle()
|
|
84
|
+
circle?.zIndex = zIndex
|
|
99
85
|
}
|
|
100
86
|
|
|
101
87
|
/**
|
|
102
88
|
* 创建或更新圆形
|
|
103
89
|
*/
|
|
104
90
|
private fun createOrUpdateCircle() {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// 必须同时有地图实例和圆心才能创建
|
|
109
|
-
val map = aMap ?: run {
|
|
110
|
-
android.util.Log.w("CircleView", "⚠️ aMap 为 null,无法创建圆形")
|
|
111
|
-
return
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
val centerPoint = center ?: run {
|
|
115
|
-
android.util.Log.w("CircleView", "⚠️ center 为 null,无法创建圆形")
|
|
116
|
-
return
|
|
117
|
-
}
|
|
91
|
+
val map = aMap ?: return
|
|
92
|
+
val centerPoint = center ?: return
|
|
118
93
|
|
|
119
94
|
if (circle == null) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
circle = map.addCircle(options)
|
|
129
|
-
android.util.Log.d("CircleView", "✅ 圆形创建成功: $circle")
|
|
95
|
+
circle = map.addCircle(
|
|
96
|
+
CircleOptions()
|
|
97
|
+
.center(centerPoint)
|
|
98
|
+
.radius(radius)
|
|
99
|
+
.fillColor(fillColor)
|
|
100
|
+
.strokeColor(strokeColor)
|
|
101
|
+
.strokeWidth(strokeWidth)
|
|
102
|
+
)
|
|
130
103
|
}
|
|
131
104
|
}
|
|
132
105
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
package expo.modules.gaodemap.overlays
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.graphics.Canvas
|
|
6
|
+
import android.view.View
|
|
4
7
|
import com.amap.api.maps.AMap
|
|
5
8
|
import com.amap.api.maps.model.BitmapDescriptorFactory
|
|
6
9
|
import com.amap.api.maps.model.LatLng
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoGaodeMap.types.d.ts","sourceRoot":"","sources":["../src/ExpoGaodeMap.types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoGaodeMap.types.d.ts","sourceRoot":"","sources":["../src/ExpoGaodeMap.types.ts"],"names":[],"mappings":"AAGA,cAAc,SAAS,CAAC;AAGxB,YAAY,EAEV,MAAM,EACN,KAAK,EACL,cAAc,EACd,YAAY,EACZ,MAAM,EAGN,YAAY,EACZ,WAAW,EAGX,WAAW,EACX,SAAS,EACT,eAAe,EAGf,WAAW,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,gBAAgB,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAE1C;;OAEG;IACH,eAAe,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACrE,CAAC;AAEF;;GAEG;AACH,YAAY,EAAE,YAAY,IAAI,qBAAqB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
3
|
-
* @Date : 2025-11-13 14:03:56
|
|
4
|
-
* @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
5
|
-
* @LastEditTime : 2025-11-13 14:30:00
|
|
6
|
-
* @FilePath : /expo-gaode-map/src/ExpoGaodeMap.types.ts
|
|
7
|
-
* @Description : 高德地图 Expo Module 主类型定义文件
|
|
8
|
-
*
|
|
9
|
-
* Copyright (c) 2025 by 尚博信_王强, All Rights Reserved.
|
|
10
|
-
*/
|
|
11
1
|
// 导出所有类型定义
|
|
12
2
|
export * from './types';
|
|
13
3
|
export { MapType, LocationMode, LocationAccuracy, CoordinateType, } from './types';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoGaodeMap.types.js","sourceRoot":"","sources":["../src/ExpoGaodeMap.types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoGaodeMap.types.js","sourceRoot":"","sources":["../src/ExpoGaodeMap.types.ts"],"names":[],"mappings":"AAEA,WAAW;AACX,cAAc,SAAS,CAAC;AA8BxB,OAAO,EACL,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAC","sourcesContent":["\n\n// 导出所有类型定义\nexport * from './types';\n\n// 重新导出常用类型,方便直接从主模块导入\nexport type {\n // 通用类型\n LatLng,\n Point,\n CameraPosition,\n LatLngBounds,\n MapPoi,\n \n // 地图视图\n MapViewProps,\n CameraEvent,\n \n // 定位\n Coordinates,\n ReGeocode,\n LocationOptions,\n \n // 覆盖物\n MarkerProps,\n PolylineProps,\n PolygonProps,\n CircleProps,\n HeatMapProps,\n MultiPointProps,\n ClusterProps,\n} from './types';\n\nexport {\n MapType,\n LocationMode,\n LocationAccuracy,\n CoordinateType,\n} from './types';\n\n/**\n * Expo 模块事件类型\n */\nexport type ExpoGaodeMapModuleEvents = {\n /**\n * 定位更新事件\n */\n onLocationUpdate: (location: any) => void;\n \n /**\n * 定位错误事件\n */\n onLocationError: (error: { code: number; message: string }) => void;\n};\n\n/**\n * Expo 地图视图属性(用于主视图组件)\n */\nexport type { MapViewProps as ExpoGaodeMapViewProps } from './types';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoGaodeMapModule.d.ts","sourceRoot":"","sources":["../src/ExpoGaodeMapModule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoGaodeMapModule.d.ts","sourceRoot":"","sources":["../src/ExpoGaodeMapModule.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGrE,OAAO,OAAO,kBAAmB,SAAQ,YAAY,CAAC,wBAAwB,CAAC;CAG9E;;AAGD,wBAAuE"}
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
3
|
-
* @Date : 2025-11-13 14:03:56
|
|
4
|
-
* @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
5
|
-
* @LastEditTime : 2025-11-13 14:58:00
|
|
6
|
-
* @FilePath : /expo-gaode-map/src/ExpoGaodeMapModule.ts
|
|
7
|
-
* @Description :
|
|
8
|
-
*
|
|
9
|
-
* Copyright (c) 2025 by 尚博信_王强, All Rights Reserved.
|
|
10
|
-
*/
|
|
11
1
|
import { requireNativeModule } from 'expo';
|
|
12
2
|
// This call loads the native module object from the JSI.
|
|
13
3
|
export default requireNativeModule('ExpoGaodeMap');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoGaodeMapModule.js","sourceRoot":"","sources":["../src/ExpoGaodeMapModule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoGaodeMapModule.js","sourceRoot":"","sources":["../src/ExpoGaodeMapModule.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AASzD,yDAAyD;AACzD,eAAe,mBAAmB,CAAqB,cAAc,CAAC,CAAC","sourcesContent":["\nimport { NativeModule, requireNativeModule } from 'expo';\nimport type { ExpoGaodeMapModuleEvents } from './ExpoGaodeMap.types';\n\n\ndeclare class ExpoGaodeMapModule extends NativeModule<ExpoGaodeMapModuleEvents> {\n // 地图控制方法已移至 MapView 的 ref 调用\n // 使用方式: mapRef.current.moveCamera() 等\n}\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule<ExpoGaodeMapModule>('ExpoGaodeMap');\n"]}
|