expo-gaode-map-navigation 2.0.13 → 2.0.15

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 CHANGED
@@ -7,7 +7,7 @@
7
7
  - 🗺️ **地图渲染**:内置完整地图能力,支持 Marker、Polyline、Polygon、Circle、Cluster、HeatMap 等覆盖物。
8
8
  - 🔍 **原生搜索**:内置 POI 搜索、周边搜索、沿途搜索、输入提示、逆地理编码等搜索能力。
9
9
  - 🚗 **多模式路径规划**:支持驾车、步行、骑行、电动车、货车、摩托车等多种出行方式。
10
- - 🧭 **实时导航 UI**:提供 `NaviView` 官方嵌入视图,并暴露完整事件与原生参数,方便你自行定制导航界面。
10
+ - 🧭 **实时导航 UI**:提供 `ExpoGaodeMapNaviView` 官方嵌入视图,并暴露完整事件与原生参数,方便你自行定制导航界面。
11
11
  - 🛣️ **独立路径规划**:支持“先算路、再导航”的高级模式,可实现多路线对比与选择。
12
12
  - ⚙️ **策略丰富**:支持速度优先、避让拥堵、少收费、不走高速等多种算路策略。
13
13
  - ✅ **开箱即用**:封装了 Android/iOS 原生导航 SDK,统一 JS 接口。
@@ -30,7 +30,7 @@ npm install expo-gaode-map-navigation
30
30
  **⚠️ 重要提示:**
31
31
  如果项目中已安装 `expo-gaode-map`,请务必先卸载,否则会导致 Android 端二进制冲突(`3dmap` vs `navi-3dmap`)。`expo-gaode-map` 和 `expo-gaode-map-navigation` 由于 SDK 冲突不能同时安装,二选一使用。
32
32
 
33
- `expo-gaode-map-search` 的独立集成只维护到 `2.2.33`。从下个版本开始,搜索能力随 `expo-gaode-map` / `expo-gaode-map-navigation` 一起维护;在导航包中请直接从 `expo-gaode-map-navigation` 导入搜索 API。
33
+ `expo-gaode-map-search` 的独立集成只维护到 `2.2.33`。从 `2.0.13` 开始,搜索能力随 `expo-gaode-map` / `expo-gaode-map-navigation` 一起维护;在导航包中请直接从 `expo-gaode-map-navigation` 导入搜索 API。
34
34
 
35
35
  高德官方 Android SDK 在 `10.0.700` 之后将远程依赖由“地图 + 定位”调整为“地图 + 定位 + 搜索”,依赖地址从 `com.amap.api:3dmap:latest.integration` 调整为 `com.amap.api:3dmap-location-search:latest.integration`。继续单独维护 search 模块会带来重复合包和依赖冲突成本,因此搜索能力改为随 core / navigation 一起维护。
36
36
 
@@ -80,8 +80,8 @@ npx expo run:ios
80
80
  - `enableBackgroundAudio` 仅 iOS 生效(默认随 `enableBackgroundLocation` 自动开启),用于注入 `UIBackgroundModes: audio`,保障后台导航语音持续播报。
81
81
  - `enableIOSLiveActivity` 仅 iOS 生效,用于注入 `NSSupportsLiveActivities`。
82
82
  - `enableIOSLiveActivityFrequentUpdates` 仅 iOS 生效,用于注入 `NSSupportsLiveActivitiesFrequentUpdates`。
83
- - 运行时还需要在 `NaviView` 里显式传 `androidBackgroundNavigationNotificationEnabled={true}` 才会在应用退到后台后显示导航常驻通知。
84
- - iOS 运行时还需要在 `NaviView` 里显式传 `iosLiveActivityEnabled={true}` 才会持续更新 Live Activity。
83
+ - 运行时还需要在 `ExpoGaodeMapNaviView` 里显式传 `androidBackgroundNavigationNotificationEnabled={true}` 才会在应用退到后台后显示导航常驻通知。
84
+ - iOS 运行时还需要在 `ExpoGaodeMapNaviView` 里显式传 `iosLiveActivityEnabled={true}` 才会持续更新 Live Activity。
85
85
 
86
86
  ## 示例工程
87
87
 
@@ -89,7 +89,7 @@ npx expo run:ios
89
89
 
90
90
  推荐场景:
91
91
 
92
- - 调试 `NaviView` 与示例工程里的自定义 HUD / 车道 HUD / 路况光柱
92
+ - 调试 `ExpoGaodeMapNaviView` 与示例工程里的自定义 HUD / 车道 HUD / 路况光柱
93
93
  - 对比官方黑盒页、官方嵌入式页、自绘嵌入式页
94
94
  - 验证独立算路、多路线选择、近似跟线导航
95
95
 
@@ -170,15 +170,16 @@ export default function BasicMapScreen() {
170
170
 
171
171
  ### 2. 嵌入导航视图
172
172
 
173
- 使用 `NaviView` 组件直接嵌入导航界面:
173
+ 使用 `ExpoGaodeMapNaviView` 组件直接嵌入导航界面:
174
174
 
175
175
  ```tsx
176
176
  import React, { useEffect, useRef } from 'react';
177
177
  import { View } from 'react-native';
178
- import { NaviView, type NaviViewRef } from 'expo-gaode-map-navigation';
178
+ import { ExpoGaodeMapNaviView } from 'expo-gaode-map-navigation';
179
+ import type { ExpoGaodeMapNaviViewRef } from 'expo-gaode-map-navigation';
179
180
 
180
181
  export default function NavigationScreen() {
181
- const naviRef = useRef<NaviViewRef>(null);
182
+ const naviRef = useRef<ExpoGaodeMapNaviViewRef>(null);
182
183
 
183
184
  useEffect(() => {
184
185
  // 延迟 1 秒后开始导航
@@ -196,7 +197,7 @@ export default function NavigationScreen() {
196
197
 
197
198
  return (
198
199
  <View style={{ flex: 1 }}>
199
- <NaviView
200
+ <ExpoGaodeMapNaviView
200
201
  ref={naviRef}
201
202
  style={{ flex: 1 }}
202
203
  showCamera={true} // 显示摄像头
@@ -211,17 +212,17 @@ export default function NavigationScreen() {
211
212
 
212
213
  ### 3. 自定义嵌入式导航 UI
213
214
 
214
- 如果你要做“嵌入在自己页面里的导航页”,库本身提供的是底层 `NaviView`、导航事件和原生参数;完整的自定义 HUD / 车道 HUD / 路况光柱参考实现,已经迁移到仓库内的 [`example-navigation`](/Volumes/xinxin/expo-gaode-map/example-navigation/README.md)。
215
+ 如果你要做“嵌入在自己页面里的导航页”,库本身提供的是底层 `ExpoGaodeMapNaviView`、导航事件和原生参数;完整的自定义 HUD / 车道 HUD / 路况光柱参考实现,已经迁移到仓库内的 [`example-navigation`](/Volumes/xinxin/expo-gaode-map/example-navigation/README.md)。
215
216
 
216
217
  建议做法:
217
218
 
218
- - 用 `NaviView` 负责底层导航地图、语音、车道事件、路况事件、路口大图事件
219
+ - 用 `ExpoGaodeMapNaviView` 负责底层导航地图、语音、车道事件、路况事件、路口大图事件
219
220
  - 用 `onNaviInfoUpdate`、`onLaneInfoUpdate`、`onTrafficStatusesUpdate`、`onNaviVisualStateChange` 在业务侧自绘 HUD
220
221
  - 直接参考 `example-navigation/lib/navigation-ui/EmbeddedNaviView.tsx` 及配套 UI 文件,按你的产品需求裁剪
221
222
 
222
223
  注意:
223
224
 
224
- - Android 官方嵌入式 `NaviView` 在部分 React Native / Expo 宿主中,顶部信息区、车道条、路口大图联动效果可能与高德官方 Demo 不完全一致
225
+ - Android 官方嵌入式 `ExpoGaodeMapNaviView` 在部分 React Native / Expo 宿主中,顶部信息区、车道条、路口大图联动效果可能与高德官方 Demo 不完全一致
225
226
  - 如果你要验证官方嵌入式 UI 本身,请直接跑 `example-navigation` 里的 `official-embedded` 示例页
226
227
  - 如果你要交付稳定的嵌入式导航页,建议以示例工程里的“自定义 UI 导航界面”作为起点
227
228
 
@@ -494,6 +495,13 @@ const result = await calculateTransitRoute({
494
495
  - 可共享的范围仅限纯 TS 的 route / AOI 数据适配工具、文档和测试思路
495
496
  - 原生地图桥接、overlay 宿主逻辑、MapView facade 不会和核心包合并
496
497
 
498
+ ### 导入入口
499
+
500
+ - 运行时能力优先使用命名导出,例如 `calculateRoute`、`ExpoGaodeMapNaviView`、`openOfficialNaviPage`
501
+ - 类型请用 `import type`,例如 `RouteOptions`、`FollowWebPlannedRouteResult`
502
+ - 默认导出保留给需要整包挂载的场景,内容与常用路径规划和导航函数一致
503
+ - `NaviView` / `NaviViewRef` 仍作为兼容别名保留,新代码建议使用 `ExpoGaodeMapNaviView` / `ExpoGaodeMapNaviViewRef`
504
+
497
505
  ## API 参考
498
506
 
499
507
  ### DriveStrategy (驾车策略)
@@ -527,7 +535,7 @@ const result = await calculateTransitRoute({
527
535
  - 基于 `onTrafficStatusesUpdate` 的自绘路况光柱
528
536
  - “全览 / 锁车”与路况开关等浮层控制按钮
529
537
 
530
- ### NaviView Props
538
+ ### ExpoGaodeMapNaviView Props
531
539
 
532
540
  | 属性 | 类型 | 说明 |
533
541
  |---|---|---|
@@ -569,7 +577,7 @@ const result = await calculateTransitRoute({
569
577
  | `onNaviInfoUpdate` | function | 导航信息更新(剩余距离、时间等) |
570
578
  | `onLaneInfoUpdate` | function | Android / iOS 车道信息更新,用于自绘车道 HUD |
571
579
 
572
- ### NaviView UI 能力清单
580
+ ### ExpoGaodeMapNaviView UI 能力清单
573
581
 
574
582
  已开放且两端都有实现:
575
583
 
@@ -641,7 +649,7 @@ const result = await calculateTransitRoute({
641
649
  2. **Web API**:如果需要更灵活的 HTTP 算路(如公交跨城规划、Web端展示),推荐配合 `expo-gaode-map-web-api` 使用。
642
650
  3. **权限**:使用导航功能前,请确保应用已获取定位权限(`ACCESS_FINE_LOCATION`)。
643
651
  4. **Android 状态栏兼容性**:`naviStatusBarEnabled` 依赖高德 Android 导航 SDK 某些版本才提供的 `AMapNaviViewOptions.setNaviStatusBarEnabled(...)`。当前封装已做兼容处理:若宿主工程解析到的 SDK 不包含该方法,则不会再编译失败,而是在运行时跳过该设置并输出 warning。此时该 prop 在 Android 上等价于 no-op。
644
- 5. **嵌入式 UI 边界**:库导出的是底层 `NaviView` 能力;完整自定义导航界面请参考 `example-navigation` 里的示例实现,它也不是高德官方黑盒导航页的 UI 替代品。
652
+ 5. **嵌入式 UI 边界**:库导出的是底层 `ExpoGaodeMapNaviView` 能力;完整自定义导航界面请参考 `example-navigation` 里的示例实现,它也不是高德官方黑盒导航页的 UI 替代品。
645
653
 
646
654
 
647
655
  ## 📚 文档与资源
@@ -0,0 +1,34 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>expo-gaode-map-navigation</name>
4
+ <comment>Project example-navigation-android-expo-gaode-map-navigation created by Buildship.</comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>org.eclipse.jdt.core.javabuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ <buildCommand>
14
+ <name>org.eclipse.buildship.core.gradleprojectbuilder</name>
15
+ <arguments>
16
+ </arguments>
17
+ </buildCommand>
18
+ </buildSpec>
19
+ <natures>
20
+ <nature>org.eclipse.jdt.core.javanature</nature>
21
+ <nature>org.eclipse.buildship.core.gradleprojectnature</nature>
22
+ </natures>
23
+ <filteredResources>
24
+ <filter>
25
+ <id>1778483172220</id>
26
+ <name></name>
27
+ <type>30</type>
28
+ <matcher>
29
+ <id>org.eclipse.core.resources.regexFilterMatcher</id>
30
+ <arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
31
+ </matcher>
32
+ </filter>
33
+ </filteredResources>
34
+ </projectDescription>
@@ -27,6 +27,8 @@ class ExpoGaodeMapModule : Module() {
27
27
  /** 定位管理器实例 */
28
28
  private var locationManager: LocationManager? = null
29
29
 
30
+ private fun jsValue(value: Any?): Any? = value
31
+
30
32
  override fun definition() = ModuleDefinition {
31
33
  Name("ExpoGaodeMap")
32
34
 
@@ -93,7 +95,7 @@ class ExpoGaodeMapModule : Module() {
93
95
  }
94
96
 
95
97
  Function("getPrivacyStatus") {
96
- SDKInitializer.getPrivacyStatus()
98
+ jsValue(SDKInitializer.getPrivacyStatus())
97
99
  }
98
100
 
99
101
  /**
@@ -109,14 +111,14 @@ class ExpoGaodeMapModule : Module() {
109
111
  * @return SDK 版本号
110
112
  */
111
113
  Function("getVersion") {
112
- SDKInitializer.getVersion()
114
+ jsValue(SDKInitializer.getVersion())
113
115
  }
114
116
 
115
117
  /**
116
118
  * 检查原生 SDK 是否已配置 API Key
117
119
  */
118
120
  Function("isNativeSDKConfigured") {
119
- try {
121
+ jsValue(try {
120
122
  val context = appContext.reactContext!!
121
123
  val apiKey = context.packageManager
122
124
  .getApplicationInfo(context.packageName, android.content.pm.PackageManager.GET_META_DATA)
@@ -124,7 +126,7 @@ class ExpoGaodeMapModule : Module() {
124
126
  !apiKey.isNullOrEmpty()
125
127
  } catch (_: Exception) {
126
128
  false
127
- }
129
+ })
128
130
  }
129
131
 
130
132
 
@@ -187,11 +189,11 @@ class ExpoGaodeMapModule : Module() {
187
189
  Function("distanceBetweenCoordinates") { p1: Map<String, Any>?, p2: Map<String, Any>? ->
188
190
  val coord1 = LatLngParser.parseLatLng(p1)
189
191
  val coord2 = LatLngParser.parseLatLng(p2)
190
- if (coord1 != null && coord2 != null) {
192
+ jsValue(if (coord1 != null && coord2 != null) {
191
193
  GeometryUtils.calculateDistance(coord1, coord2)
192
194
  } else {
193
195
  0.0
194
- }
196
+ })
195
197
  }
196
198
 
197
199
  /**
@@ -213,16 +215,16 @@ class ExpoGaodeMapModule : Module() {
213
215
  val normalized = LatLngParser.parseLatLngList(points)
214
216
  val safeMinZoom = minZoom ?: 3
215
217
  val safeMaxZoom = maxZoom ?: 20
216
- if (normalized.isEmpty()) return@Function safeMinZoom.toDouble()
218
+ if (normalized.isEmpty()) return@Function jsValue(safeMinZoom.toDouble())
217
219
 
218
- GeometryUtils.calculateFitZoom(
220
+ jsValue(GeometryUtils.calculateFitZoom(
219
221
  normalized,
220
222
  viewportWidthPx ?: 390.0,
221
223
  viewportHeightPx ?: 844.0,
222
224
  paddingPx ?: 48.0,
223
225
  safeMinZoom,
224
226
  safeMaxZoom
225
- )
227
+ ))
226
228
  }
227
229
 
228
230
  /**
@@ -232,7 +234,7 @@ class ExpoGaodeMapModule : Module() {
232
234
  */
233
235
  Function("calculatePolygonArea") { points: List<Any>? ->
234
236
  val rings = LatLngParser.parseLatLngListList(points)
235
- if (rings.isEmpty()) return@Function 0.0
237
+ if (rings.isEmpty()) return@Function jsValue(0.0)
236
238
 
237
239
  // 第一项是外轮廓
238
240
  var totalArea = GeometryUtils.calculatePolygonArea(rings[0])
@@ -245,7 +247,7 @@ class ExpoGaodeMapModule : Module() {
245
247
  }
246
248
 
247
249
  // 确保面积不为负数
248
- max(0.0, totalArea)
250
+ jsValue(max(0.0, totalArea))
249
251
  }
250
252
 
251
253
  /**
@@ -255,24 +257,24 @@ class ExpoGaodeMapModule : Module() {
255
257
  * @return 是否在多边形内
256
258
  */
257
259
  Function("isPointInPolygon") { point: Map<String, Any>?, polygon: List<Any>? ->
258
- val pt = LatLngParser.parseLatLng(point) ?: return@Function false
260
+ val pt = LatLngParser.parseLatLng(point) ?: return@Function jsValue(false)
259
261
  val rings = LatLngParser.parseLatLngListList(polygon)
260
- if (rings.isEmpty()) return@Function false
262
+ if (rings.isEmpty()) return@Function jsValue(false)
261
263
 
262
264
  // 点必须在外轮廓内
263
265
  val inOuter = GeometryUtils.isPointInPolygon(pt, rings[0])
264
- if (!inOuter) return@Function false
266
+ if (!inOuter) return@Function jsValue(false)
265
267
 
266
268
  // 点不能在任何内孔内
267
269
  if (rings.size > 1) {
268
270
  for (i in 1 until rings.size) {
269
271
  if (GeometryUtils.isPointInPolygon(pt, rings[i])) {
270
- return@Function false
272
+ return@Function jsValue(false)
271
273
  }
272
274
  }
273
275
  }
274
276
 
275
- true
277
+ jsValue(true)
276
278
  }
277
279
 
278
280
  /**
@@ -285,11 +287,11 @@ class ExpoGaodeMapModule : Module() {
285
287
  Function("isPointInCircle") { point: Map<String, Any>?, center: Map<String, Any>?, radius: Double ->
286
288
  val pt = LatLngParser.parseLatLng(point)
287
289
  val cn = LatLngParser.parseLatLng(center)
288
- if (pt != null && cn != null) {
290
+ jsValue(if (pt != null && cn != null) {
289
291
  GeometryUtils.isPointInCircle(pt, cn, radius)
290
292
  } else {
291
293
  false
292
- }
294
+ })
293
295
  }
294
296
 
295
297
  /**
@@ -301,11 +303,11 @@ class ExpoGaodeMapModule : Module() {
301
303
  Function("calculateRectangleArea") { southWest: Map<String, Any>?, northEast: Map<String, Any>? ->
302
304
  val sw = LatLngParser.parseLatLng(southWest)
303
305
  val ne = LatLngParser.parseLatLng(northEast)
304
- if (sw != null && ne != null) {
306
+ jsValue(if (sw != null && ne != null) {
305
307
  GeometryUtils.calculateRectangleArea(sw, ne)
306
308
  } else {
307
309
  0.0
308
- }
310
+ })
309
311
  }
310
312
 
311
313
  /**
@@ -318,7 +320,7 @@ class ExpoGaodeMapModule : Module() {
318
320
  val pathPoints = LatLngParser.parseLatLngList(path)
319
321
  val targetPoint = LatLngParser.parseLatLng(target)
320
322
 
321
- if (targetPoint != null && pathPoints.isNotEmpty()) {
323
+ jsValue(if (targetPoint != null && pathPoints.isNotEmpty()) {
322
324
  val result = GeometryUtils.getNearestPointOnPath(pathPoints, targetPoint)
323
325
  if (result != null) {
324
326
  mapOf(
@@ -332,7 +334,7 @@ class ExpoGaodeMapModule : Module() {
332
334
  }
333
335
  } else {
334
336
  null
335
- }
337
+ })
336
338
  }
337
339
 
338
340
  /**
@@ -342,16 +344,16 @@ class ExpoGaodeMapModule : Module() {
342
344
  */
343
345
  Function("calculateCentroid") { polygon: List<Any>? ->
344
346
  val rings = LatLngParser.parseLatLngListList(polygon)
345
- if (rings.isEmpty()) return@Function null
347
+ if (rings.isEmpty()) return@Function jsValue(null)
346
348
 
347
349
  if (rings.size == 1) {
348
350
  val result = GeometryUtils.calculateCentroid(rings[0])
349
- return@Function result?.let {
351
+ return@Function jsValue(result?.let {
350
352
  mapOf(
351
353
  "latitude" to it.latitude,
352
354
  "longitude" to it.longitude
353
355
  )
354
- }
356
+ })
355
357
  }
356
358
 
357
359
  // 带孔多边形的质心计算: Σ(Area_i * Centroid_i) / Σ(Area_i)
@@ -376,14 +378,14 @@ class ExpoGaodeMapModule : Module() {
376
378
  }
377
379
  }
378
380
 
379
- if (abs(totalArea) > 1e-9) {
381
+ jsValue(if (abs(totalArea) > 1e-9) {
380
382
  mapOf(
381
383
  "latitude" to sumLat / totalArea,
382
384
  "longitude" to sumLon / totalArea
383
385
  )
384
386
  } else {
385
387
  null
386
- }
388
+ })
387
389
  }
388
390
 
389
391
  /**
@@ -393,10 +395,10 @@ class ExpoGaodeMapModule : Module() {
393
395
  */
394
396
  Function("calculatePathBounds") { pointsList: List<Any>? ->
395
397
  val points = LatLngParser.parseLatLngList(pointsList)
396
- if (points.isEmpty()) return@Function null
398
+ if (points.isEmpty()) return@Function jsValue(null)
397
399
 
398
400
  val result = GeometryUtils.calculatePathBounds(points)
399
- result?.let {
401
+ jsValue(result?.let {
400
402
  mapOf(
401
403
  "north" to it.north,
402
404
  "south" to it.south,
@@ -407,7 +409,7 @@ class ExpoGaodeMapModule : Module() {
407
409
  "longitude" to it.centerLon
408
410
  )
409
411
  )
410
- }
412
+ })
411
413
  }
412
414
 
413
415
  /**
@@ -418,11 +420,11 @@ class ExpoGaodeMapModule : Module() {
418
420
  */
419
421
  Function("encodeGeoHash") { coordinate: Map<String, Any>?, precision: Int ->
420
422
  val latLng = LatLngParser.parseLatLng(coordinate)
421
- if (latLng != null) {
423
+ jsValue(if (latLng != null) {
422
424
  GeometryUtils.encodeGeoHash(latLng, precision)
423
425
  } else {
424
426
  ""
425
- }
427
+ })
426
428
  }
427
429
 
428
430
  /**
@@ -434,12 +436,12 @@ class ExpoGaodeMapModule : Module() {
434
436
  Function("simplifyPolyline") { points: List<Any>?, tolerance: Double ->
435
437
  val poly = LatLngParser.parseLatLngList(points)
436
438
  val simplified = GeometryUtils.simplifyPolyline(poly, tolerance)
437
- simplified.map {
439
+ jsValue(simplified.map {
438
440
  mapOf(
439
441
  "latitude" to it.latitude,
440
442
  "longitude" to it.longitude
441
443
  )
442
- }
444
+ })
443
445
  }
444
446
 
445
447
  /**
@@ -449,7 +451,7 @@ class ExpoGaodeMapModule : Module() {
449
451
  */
450
452
  Function("calculatePathLength") { points: List<Any>? ->
451
453
  val poly = LatLngParser.parseLatLngList(points)
452
- GeometryUtils.calculatePathLength(poly)
454
+ jsValue(GeometryUtils.calculatePathLength(poly))
453
455
  }
454
456
 
455
457
  /**
@@ -459,12 +461,12 @@ class ExpoGaodeMapModule : Module() {
459
461
  */
460
462
  Function("parsePolyline") { polylineStr: String? ->
461
463
  val result = GeometryUtils.parsePolyline(polylineStr)
462
- result.map {
464
+ jsValue(result.map {
463
465
  mapOf(
464
466
  "latitude" to it.latitude,
465
467
  "longitude" to it.longitude
466
468
  )
467
- }
469
+ })
468
470
  }
469
471
 
470
472
  /**
@@ -476,7 +478,7 @@ class ExpoGaodeMapModule : Module() {
476
478
  Function("getPointAtDistance") { points: List<Any>?, distance: Double ->
477
479
  val poly = LatLngParser.parseLatLngList(points)
478
480
  val result = GeometryUtils.getPointAtDistance(poly, distance)
479
- if (result != null) {
481
+ jsValue(if (result != null) {
480
482
  mapOf(
481
483
  "latitude" to result.point.latitude,
482
484
  "longitude" to result.point.longitude,
@@ -484,7 +486,7 @@ class ExpoGaodeMapModule : Module() {
484
486
  )
485
487
  } else {
486
488
  null
487
- }
489
+ })
488
490
  }
489
491
 
490
492
  /**
@@ -495,7 +497,7 @@ class ExpoGaodeMapModule : Module() {
495
497
  */
496
498
  Function("latLngToTile") { coordinate: Map<String, Any>?, zoom: Int ->
497
499
  val latLng = LatLngParser.parseLatLng(coordinate)
498
- if (latLng != null) {
500
+ jsValue(if (latLng != null) {
499
501
  val result = GeometryUtils.latLngToTile(latLng, zoom)
500
502
  if (result != null && result.size >= 2) {
501
503
  mapOf("x" to result[0], "y" to result[1])
@@ -504,7 +506,7 @@ class ExpoGaodeMapModule : Module() {
504
506
  }
505
507
  } else {
506
508
  null
507
- }
509
+ })
508
510
  }
509
511
 
510
512
  /**
@@ -517,9 +519,9 @@ class ExpoGaodeMapModule : Module() {
517
519
  val y = (tile?.get("y") as? Number)?.toInt() ?: 0
518
520
  val zoom = (tile?.get("z") as? Number)?.toInt() ?: (tile?.get("zoom") as? Number)?.toInt() ?: 0
519
521
  val result = GeometryUtils.tileToLatLng(x, y, zoom)
520
- result?.let {
522
+ jsValue(result?.let {
521
523
  mapOf("latitude" to it.latitude, "longitude" to it.longitude)
522
- }
524
+ })
523
525
  }
524
526
 
525
527
  /**
@@ -530,7 +532,7 @@ class ExpoGaodeMapModule : Module() {
530
532
  */
531
533
  Function("latLngToPixel") { coordinate: Map<String, Any>?, zoom: Int ->
532
534
  val latLng = LatLngParser.parseLatLng(coordinate)
533
- if (latLng != null) {
535
+ jsValue(if (latLng != null) {
534
536
  val result = GeometryUtils.latLngToPixel(latLng, zoom)
535
537
  if (result != null && result.size >= 2) {
536
538
  mapOf("x" to result[0], "y" to result[1])
@@ -539,7 +541,7 @@ class ExpoGaodeMapModule : Module() {
539
541
  }
540
542
  } else {
541
543
  null
542
- }
544
+ })
543
545
  }
544
546
 
545
547
  /**
@@ -552,9 +554,9 @@ class ExpoGaodeMapModule : Module() {
552
554
  val x = (pixel?.get("x") as? Number)?.toDouble() ?: 0.0
553
555
  val y = (pixel?.get("y") as? Number)?.toDouble() ?: 0.0
554
556
  val result = GeometryUtils.pixelToLatLng(x, y, zoom)
555
- result?.let {
557
+ jsValue(result?.let {
556
558
  mapOf("latitude" to it.latitude, "longitude" to it.longitude)
557
- }
559
+ })
558
560
  }
559
561
 
560
562
  /**
@@ -566,11 +568,11 @@ class ExpoGaodeMapModule : Module() {
566
568
  Function("findPointInPolygons") { point: Map<String, Any>?, polygons: List<List<Any>>? ->
567
569
  val pt = LatLngParser.parseLatLng(point)
568
570
  val polys = polygons?.map { LatLngParser.parseLatLngList(it) }
569
- if (pt != null && polys != null) {
571
+ jsValue(if (pt != null && polys != null) {
570
572
  GeometryUtils.findPointInPolygons(pt, polys)
571
573
  } else {
572
574
  -1
573
- }
575
+ })
574
576
  }
575
577
 
576
578
  /**
@@ -579,7 +581,7 @@ class ExpoGaodeMapModule : Module() {
579
581
  * @param gridSizeMeters 网格大小(米)
580
582
  */
581
583
  Function("generateHeatmapGrid") { points: List<Map<String, Any>>?, gridSizeMeters: Double ->
582
- if (points == null || points.isEmpty()) return@Function emptyList<Map<String, Any>>()
584
+ if (points == null || points.isEmpty()) return@Function jsValue(emptyList<Map<String, Any>>())
583
585
 
584
586
  val count = points.size
585
587
  val latitudes = DoubleArray(count)
@@ -593,13 +595,13 @@ class ExpoGaodeMapModule : Module() {
593
595
  }
594
596
 
595
597
  val result = GeometryUtils.generateHeatmapGrid(latitudes, longitudes, weights, gridSizeMeters)
596
- result.map {
598
+ jsValue(result.map {
597
599
  mapOf(
598
600
  "latitude" to it.latitude,
599
601
  "longitude" to it.longitude,
600
602
  "intensity" to it.intensity
601
603
  )
602
- }
604
+ })
603
605
  }
604
606
 
605
607
  // ==================== 定位配置 ====================