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.
- package/README.md +213 -73
- package/android/build.gradle +10 -0
- package/android/src/main/cpp/CMakeLists.txt +24 -0
- package/android/src/main/cpp/cluster_jni.cpp +848 -0
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +616 -92
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +493 -0
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +230 -14
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapViewModule.kt +37 -27
- package/android/src/main/java/expo/modules/gaodemap/map/MapPreloadManager.kt +494 -0
- package/android/src/main/java/expo/modules/gaodemap/map/companion/BitmapDescriptorCache.kt +30 -0
- package/android/src/main/java/expo/modules/gaodemap/map/companion/IconBitmapCache.kt +37 -0
- package/android/src/main/java/expo/modules/gaodemap/map/managers/UIManager.kt +76 -0
- package/android/src/main/java/expo/modules/gaodemap/map/modules/LocationManager.kt +15 -3
- package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +4 -59
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleView.kt +9 -12
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleViewModule.kt +5 -6
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterView.kt +539 -66
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterViewModule.kt +17 -1
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapView.kt +165 -33
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapViewModule.kt +15 -3
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +1249 -672
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerViewModule.kt +40 -17
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointView.kt +177 -22
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointViewModule.kt +11 -3
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonView.kt +57 -14
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonViewModule.kt +9 -5
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineView.kt +90 -63
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineViewModule.kt +7 -3
- package/android/src/main/java/expo/modules/gaodemap/map/services/LocationForegroundService.kt +3 -2
- package/android/src/main/java/expo/modules/gaodemap/map/utils/BitmapDescriptorCache.kt +20 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/ClusterNative.kt +13 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/ColorParser.kt +20 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/GeometryUtils.kt +515 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/LatLngParser.kt +91 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/PermissionHelper.kt +248 -0
- package/build/ExpoGaodeMapNaviView.d.ts +7 -7
- package/build/ExpoGaodeMapNaviView.js +10 -11
- package/build/ExpoGaodeMapNavigationModule.d.ts +2 -1
- package/build/index.d.ts +35 -33
- package/build/index.js +70 -106
- package/build/map/ExpoGaodeMapModule.d.ts +2 -201
- package/build/map/ExpoGaodeMapModule.js +586 -18
- package/build/map/ExpoGaodeMapOfflineModule.d.ts +139 -0
- package/build/map/ExpoGaodeMapOfflineModule.js +8 -0
- package/build/map/ExpoGaodeMapView.js +66 -58
- package/build/map/components/FoldableMapView.d.ts +38 -0
- package/build/map/components/FoldableMapView.js +209 -0
- package/build/map/components/MapContext.d.ts +12 -0
- package/build/map/components/MapContext.js +54 -0
- package/build/map/components/MapUI.d.ts +18 -0
- package/build/map/components/MapUI.js +29 -0
- package/build/map/components/overlays/Circle.js +34 -3
- package/build/map/components/overlays/Cluster.d.ts +3 -1
- package/build/map/components/overlays/Cluster.js +31 -2
- package/build/map/components/overlays/HeatMap.d.ts +3 -1
- package/build/map/components/overlays/HeatMap.js +33 -3
- package/build/map/components/overlays/Marker.d.ts +1 -1
- package/build/map/components/overlays/Marker.js +37 -32
- package/build/map/components/overlays/MultiPoint.js +1 -1
- package/build/map/components/overlays/Polygon.js +30 -3
- package/build/map/components/overlays/Polyline.js +36 -3
- package/build/map/index.d.ts +25 -5
- package/build/map/index.js +59 -18
- package/build/map/types/common.types.d.ts +40 -0
- package/build/map/types/common.types.js +0 -4
- package/build/map/types/index.d.ts +3 -2
- package/build/map/types/map-view.types.d.ts +108 -3
- package/build/map/types/native-module.types.d.ts +363 -0
- package/build/map/types/native-module.types.js +5 -0
- package/build/map/types/offline.types.d.ts +132 -0
- package/build/map/types/offline.types.js +5 -0
- package/build/map/types/overlays.types.d.ts +137 -24
- package/build/map/utils/ErrorHandler.d.ts +110 -0
- package/build/map/utils/ErrorHandler.js +421 -0
- package/build/map/utils/GeoUtils.d.ts +20 -0
- package/build/map/utils/GeoUtils.js +76 -0
- package/build/map/utils/OfflineMapManager.d.ts +148 -0
- package/build/map/utils/OfflineMapManager.js +217 -0
- package/build/map/utils/PermissionUtils.d.ts +91 -0
- package/build/map/utils/PermissionUtils.js +255 -0
- package/build/map/utils/PlatformDetector.d.ts +102 -0
- package/build/map/utils/PlatformDetector.js +186 -0
- package/build/types/index.d.ts +1 -0
- package/build/types/index.js +1 -0
- package/build/types/native-module.types.d.ts +69 -0
- package/build/types/native-module.types.js +2 -0
- package/build/types/naviview.types.d.ts +1 -1
- package/expo-module.config.json +12 -10
- package/ios/ExpoGaodeMapNavigation.podspec +9 -0
- package/ios/map/ExpoGaodeMapModule.swift +485 -75
- package/ios/map/ExpoGaodeMapOfflineModule.swift +479 -0
- package/ios/map/ExpoGaodeMapView.swift +611 -62
- package/ios/map/ExpoGaodeMapViewModule.swift +48 -26
- package/ios/map/MapPreloadManager.swift +348 -0
- package/ios/map/cpp/ClusterEngine.cpp +110 -0
- package/ios/map/cpp/ClusterEngine.hpp +20 -0
- package/ios/map/cpp/ColorParser.cpp +135 -0
- package/ios/map/cpp/ColorParser.hpp +14 -0
- package/ios/map/cpp/GeometryEngine.cpp +574 -0
- package/ios/map/cpp/GeometryEngine.hpp +159 -0
- package/ios/map/cpp/QuadTree.cpp +92 -0
- package/ios/map/cpp/QuadTree.hpp +42 -0
- package/ios/map/cpp/README.md +55 -0
- package/ios/map/managers/UIManager.swift +72 -1
- package/ios/map/modules/LocationManager.swift +123 -166
- package/ios/map/overlays/CircleView.swift +16 -32
- package/ios/map/overlays/CircleViewModule.swift +12 -12
- package/ios/map/overlays/ClusterAnnotation.swift +32 -0
- package/ios/map/overlays/ClusterView.swift +331 -45
- package/ios/map/overlays/ClusterViewModule.swift +20 -6
- package/ios/map/overlays/HeatMapView.swift +135 -32
- package/ios/map/overlays/HeatMapViewModule.swift +20 -8
- package/ios/map/overlays/MarkerView.swift +613 -130
- package/ios/map/overlays/MarkerViewModule.swift +38 -18
- package/ios/map/overlays/MultiPointView.swift +168 -10
- package/ios/map/overlays/MultiPointViewModule.swift +27 -5
- package/ios/map/overlays/PolygonView.swift +62 -23
- package/ios/map/overlays/PolygonViewModule.swift +18 -12
- package/ios/map/overlays/PolylineView.swift +21 -13
- package/ios/map/overlays/PolylineViewModule.swift +18 -12
- package/ios/map/utils/ClusterNative.h +96 -0
- package/ios/map/utils/ClusterNative.mm +377 -0
- package/ios/map/utils/ColorParser.swift +12 -1
- package/ios/map/utils/CppBridging.mm +13 -0
- package/ios/map/utils/GeometryUtils.swift +34 -0
- package/ios/map/utils/LatLngParser.swift +87 -0
- package/ios/map/utils/PermissionManager.swift +135 -6
- package/package.json +3 -2
- package/shared/cpp/ClusterEngine.cpp +110 -0
- package/shared/cpp/ClusterEngine.hpp +20 -0
- package/shared/cpp/ColorParser.cpp +135 -0
- package/shared/cpp/ColorParser.hpp +14 -0
- package/shared/cpp/GeometryEngine.cpp +574 -0
- package/shared/cpp/GeometryEngine.hpp +159 -0
- package/shared/cpp/QuadTree.cpp +92 -0
- package/shared/cpp/QuadTree.hpp +42 -0
- package/shared/cpp/README.md +55 -0
- package/shared/cpp/tests/benchmark_js.js +41 -0
- package/shared/cpp/tests/run.sh +17 -0
- package/shared/cpp/tests/test_main.cpp +276 -0
- package/build/map/ExpoGaodeMap.types.d.ts +0 -41
- package/build/map/ExpoGaodeMap.types.js +0 -24
- package/build/map/utils/EventManager.d.ts +0 -10
- package/build/map/utils/EventManager.js +0 -26
- package/build/map/utils/ModuleLoader.d.ts +0 -73
- 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;
|
|
@@ -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
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
98
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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;
|