expo-gaode-map-navigation 1.1.5 → 1.1.6

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 (146) hide show
  1. package/README.md +213 -73
  2. package/android/build.gradle +10 -0
  3. package/android/src/main/cpp/CMakeLists.txt +24 -0
  4. package/android/src/main/cpp/cluster_jni.cpp +848 -0
  5. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +616 -92
  6. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +493 -0
  7. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +230 -14
  8. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapViewModule.kt +37 -27
  9. package/android/src/main/java/expo/modules/gaodemap/map/MapPreloadManager.kt +494 -0
  10. package/android/src/main/java/expo/modules/gaodemap/map/companion/BitmapDescriptorCache.kt +30 -0
  11. package/android/src/main/java/expo/modules/gaodemap/map/companion/IconBitmapCache.kt +37 -0
  12. package/android/src/main/java/expo/modules/gaodemap/map/managers/UIManager.kt +76 -0
  13. package/android/src/main/java/expo/modules/gaodemap/map/modules/LocationManager.kt +15 -3
  14. package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +4 -59
  15. package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleView.kt +9 -12
  16. package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleViewModule.kt +5 -6
  17. package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterView.kt +539 -66
  18. package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterViewModule.kt +17 -1
  19. package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapView.kt +165 -33
  20. package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapViewModule.kt +15 -3
  21. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +1249 -672
  22. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerViewModule.kt +40 -17
  23. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointView.kt +177 -22
  24. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointViewModule.kt +11 -3
  25. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonView.kt +57 -14
  26. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonViewModule.kt +9 -5
  27. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineView.kt +90 -63
  28. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineViewModule.kt +7 -3
  29. package/android/src/main/java/expo/modules/gaodemap/map/services/LocationForegroundService.kt +3 -2
  30. package/android/src/main/java/expo/modules/gaodemap/map/utils/BitmapDescriptorCache.kt +20 -0
  31. package/android/src/main/java/expo/modules/gaodemap/map/utils/ClusterNative.kt +13 -0
  32. package/android/src/main/java/expo/modules/gaodemap/map/utils/ColorParser.kt +20 -0
  33. package/android/src/main/java/expo/modules/gaodemap/map/utils/GeometryUtils.kt +515 -0
  34. package/android/src/main/java/expo/modules/gaodemap/map/utils/LatLngParser.kt +91 -0
  35. package/android/src/main/java/expo/modules/gaodemap/map/utils/PermissionHelper.kt +248 -0
  36. package/build/ExpoGaodeMapNaviView.d.ts +7 -7
  37. package/build/ExpoGaodeMapNaviView.js +10 -11
  38. package/build/ExpoGaodeMapNavigationModule.d.ts +2 -1
  39. package/build/index.d.ts +35 -33
  40. package/build/index.js +70 -106
  41. package/build/map/ExpoGaodeMapModule.d.ts +2 -201
  42. package/build/map/ExpoGaodeMapModule.js +586 -18
  43. package/build/map/ExpoGaodeMapOfflineModule.d.ts +139 -0
  44. package/build/map/ExpoGaodeMapOfflineModule.js +8 -0
  45. package/build/map/ExpoGaodeMapView.js +66 -58
  46. package/build/map/components/FoldableMapView.d.ts +38 -0
  47. package/build/map/components/FoldableMapView.js +209 -0
  48. package/build/map/components/MapContext.d.ts +12 -0
  49. package/build/map/components/MapContext.js +54 -0
  50. package/build/map/components/MapUI.d.ts +18 -0
  51. package/build/map/components/MapUI.js +29 -0
  52. package/build/map/components/overlays/Circle.js +34 -3
  53. package/build/map/components/overlays/Cluster.d.ts +3 -1
  54. package/build/map/components/overlays/Cluster.js +31 -2
  55. package/build/map/components/overlays/HeatMap.d.ts +3 -1
  56. package/build/map/components/overlays/HeatMap.js +33 -3
  57. package/build/map/components/overlays/Marker.d.ts +1 -1
  58. package/build/map/components/overlays/Marker.js +37 -32
  59. package/build/map/components/overlays/MultiPoint.js +1 -1
  60. package/build/map/components/overlays/Polygon.js +30 -3
  61. package/build/map/components/overlays/Polyline.js +36 -3
  62. package/build/map/index.d.ts +25 -5
  63. package/build/map/index.js +59 -18
  64. package/build/map/types/common.types.d.ts +40 -0
  65. package/build/map/types/common.types.js +0 -4
  66. package/build/map/types/index.d.ts +3 -2
  67. package/build/map/types/map-view.types.d.ts +108 -3
  68. package/build/map/types/native-module.types.d.ts +363 -0
  69. package/build/map/types/native-module.types.js +5 -0
  70. package/build/map/types/offline.types.d.ts +132 -0
  71. package/build/map/types/offline.types.js +5 -0
  72. package/build/map/types/overlays.types.d.ts +137 -24
  73. package/build/map/utils/ErrorHandler.d.ts +110 -0
  74. package/build/map/utils/ErrorHandler.js +421 -0
  75. package/build/map/utils/GeoUtils.d.ts +20 -0
  76. package/build/map/utils/GeoUtils.js +76 -0
  77. package/build/map/utils/OfflineMapManager.d.ts +148 -0
  78. package/build/map/utils/OfflineMapManager.js +217 -0
  79. package/build/map/utils/PermissionUtils.d.ts +91 -0
  80. package/build/map/utils/PermissionUtils.js +255 -0
  81. package/build/map/utils/PlatformDetector.d.ts +102 -0
  82. package/build/map/utils/PlatformDetector.js +186 -0
  83. package/build/types/index.d.ts +1 -0
  84. package/build/types/index.js +1 -0
  85. package/build/types/native-module.types.d.ts +69 -0
  86. package/build/types/native-module.types.js +2 -0
  87. package/build/types/naviview.types.d.ts +1 -1
  88. package/expo-module.config.json +12 -10
  89. package/ios/ExpoGaodeMapNavigation.podspec +9 -0
  90. package/ios/map/ExpoGaodeMapModule.swift +485 -75
  91. package/ios/map/ExpoGaodeMapOfflineModule.swift +479 -0
  92. package/ios/map/ExpoGaodeMapView.swift +611 -62
  93. package/ios/map/ExpoGaodeMapViewModule.swift +48 -26
  94. package/ios/map/MapPreloadManager.swift +348 -0
  95. package/ios/map/cpp/ClusterEngine.cpp +110 -0
  96. package/ios/map/cpp/ClusterEngine.hpp +20 -0
  97. package/ios/map/cpp/ColorParser.cpp +135 -0
  98. package/ios/map/cpp/ColorParser.hpp +14 -0
  99. package/ios/map/cpp/GeometryEngine.cpp +574 -0
  100. package/ios/map/cpp/GeometryEngine.hpp +159 -0
  101. package/ios/map/cpp/QuadTree.cpp +92 -0
  102. package/ios/map/cpp/QuadTree.hpp +42 -0
  103. package/ios/map/cpp/README.md +55 -0
  104. package/ios/map/managers/UIManager.swift +72 -1
  105. package/ios/map/modules/LocationManager.swift +123 -166
  106. package/ios/map/overlays/CircleView.swift +16 -32
  107. package/ios/map/overlays/CircleViewModule.swift +12 -12
  108. package/ios/map/overlays/ClusterAnnotation.swift +32 -0
  109. package/ios/map/overlays/ClusterView.swift +331 -45
  110. package/ios/map/overlays/ClusterViewModule.swift +20 -6
  111. package/ios/map/overlays/HeatMapView.swift +135 -32
  112. package/ios/map/overlays/HeatMapViewModule.swift +20 -8
  113. package/ios/map/overlays/MarkerView.swift +613 -130
  114. package/ios/map/overlays/MarkerViewModule.swift +38 -18
  115. package/ios/map/overlays/MultiPointView.swift +168 -10
  116. package/ios/map/overlays/MultiPointViewModule.swift +27 -5
  117. package/ios/map/overlays/PolygonView.swift +62 -23
  118. package/ios/map/overlays/PolygonViewModule.swift +18 -12
  119. package/ios/map/overlays/PolylineView.swift +21 -13
  120. package/ios/map/overlays/PolylineViewModule.swift +18 -12
  121. package/ios/map/utils/ClusterNative.h +96 -0
  122. package/ios/map/utils/ClusterNative.mm +377 -0
  123. package/ios/map/utils/ColorParser.swift +12 -1
  124. package/ios/map/utils/CppBridging.mm +13 -0
  125. package/ios/map/utils/GeometryUtils.swift +34 -0
  126. package/ios/map/utils/LatLngParser.swift +87 -0
  127. package/ios/map/utils/PermissionManager.swift +135 -6
  128. package/package.json +3 -2
  129. package/shared/cpp/ClusterEngine.cpp +110 -0
  130. package/shared/cpp/ClusterEngine.hpp +20 -0
  131. package/shared/cpp/ColorParser.cpp +135 -0
  132. package/shared/cpp/ColorParser.hpp +14 -0
  133. package/shared/cpp/GeometryEngine.cpp +574 -0
  134. package/shared/cpp/GeometryEngine.hpp +159 -0
  135. package/shared/cpp/QuadTree.cpp +92 -0
  136. package/shared/cpp/QuadTree.hpp +42 -0
  137. package/shared/cpp/README.md +55 -0
  138. package/shared/cpp/tests/benchmark_js.js +41 -0
  139. package/shared/cpp/tests/run.sh +17 -0
  140. package/shared/cpp/tests/test_main.cpp +276 -0
  141. package/build/map/ExpoGaodeMap.types.d.ts +0 -41
  142. package/build/map/ExpoGaodeMap.types.js +0 -24
  143. package/build/map/utils/EventManager.d.ts +0 -10
  144. package/build/map/utils/EventManager.js +0 -26
  145. package/build/map/utils/ModuleLoader.d.ts +0 -73
  146. package/build/map/utils/ModuleLoader.js +0 -112
@@ -0,0 +1,139 @@
1
+ /**
2
+ * 高德地图离线地图原生模块
3
+ */
4
+ import { NativeModule } from 'expo';
5
+ import type { OfflineMapInfo, OfflineMapDownloadConfig, OfflineMapStorageInfo, OfflineMapEvents } from './types/offline.types';
6
+ /**
7
+ * 离线地图原生模块接口
8
+ */
9
+ declare class NaviMapOfflineModule extends NativeModule<OfflineMapEvents> {
10
+ /**
11
+ * 获取所有可下载的城市列表
12
+ * @returns Promise<OfflineMapInfo[]> 城市列表
13
+ */
14
+ getAvailableCities(): Promise<OfflineMapInfo[]>;
15
+ /**
16
+ * 获取所有省份列表
17
+ * @returns Promise<OfflineMapInfo[]> 省份列表
18
+ */
19
+ getAvailableProvinces(): Promise<OfflineMapInfo[]>;
20
+ /**
21
+ * 根据省份代码获取城市列表
22
+ * @param provinceCode 省份代码
23
+ * @returns Promise<OfflineMapInfo[]> 该省份下的城市列表
24
+ */
25
+ getCitiesByProvince(provinceCode: string): Promise<OfflineMapInfo[]>;
26
+ /**
27
+ * 获取已下载的地图列表
28
+ * @returns Promise<OfflineMapInfo[]> 已下载的地图列表
29
+ */
30
+ getDownloadedMaps(): Promise<OfflineMapInfo[]>;
31
+ /**
32
+ * 开始下载离线地图
33
+ * @param config 下载配置
34
+ */
35
+ startDownload(config: OfflineMapDownloadConfig): Promise<void>;
36
+ /**
37
+ * 暂停下载
38
+ * @param cityCode 城市代码
39
+ */
40
+ pauseDownload(cityCode: string): Promise<void>;
41
+ /**
42
+ * 恢复下载
43
+ * @param cityCode 城市代码
44
+ */
45
+ resumeDownload(cityCode: string): Promise<void>;
46
+ /**
47
+ * 取消下载
48
+ * @param cityCode 城市代码
49
+ */
50
+ cancelDownload(cityCode: string): Promise<void>;
51
+ /**
52
+ * 删除离线地图
53
+ * @param cityCode 城市代码
54
+ */
55
+ deleteMap(cityCode: string): Promise<void>;
56
+ /**
57
+ * 更新离线地图
58
+ * @param cityCode 城市代码
59
+ */
60
+ updateMap(cityCode: string): Promise<void>;
61
+ /**
62
+ * 检查是否有可用更新
63
+ * @param cityCode 城市代码
64
+ * @returns Promise<boolean> 是否有更新
65
+ */
66
+ checkUpdate(cityCode: string): Promise<boolean>;
67
+ /**
68
+ * 检查地图是否已下载
69
+ * @param cityCode 城市代码
70
+ * @returns Promise<boolean> 是否已下载
71
+ */
72
+ isMapDownloaded(cityCode: string): Promise<boolean>;
73
+ /**
74
+ * 获取地图下载状态
75
+ * @param cityCode 城市代码
76
+ * @returns Promise<OfflineMapInfo> 地图信息
77
+ */
78
+ getMapStatus(cityCode: string): Promise<OfflineMapInfo>;
79
+ /**
80
+ * 获取所有下载任务的总进度
81
+ * @returns Promise<number> 总进度 (0-100)
82
+ */
83
+ getTotalProgress(): Promise<number>;
84
+ /**
85
+ * 获取当前正在下载的城市列表
86
+ * @returns Promise<string[]> 城市代码列表
87
+ */
88
+ getDownloadingCities(): Promise<string[]>;
89
+ /**
90
+ * 获取离线地图占用的存储空间(字节)
91
+ * @returns Promise<number> 存储空间大小
92
+ */
93
+ getStorageSize(): Promise<number>;
94
+ /**
95
+ * 获取详细的存储信息
96
+ * @returns Promise<OfflineMapStorageInfo> 存储信息
97
+ */
98
+ getStorageInfo(): Promise<OfflineMapStorageInfo>;
99
+ /**
100
+ * 清理所有离线地图
101
+ */
102
+ clearAllMaps(): Promise<void>;
103
+ /**
104
+ * 设置离线地图存储路径
105
+ * @param path 存储路径
106
+ */
107
+ setStoragePath(path: string): void;
108
+ /**
109
+ * 获取离线地图存储路径
110
+ * @returns Promise<string> 存储路径
111
+ */
112
+ getStoragePath(): Promise<string>;
113
+ /**
114
+ * 批量下载地图
115
+ * @param cityCodes 城市代码列表
116
+ * @param allowCellular 是否允许移动网络
117
+ */
118
+ batchDownload(cityCodes: string[], allowCellular?: boolean): Promise<void>;
119
+ /**
120
+ * 批量删除地图
121
+ * @param cityCodes 城市代码列表
122
+ */
123
+ batchDelete(cityCodes: string[]): Promise<void>;
124
+ /**
125
+ * 批量更新地图
126
+ * @param cityCodes 城市代码列表
127
+ */
128
+ batchUpdate(cityCodes: string[]): Promise<void>;
129
+ /**
130
+ * 暂停所有下载任务
131
+ */
132
+ pauseAllDownloads(): Promise<void>;
133
+ /**
134
+ * 恢复所有下载任务
135
+ */
136
+ resumeAllDownloads(): Promise<void>;
137
+ }
138
+ declare const _default: NaviMapOfflineModule;
139
+ export default _default;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ /**
3
+ * 高德地图离线地图原生模块
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const expo_1 = require("expo");
7
+ // 获取原生模块实例
8
+ exports.default = (0, expo_1.requireNativeModule)('ExpoGaodeMapOffline');
@@ -35,7 +35,12 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const expo_modules_core_1 = require("expo-modules-core");
37
37
  const React = __importStar(require("react"));
38
- const NativeView = (0, expo_modules_core_1.requireNativeViewManager)('NaviMapView');
38
+ const GeoUtils_1 = require("./utils/GeoUtils");
39
+ const ErrorHandler_1 = require("./utils/ErrorHandler");
40
+ const MapContext_1 = require("./components/MapContext");
41
+ const MapUI_1 = require("./components/MapUI");
42
+ const react_native_1 = require("react-native");
43
+ const NativeView = (0, expo_modules_core_1.requireNativeViewManager)('ExpoGaodeMapView');
39
44
  /**
40
45
  * 高德地图视图组件,提供地图操作API和覆盖物管理功能
41
46
  *
@@ -57,63 +62,49 @@ const NativeView = (0, expo_modules_core_1.requireNativeViewManager)('NaviMapVie
57
62
  const ExpoGaodeMapView = React.forwardRef((props, ref) => {
58
63
  const nativeRef = React.useRef(null);
59
64
  const internalRef = React.useRef(null);
65
+ /**
66
+ * 🔑 性能优化:通用 API 方法包装器
67
+ * 统一处理初始化检查和错误处理,减少重复代码
68
+ */
69
+ const createApiMethod = React.useCallback((methodName) => {
70
+ return ((...args) => {
71
+ if (!nativeRef.current) {
72
+ throw ErrorHandler_1.ErrorHandler.mapViewNotInitialized(methodName);
73
+ }
74
+ try {
75
+ return nativeRef.current[methodName](...args);
76
+ }
77
+ catch (error) {
78
+ throw ErrorHandler_1.ErrorHandler.wrapNativeError(error, methodName);
79
+ }
80
+ });
81
+ }, []);
82
+ /**
83
+ * 使用通用包装器创建所有 API 方法
84
+ * 所有方法共享相同的错误处理逻辑
85
+ */
60
86
  const apiRef = React.useMemo(() => ({
61
- /**
62
- * 移动地图相机到指定位置
63
- * @param position 相机位置参数对象,包含目标经纬度、缩放级别等信息
64
- * @param duration 动画持续时间(毫秒),默认300毫秒
65
- * @throws 如果地图视图未初始化则抛出错误
66
- * @returns Promise<void> 异步操作完成后的Promise
67
- */
68
- moveCamera: async (position, duration = 300) => {
69
- if (!nativeRef.current)
70
- throw new Error('MapView not initialized');
71
- return nativeRef.current.moveCamera(position, duration);
72
- },
73
- /**
74
- * 将屏幕坐标点转换为地理坐标(经纬度)
75
- * @param point 屏幕坐标点 {x: number, y: number}
76
- * @returns 返回Promise,解析为对应的地理坐标 {latitude: number, longitude: number}
77
- * @throws 如果地图视图未初始化,抛出错误 'MapView not initialized'
78
- */
79
- getLatLng: async (point) => {
80
- if (!nativeRef.current)
81
- throw new Error('MapView not initialized');
82
- return nativeRef.current.getLatLng(point);
87
+ moveCamera: (position, duration) => {
88
+ if (!nativeRef.current) {
89
+ throw ErrorHandler_1.ErrorHandler.mapViewNotInitialized('moveCamera');
90
+ }
91
+ const normalizedPosition = {
92
+ ...position,
93
+ target: position.target ? (0, GeoUtils_1.normalizeLatLng)(position.target) : undefined,
94
+ };
95
+ return nativeRef.current.moveCamera(normalizedPosition, duration);
83
96
  },
84
- /**
85
- * 设置地图中心点坐标
86
- * @param center 要设置的中心点坐标(LatLng格式)
87
- * @param animated 是否使用动画效果移动地图(默认为false)
88
- * @throws 如果地图视图未初始化则抛出错误
89
- */
90
- setCenter: async (center, animated = false) => {
91
- if (!nativeRef.current)
92
- throw new Error('MapView not initialized');
93
- return nativeRef.current.setCenter(center, animated);
97
+ getLatLng: createApiMethod('getLatLng'),
98
+ setCenter: (center, animated) => {
99
+ if (!nativeRef.current) {
100
+ throw ErrorHandler_1.ErrorHandler.mapViewNotInitialized('setCenter');
101
+ }
102
+ return nativeRef.current.setCenter((0, GeoUtils_1.normalizeLatLng)(center), animated);
94
103
  },
95
- /**
96
- * 设置地图的缩放级别
97
- * @param zoom 目标缩放级别
98
- * @param animated 是否使用动画过渡效果,默认为false
99
- * @throws 如果地图视图未初始化,抛出错误
100
- */
101
- setZoom: async (zoom, animated = false) => {
102
- if (!nativeRef.current)
103
- throw new Error('MapView not initialized');
104
- return nativeRef.current.setZoom(zoom, animated);
105
- },
106
- /**
107
- * 获取当前地图的相机位置(视角中心点、缩放级别、倾斜角度等)
108
- * @returns 返回一个Promise,解析为当前相机位置的对象
109
- * @throws 如果地图视图未初始化,则抛出错误
110
- */
111
- getCameraPosition: async () => {
112
- if (!nativeRef.current)
113
- throw new Error('MapView not initialized');
114
- return nativeRef.current.getCameraPosition();
115
- }
116
- }), []);
104
+ setZoom: createApiMethod('setZoom'),
105
+ getCameraPosition: createApiMethod('getCameraPosition'),
106
+ takeSnapshot: createApiMethod('takeSnapshot'),
107
+ }), [createApiMethod]);
117
108
  /**
118
109
  * 将传入的apiRef赋值给internalRef.current
119
110
  * 用于在组件内部保存对地图API实例的引用
@@ -126,9 +117,26 @@ const ExpoGaodeMapView = React.forwardRef((props, ref) => {
126
117
  * @returns 返回地图API的引用对象,可用于调用地图相关方法
127
118
  */
128
119
  React.useImperativeHandle(ref, () => apiRef, [apiRef]);
129
- return (<NativeView ref={nativeRef} {...props}>
130
- {props.children}
131
- </NativeView>);
120
+ // 分离 children:区分原生覆盖物和普通 UI 组件
121
+ const { children, style, ...otherProps } = props;
122
+ const overlays = [];
123
+ const uiControls = [];
124
+ React.Children.forEach(children, (child) => {
125
+ if (React.isValidElement(child) && (child.type === MapUI_1.MapUI || child.type?.isMapUI)) {
126
+ uiControls.push(child);
127
+ }
128
+ else {
129
+ overlays.push(child);
130
+ }
131
+ });
132
+ return (<MapContext_1.MapContext.Provider value={apiRef}>
133
+ <react_native_1.View style={[{ flex: 1, position: 'relative', overflow: 'hidden', }, style]}>
134
+ <NativeView ref={nativeRef} style={react_native_1.StyleSheet.absoluteFill} {...otherProps}>
135
+ {overlays}
136
+ </NativeView>
137
+ {uiControls}
138
+ </react_native_1.View>
139
+ </MapContext_1.MapContext.Provider>);
132
140
  });
133
141
  ExpoGaodeMapView.displayName = 'ExpoGaodeMapView';
134
142
  exports.default = ExpoGaodeMapView;
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { DeviceInfo, FoldState } from '../utils/PlatformDetector';
3
+ import { MapViewProps, MapViewRef } from '../types';
4
+ /**
5
+ * 折叠屏适配配置
6
+ */
7
+ export interface FoldableConfig {
8
+ /** 折叠时是否自动调整缩放级别 */
9
+ autoAdjustZoom?: boolean;
10
+ /** 展开时的缩放级别增量 */
11
+ unfoldedZoomDelta?: number;
12
+ /** 是否在折叠/展开时保持中心点 */
13
+ keepCenterOnFold?: boolean;
14
+ /** 折叠状态变化回调 */
15
+ onFoldStateChange?: (state: FoldState, deviceInfo: DeviceInfo) => void;
16
+ /** 是否启用调试日志 */
17
+ debug?: boolean;
18
+ }
19
+ /**
20
+ * 折叠屏地图视图组件
21
+ *
22
+ * 自动适配折叠屏设备的展开/折叠状态变化
23
+ */
24
+ export interface FoldableMapViewProps extends MapViewProps {
25
+ /** 折叠屏适配配置 */
26
+ foldableConfig?: FoldableConfig;
27
+ }
28
+ export declare const FoldableMapView: React.FC<FoldableMapViewProps>;
29
+ /**
30
+ * 折叠屏适配 Hook
31
+ *
32
+ * 用于在现有地图组件中添加折叠屏适配功能
33
+ */
34
+ export declare function useFoldableMap(mapRef: React.RefObject<MapViewRef>, config?: FoldableConfig): {
35
+ foldState: FoldState;
36
+ deviceInfo: DeviceInfo;
37
+ isFoldable: boolean;
38
+ };
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FoldableMapView = void 0;
40
+ exports.useFoldableMap = useFoldableMap;
41
+ const react_1 = __importStar(require("react"));
42
+ const react_native_1 = require("react-native");
43
+ const ExpoGaodeMapView_1 = __importDefault(require("../ExpoGaodeMapView"));
44
+ const PlatformDetector_1 = require("../utils/PlatformDetector");
45
+ const FoldableMapView = ({ foldableConfig, ...mapProps }) => {
46
+ const mapRef = (0, react_1.useRef)(null);
47
+ const [currentFoldState, setCurrentFoldState] = (0, react_1.useState)(PlatformDetector_1.FoldState.UNKNOWN);
48
+ const [deviceInfo, setDeviceInfo] = (0, react_1.useState)(PlatformDetector_1.PlatformDetector.getDeviceInfo());
49
+ const config = {
50
+ autoAdjustZoom: true,
51
+ unfoldedZoomDelta: 1,
52
+ keepCenterOnFold: true,
53
+ onFoldStateChange: () => { },
54
+ debug: false,
55
+ ...foldableConfig,
56
+ };
57
+ (0, react_1.useEffect)(() => {
58
+ // 仅在 Android 折叠屏设备上启用
59
+ if (react_native_1.Platform.OS !== 'android' || !deviceInfo.isFoldable) {
60
+ if (config.debug) {
61
+ console.log('[FoldableMapView] 非折叠屏设备,跳过适配');
62
+ }
63
+ return;
64
+ }
65
+ if (config.debug) {
66
+ console.log('[FoldableMapView] 初始化折叠屏适配');
67
+ console.log('设备信息:', deviceInfo);
68
+ console.log('初始折叠状态:', currentFoldState);
69
+ }
70
+ // 监听屏幕尺寸变化
71
+ const removeListener = PlatformDetector_1.PlatformDetector.addDimensionChangeListener(async (newInfo) => {
72
+ const newFoldState = PlatformDetector_1.PlatformDetector.getFoldState();
73
+ if (config.debug) {
74
+ console.log('[FoldableMapView] 屏幕尺寸变化');
75
+ console.log('新设备信息:', newInfo);
76
+ console.log('新折叠状态:', newFoldState);
77
+ }
78
+ // 折叠状态变化时的处理
79
+ if (newFoldState !== currentFoldState && currentFoldState !== PlatformDetector_1.FoldState.UNKNOWN) {
80
+ await handleFoldStateChange(currentFoldState, newFoldState, newInfo);
81
+ }
82
+ setCurrentFoldState(newFoldState);
83
+ setDeviceInfo(newInfo);
84
+ // 触发回调
85
+ config.onFoldStateChange(newFoldState, newInfo);
86
+ });
87
+ // 设置初始状态
88
+ const initialState = PlatformDetector_1.PlatformDetector.getFoldState();
89
+ setCurrentFoldState(initialState);
90
+ return () => {
91
+ removeListener();
92
+ };
93
+ }, []);
94
+ /**
95
+ * 处理折叠状态变化
96
+ */
97
+ const handleFoldStateChange = async (oldState, newState, newInfo) => {
98
+ if (!mapRef.current) {
99
+ return;
100
+ }
101
+ try {
102
+ // 获取当前地图状态
103
+ const currentCamera = await mapRef.current.getCameraPosition?.();
104
+ if (!currentCamera) {
105
+ if (config.debug) {
106
+ console.warn('[FoldableMapView] 无法获取相机位置');
107
+ }
108
+ return;
109
+ }
110
+ const isUnfolding = newState === PlatformDetector_1.FoldState.UNFOLDED && oldState === PlatformDetector_1.FoldState.FOLDED;
111
+ const isFolding = newState === PlatformDetector_1.FoldState.FOLDED && oldState === PlatformDetector_1.FoldState.UNFOLDED;
112
+ if (config.debug) {
113
+ console.log('[FoldableMapView] 折叠状态变化:', {
114
+ oldState,
115
+ newState,
116
+ isUnfolding,
117
+ isFolding,
118
+ currentZoom: currentCamera.zoom,
119
+ });
120
+ }
121
+ // 展开时增加缩放级别,折叠时减少
122
+ if (config.autoAdjustZoom && (isUnfolding || isFolding)) {
123
+ const currentZoom = currentCamera.zoom ?? 15;
124
+ const zoomDelta = isUnfolding ? config.unfoldedZoomDelta : -config.unfoldedZoomDelta;
125
+ const newZoom = Math.max(3, Math.min(20, currentZoom + zoomDelta));
126
+ if (config.debug) {
127
+ console.log('[FoldableMapView] 调整缩放:', {
128
+ oldZoom: currentZoom,
129
+ newZoom,
130
+ delta: zoomDelta,
131
+ });
132
+ }
133
+ // 保持中心点,只调整缩放
134
+ await mapRef.current.moveCamera({
135
+ target: config.keepCenterOnFold ? currentCamera.target : undefined,
136
+ zoom: newZoom,
137
+ }, 300);
138
+ }
139
+ }
140
+ catch (error) {
141
+ if (config.debug) {
142
+ console.error('[FoldableMapView] 处理折叠状态变化失败:');
143
+ }
144
+ }
145
+ };
146
+ return (<ExpoGaodeMapView_1.default ref={mapRef} {...mapProps}/>);
147
+ };
148
+ exports.FoldableMapView = FoldableMapView;
149
+ /**
150
+ * 折叠屏适配 Hook
151
+ *
152
+ * 用于在现有地图组件中添加折叠屏适配功能
153
+ */
154
+ function useFoldableMap(mapRef, config) {
155
+ const [foldState, setFoldState] = (0, react_1.useState)(PlatformDetector_1.FoldState.UNKNOWN);
156
+ const [deviceInfo, setDeviceInfo] = (0, react_1.useState)(PlatformDetector_1.PlatformDetector.getDeviceInfo());
157
+ const mergedConfig = {
158
+ autoAdjustZoom: true,
159
+ unfoldedZoomDelta: 1,
160
+ keepCenterOnFold: true,
161
+ onFoldStateChange: () => { },
162
+ debug: false,
163
+ ...config,
164
+ };
165
+ (0, react_1.useEffect)(() => {
166
+ if (react_native_1.Platform.OS !== 'android' || !deviceInfo.isFoldable) {
167
+ return;
168
+ }
169
+ const removeListener = PlatformDetector_1.PlatformDetector.addDimensionChangeListener(async (newInfo) => {
170
+ const newFoldState = PlatformDetector_1.PlatformDetector.getFoldState();
171
+ if (newFoldState !== foldState && foldState !== PlatformDetector_1.FoldState.UNKNOWN) {
172
+ // 处理折叠状态变化
173
+ if (mapRef.current && mergedConfig.autoAdjustZoom) {
174
+ try {
175
+ const currentCamera = await mapRef.current.getCameraPosition();
176
+ if (currentCamera) {
177
+ const currentZoom = currentCamera.zoom ?? 15;
178
+ const isUnfolding = newFoldState === PlatformDetector_1.FoldState.UNFOLDED && foldState === PlatformDetector_1.FoldState.FOLDED;
179
+ const zoomDelta = isUnfolding ? mergedConfig.unfoldedZoomDelta : -mergedConfig.unfoldedZoomDelta;
180
+ const newZoom = Math.max(3, Math.min(20, currentZoom + zoomDelta));
181
+ await mapRef.current.moveCamera({
182
+ target: mergedConfig.keepCenterOnFold ? currentCamera.target : undefined,
183
+ zoom: newZoom,
184
+ }, 300);
185
+ }
186
+ }
187
+ catch (error) {
188
+ if (mergedConfig.debug) {
189
+ console.error('[useFoldableMap] 调整失败:');
190
+ }
191
+ }
192
+ }
193
+ }
194
+ setFoldState(newFoldState);
195
+ setDeviceInfo(newInfo);
196
+ mergedConfig.onFoldStateChange(newFoldState, newInfo);
197
+ });
198
+ const initialState = PlatformDetector_1.PlatformDetector.getFoldState();
199
+ setFoldState(initialState);
200
+ return () => {
201
+ removeListener();
202
+ };
203
+ }, [foldState, deviceInfo.isFoldable]);
204
+ return {
205
+ foldState,
206
+ deviceInfo,
207
+ isFoldable: deviceInfo.isFoldable,
208
+ };
209
+ }
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ import type { MapViewRef } from '../types';
3
+ /**
4
+ * 地图上下文
5
+ * 用于在子组件中访问地图实例的方法
6
+ */
7
+ export declare const MapContext: React.Context<MapViewRef | null>;
8
+ /**
9
+ * Hook: 获取地图实例引用
10
+ * 只能在 MapView 的子组件中使用
11
+ */
12
+ export declare function useMap(): MapViewRef;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MapContext = void 0;
37
+ exports.useMap = useMap;
38
+ const React = __importStar(require("react"));
39
+ /**
40
+ * 地图上下文
41
+ * 用于在子组件中访问地图实例的方法
42
+ */
43
+ exports.MapContext = React.createContext(null);
44
+ /**
45
+ * Hook: 获取地图实例引用
46
+ * 只能在 MapView 的子组件中使用
47
+ */
48
+ function useMap() {
49
+ const context = React.useContext(exports.MapContext);
50
+ if (!context) {
51
+ throw new Error('useMap must be used within a MapView component');
52
+ }
53
+ return context;
54
+ }
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ /**
3
+ * MapUI 组件
4
+ * 用于包裹不需要作为地图原生子组件(如 Marker)的普通 React 组件。
5
+ * 被此组件包裹的内容将渲染在地图视图的上方(兄弟节点),而不是内部。
6
+ * 这解决了在地图内部放置普通 View 导致的触摸事件冲突问题。
7
+ *
8
+ * 示例:
9
+ * <MapView>
10
+ * <Marker ... />
11
+ * <MapUI>
12
+ * <View style={{ position: 'absolute', ... }}>
13
+ * <Text>悬浮层</Text>
14
+ * </View>
15
+ * </MapUI>
16
+ * </MapView>
17
+ */
18
+ export declare const MapUI: React.FC<React.PropsWithChildren<{}>>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MapUI = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ /**
9
+ * MapUI 组件
10
+ * 用于包裹不需要作为地图原生子组件(如 Marker)的普通 React 组件。
11
+ * 被此组件包裹的内容将渲染在地图视图的上方(兄弟节点),而不是内部。
12
+ * 这解决了在地图内部放置普通 View 导致的触摸事件冲突问题。
13
+ *
14
+ * 示例:
15
+ * <MapView>
16
+ * <Marker ... />
17
+ * <MapUI>
18
+ * <View style={{ position: 'absolute', ... }}>
19
+ * <Text>悬浮层</Text>
20
+ * </View>
21
+ * </MapUI>
22
+ * </MapView>
23
+ */
24
+ const MapUI = ({ children }) => {
25
+ return <>{children}</>;
26
+ };
27
+ exports.MapUI = MapUI;
28
+ // 静态标志,用于识别
29
+ exports.MapUI.isMapUI = true;