expo-gaode-map-navigation 2.0.12 → 2.0.14
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 +29 -16
- package/android/build.gradle +8 -4
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +83 -15
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +13 -3
- package/android/src/main/java/expo/modules/gaodemap/map/managers/UIManager.kt +36 -39
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterView.kt +5 -2
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapView.kt +122 -10
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapViewModule.kt +2 -2
- package/android/src/main/java/expo/modules/gaodemap/map/search/ExpoGaodeMapSearchModule.kt +751 -0
- package/build/index.d.ts +26 -126
- package/build/index.d.ts.map +1 -1
- package/build/index.js +11 -612
- package/build/index.js.map +1 -1
- package/build/map/ExpoGaodeMapOfflineModule.d.ts +5 -0
- package/build/map/ExpoGaodeMapOfflineModule.d.ts.map +1 -1
- package/build/map/ExpoGaodeMapOfflineModule.js.map +1 -1
- package/build/map/components/overlays/HeatMap.d.ts.map +1 -1
- package/build/map/components/overlays/HeatMap.js +21 -2
- package/build/map/components/overlays/HeatMap.js.map +1 -1
- package/build/map/index.d.ts +3 -0
- package/build/map/index.d.ts.map +1 -1
- package/build/map/index.js +3 -0
- package/build/map/index.js.map +1 -1
- package/build/map/search/ExpoGaodeMapSearch.types.d.ts +340 -0
- package/build/map/search/ExpoGaodeMapSearch.types.d.ts.map +1 -0
- package/build/map/search/ExpoGaodeMapSearch.types.js +19 -0
- package/build/map/search/ExpoGaodeMapSearch.types.js.map +1 -0
- package/build/map/search/ExpoGaodeMapSearchModule.d.ts +74 -0
- package/build/map/search/ExpoGaodeMapSearchModule.d.ts.map +1 -0
- package/build/map/search/ExpoGaodeMapSearchModule.js +47 -0
- package/build/map/search/ExpoGaodeMapSearchModule.js.map +1 -0
- package/build/map/search/index.d.ts +156 -0
- package/build/map/search/index.d.ts.map +1 -0
- package/build/map/search/index.js +171 -0
- package/build/map/search/index.js.map +1 -0
- package/build/map/types/map-view.types.d.ts +4 -2
- package/build/map/types/map-view.types.d.ts.map +1 -1
- package/build/map/types/map-view.types.js.map +1 -1
- package/build/map/utils/ErrorHandler.js +11 -11
- package/build/map/utils/ErrorHandler.js.map +1 -1
- package/build/map/utils/OfflineMapManager.d.ts +4 -0
- package/build/map/utils/OfflineMapManager.d.ts.map +1 -1
- package/build/map/utils/OfflineMapManager.js +6 -0
- package/build/map/utils/OfflineMapManager.js.map +1 -1
- package/build/route-geometry.d.ts +13 -0
- package/build/route-geometry.d.ts.map +1 -0
- package/build/route-geometry.js +154 -0
- package/build/route-geometry.js.map +1 -0
- package/build/route-planning.d.ts +21 -0
- package/build/route-planning.d.ts.map +1 -0
- package/build/route-planning.js +67 -0
- package/build/route-planning.js.map +1 -0
- package/build/web-api-fallback.d.ts +5 -0
- package/build/web-api-fallback.d.ts.map +1 -0
- package/build/web-api-fallback.js +160 -0
- package/build/web-api-fallback.js.map +1 -0
- package/build/web-route-following.d.ts +3 -0
- package/build/web-route-following.d.ts.map +1 -0
- package/build/web-route-following.js +178 -0
- package/build/web-route-following.js.map +1 -0
- package/expo-module.config.json +4 -2
- package/ios/ExpoGaodeMapNaviView.swift +16 -17
- package/ios/ExpoGaodeMapNavigation.podspec +2 -1
- package/ios/map/ExpoGaodeMapOfflineModule.swift +61 -0
- package/ios/map/ExpoGaodeMapSearchModule.swift +773 -0
- package/ios/map/modules/LocationManager.swift +9 -3
- package/ios/map/overlays/PolylineView.swift +6 -12
- package/package.json +2 -2
- package/plugin/build/withGaodeMap.js +12 -0
- package/android/src/main/java/expo/modules/gaodemap/navigation/managers/RouteCalculator.kt +0 -173
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
package expo.modules.gaodemap.map.overlays
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
import android.graphics.Color
|
|
4
5
|
import android.os.Looper
|
|
5
6
|
import android.util.Log
|
|
6
7
|
import com.amap.api.maps.AMap
|
|
8
|
+
import com.amap.api.maps.CameraUpdateFactory
|
|
9
|
+
import com.amap.api.maps.model.Gradient
|
|
10
|
+
import com.amap.api.maps.model.HeatmapTileProvider
|
|
7
11
|
import com.amap.api.maps.model.LatLng
|
|
8
12
|
import com.amap.api.maps.model.TileOverlay
|
|
9
13
|
import com.amap.api.maps.model.TileOverlayOptions
|
|
10
|
-
import com.amap.api.maps.model.
|
|
11
|
-
import com.amap.api.maps.CameraUpdateFactory
|
|
14
|
+
import com.amap.api.maps.model.WeightedLatLng
|
|
12
15
|
import expo.modules.kotlin.AppContext
|
|
13
16
|
import expo.modules.kotlin.views.ExpoView
|
|
17
|
+
import expo.modules.gaodemap.map.utils.LatLngParser
|
|
14
18
|
import java.util.concurrent.ExecutorService
|
|
15
19
|
import java.util.concurrent.Executors
|
|
16
|
-
import expo.modules.gaodemap.map.utils.LatLngParser
|
|
17
20
|
|
|
18
21
|
class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
|
|
22
|
+
private companion object {
|
|
23
|
+
const val TAG = "HeatMapView"
|
|
24
|
+
}
|
|
19
25
|
|
|
20
26
|
private val executor: ExecutorService = Executors.newSingleThreadExecutor()
|
|
21
27
|
private val applyUpdateRunnable = Runnable { applyUpdateOnMain() }
|
|
@@ -25,9 +31,10 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
25
31
|
|
|
26
32
|
private var heatmapOverlay: TileOverlay? = null
|
|
27
33
|
private var aMap: AMap? = null
|
|
28
|
-
private var dataList: MutableList<
|
|
34
|
+
private var dataList: MutableList<WeightedLatLng> = mutableListOf()
|
|
29
35
|
private var radius: Int = 50
|
|
30
36
|
private var opacity: Double = 0.6
|
|
37
|
+
private var gradient: Gradient? = null
|
|
31
38
|
|
|
32
39
|
/**
|
|
33
40
|
* 设置地图实例
|
|
@@ -36,6 +43,7 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
36
43
|
fun setMap(map: AMap) {
|
|
37
44
|
aMap = map
|
|
38
45
|
needsRebuild = true
|
|
46
|
+
Log.d(TAG, "setMap: map attached")
|
|
39
47
|
scheduleUpdate()
|
|
40
48
|
}
|
|
41
49
|
|
|
@@ -46,7 +54,8 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
46
54
|
*/
|
|
47
55
|
fun setData(data: List<Any>?) {
|
|
48
56
|
dataList.clear()
|
|
49
|
-
dataList.addAll(
|
|
57
|
+
dataList.addAll(parseWeightedLatLngList(data))
|
|
58
|
+
Log.d(TAG, "setData: raw=${data?.size ?: 0}, parsed=${dataList.size}, ${formatPointStats(dataList)}")
|
|
50
59
|
needsRebuild = true
|
|
51
60
|
scheduleUpdate()
|
|
52
61
|
}
|
|
@@ -56,6 +65,7 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
56
65
|
*/
|
|
57
66
|
fun setRadius(radiusValue: Int) {
|
|
58
67
|
radius = radiusValue
|
|
68
|
+
Log.d(TAG, "setRadius: $radiusValue")
|
|
59
69
|
needsRebuild = true
|
|
60
70
|
scheduleUpdate()
|
|
61
71
|
}
|
|
@@ -65,10 +75,20 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
65
75
|
*/
|
|
66
76
|
fun setOpacity(opacityValue: Double) {
|
|
67
77
|
opacity = opacityValue
|
|
68
|
-
|
|
78
|
+
Log.d(TAG, "setOpacity: $opacityValue")
|
|
79
|
+
needsRebuild = true
|
|
80
|
+
scheduleUpdate()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fun setGradient(gradientValue: Map<String, Any>?) {
|
|
84
|
+
gradient = parseGradient(gradientValue)
|
|
85
|
+
Log.d(TAG, "setGradient: hasGradient=${gradient != null}, raw=${gradientValue != null}")
|
|
86
|
+
needsRebuild = true
|
|
87
|
+
scheduleUpdate()
|
|
69
88
|
}
|
|
70
89
|
|
|
71
90
|
fun setVisible(visibleValue: Boolean) {
|
|
91
|
+
Log.d(TAG, "setVisible: $visibleValue, points=${dataList.size}, hasOverlay=${heatmapOverlay != null}, needsRebuild=$needsRebuild")
|
|
72
92
|
if (!visibleValue) {
|
|
73
93
|
visible = false
|
|
74
94
|
updateToken += 1
|
|
@@ -95,6 +115,7 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
95
115
|
private fun scheduleUpdate() {
|
|
96
116
|
updateToken += 1
|
|
97
117
|
removeCallbacks(applyUpdateRunnable)
|
|
118
|
+
Log.d(TAG, "scheduleUpdate: token=$updateToken, mapAttached=${aMap != null}, visible=$visible, points=${dataList.size}")
|
|
98
119
|
postDelayed(applyUpdateRunnable, 32)
|
|
99
120
|
}
|
|
100
121
|
|
|
@@ -142,8 +163,11 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
142
163
|
val map = aMap ?: return
|
|
143
164
|
val token = updateToken
|
|
144
165
|
val pointsSnapshot = ArrayList(dataList)
|
|
166
|
+
val latLngSnapshot = pointsSnapshot.map { it.latLng }
|
|
145
167
|
val radiusValue = radius.coerceIn(10, 200)
|
|
146
168
|
val opacityValue = opacity.coerceIn(0.0, 1.0)
|
|
169
|
+
val gradientValue = gradient
|
|
170
|
+
Log.d(TAG, "applyUpdate: token=$token, visible=$visible, points=${pointsSnapshot.size}, radius=$radiusValue, opacity=$opacityValue, gradient=${gradientValue != null}, ${formatPointStats(pointsSnapshot)}")
|
|
147
171
|
|
|
148
172
|
if (!visible) {
|
|
149
173
|
applyOverlayVisibility()
|
|
@@ -151,6 +175,7 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
151
175
|
}
|
|
152
176
|
|
|
153
177
|
if (pointsSnapshot.isEmpty()) {
|
|
178
|
+
Log.w(TAG, "applyUpdate: no valid heatmap points, removing overlay")
|
|
154
179
|
heatmapOverlay?.remove()
|
|
155
180
|
heatmapOverlay = null
|
|
156
181
|
return
|
|
@@ -164,19 +189,25 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
164
189
|
|
|
165
190
|
executor.execute {
|
|
166
191
|
try {
|
|
167
|
-
val
|
|
168
|
-
.data(
|
|
192
|
+
val builder = HeatmapTileProvider.Builder()
|
|
193
|
+
.data(latLngSnapshot)
|
|
169
194
|
.radius(radiusValue)
|
|
170
|
-
|
|
195
|
+
|
|
196
|
+
gradientValue?.let { builder.gradient(it) }
|
|
197
|
+
|
|
198
|
+
val provider = builder.build()
|
|
171
199
|
|
|
172
200
|
post {
|
|
173
201
|
if (token != updateToken) {
|
|
202
|
+
Log.d(TAG, "addOverlay skipped: stale token=$token, current=$updateToken")
|
|
174
203
|
return@post
|
|
175
204
|
}
|
|
176
205
|
if (aMap !== map) {
|
|
206
|
+
Log.d(TAG, "addOverlay skipped: map instance changed")
|
|
177
207
|
return@post
|
|
178
208
|
}
|
|
179
209
|
if (!visible) {
|
|
210
|
+
Log.d(TAG, "addOverlay skipped: hidden")
|
|
180
211
|
return@post
|
|
181
212
|
}
|
|
182
213
|
|
|
@@ -200,9 +231,10 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
200
231
|
applyOverlayVisibility()
|
|
201
232
|
applyOverlayOpacity()
|
|
202
233
|
forceRefresh()
|
|
234
|
+
Log.i(TAG, "addOverlay success: id=${runCatching { heatmapOverlay?.id }.getOrNull()}, points=${pointsSnapshot.size}, radius=$radiusValue, opacity=$opacityValue")
|
|
203
235
|
}
|
|
204
236
|
} catch (t: Throwable) {
|
|
205
|
-
Log.e(
|
|
237
|
+
Log.e(TAG, "Failed to build heatmap", t)
|
|
206
238
|
}
|
|
207
239
|
}
|
|
208
240
|
}
|
|
@@ -217,11 +249,91 @@ class HeatMapView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
217
249
|
fun removeHeatMap() {
|
|
218
250
|
updateToken += 1
|
|
219
251
|
removeCallbacks(applyUpdateRunnable)
|
|
252
|
+
Log.d(TAG, "removeHeatMap")
|
|
220
253
|
heatmapOverlay?.remove()
|
|
221
254
|
heatmapOverlay = null
|
|
222
255
|
dataList.clear()
|
|
223
256
|
needsRebuild = true
|
|
224
257
|
}
|
|
258
|
+
|
|
259
|
+
private fun parseWeightedLatLngList(data: Any?): List<WeightedLatLng> {
|
|
260
|
+
if (data == null || data !is List<*>) return emptyList()
|
|
261
|
+
|
|
262
|
+
val result = mutableListOf<WeightedLatLng>()
|
|
263
|
+
for (item in data) {
|
|
264
|
+
val point = parseWeightedLatLng(item)
|
|
265
|
+
if (point != null) {
|
|
266
|
+
result.add(point)
|
|
267
|
+
} else if (item is List<*>) {
|
|
268
|
+
result.addAll(parseWeightedLatLngList(item))
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return result
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private fun parseWeightedLatLng(data: Any?): WeightedLatLng? {
|
|
275
|
+
val latLng = LatLngParser.parseLatLng(data) ?: return null
|
|
276
|
+
val intensity = when (data) {
|
|
277
|
+
is Map<*, *> -> listOf(data["intensity"], data["weight"], data["count"], data["value"])
|
|
278
|
+
.firstOrNull { it is Number }
|
|
279
|
+
is List<*> -> data.getOrNull(2)
|
|
280
|
+
else -> null
|
|
281
|
+
}
|
|
282
|
+
val weight = ((intensity as? Number)?.toDouble() ?: 1.0).takeIf { it.isFinite() && it > 0.0 } ?: 1.0
|
|
283
|
+
return WeightedLatLng(latLng, weight)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private fun parseGradient(gradientValue: Map<String, Any>?): Gradient? {
|
|
287
|
+
if (gradientValue == null) return null
|
|
288
|
+
val rawColors = gradientValue["colors"] as? List<*> ?: return null
|
|
289
|
+
val rawStartPoints = gradientValue["startPoints"] as? List<*> ?: return null
|
|
290
|
+
if (rawColors.size < 2 || rawColors.size != rawStartPoints.size) {
|
|
291
|
+
Log.w(TAG, "parseGradient ignored: colors=${rawColors.size}, startPoints=${rawStartPoints.size}")
|
|
292
|
+
return null
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
val colors = IntArray(rawColors.size)
|
|
296
|
+
val startPoints = FloatArray(rawStartPoints.size)
|
|
297
|
+
for (index in rawColors.indices) {
|
|
298
|
+
val color = parseColor(rawColors[index]) ?: run {
|
|
299
|
+
Log.w(TAG, "parseGradient ignored: invalid color at index=$index, value=${rawColors[index]}")
|
|
300
|
+
return null
|
|
301
|
+
}
|
|
302
|
+
val startPoint = (rawStartPoints[index] as? Number)?.toFloat() ?: run {
|
|
303
|
+
Log.w(TAG, "parseGradient ignored: invalid startPoint at index=$index, value=${rawStartPoints[index]}")
|
|
304
|
+
return null
|
|
305
|
+
}
|
|
306
|
+
colors[index] = color
|
|
307
|
+
startPoints[index] = startPoint.coerceIn(0f, 1f)
|
|
308
|
+
}
|
|
309
|
+
return Gradient(colors, startPoints)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private fun parseColor(value: Any?): Int? {
|
|
313
|
+
return when (value) {
|
|
314
|
+
is Number -> value.toInt()
|
|
315
|
+
is String -> runCatching { Color.parseColor(value) }.getOrNull()
|
|
316
|
+
else -> null
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private fun formatPointStats(points: List<WeightedLatLng>): String {
|
|
321
|
+
if (points.isEmpty()) return "bounds=empty"
|
|
322
|
+
var minLat = Double.POSITIVE_INFINITY
|
|
323
|
+
var maxLat = Double.NEGATIVE_INFINITY
|
|
324
|
+
var minLng = Double.POSITIVE_INFINITY
|
|
325
|
+
var maxLng = Double.NEGATIVE_INFINITY
|
|
326
|
+
var totalIntensity = 0.0
|
|
327
|
+
points.forEach { point ->
|
|
328
|
+
val latLng: LatLng = point.latLng
|
|
329
|
+
minLat = minOf(minLat, latLng.latitude)
|
|
330
|
+
maxLat = maxOf(maxLat, latLng.latitude)
|
|
331
|
+
minLng = minOf(minLng, latLng.longitude)
|
|
332
|
+
maxLng = maxOf(maxLng, latLng.longitude)
|
|
333
|
+
totalIntensity += point.intensity
|
|
334
|
+
}
|
|
335
|
+
return "bounds=[$minLat,$minLng]-[$maxLat,$maxLng], totalIntensity=$totalIntensity"
|
|
336
|
+
}
|
|
225
337
|
|
|
226
338
|
override fun onDetachedFromWindow() {
|
|
227
339
|
super.onDetachedFromWindow()
|
|
@@ -27,8 +27,8 @@ class HeatMapViewModule : Module() {
|
|
|
27
27
|
view.setOpacity(opacity)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
Prop<Map<String, Any>?>("gradient") {
|
|
31
|
-
|
|
30
|
+
Prop<Map<String, Any>?>("gradient") { view: HeatMapView, gradient ->
|
|
31
|
+
view.setGradient(gradient)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
Prop<Boolean>("allowRetinaAdapting") { _: HeatMapView, _ ->
|