expo-gaode-map-navigation 2.0.11 → 2.0.12
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/android/src/main/cpp/cluster_jni.cpp +56 -0
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +45 -6
- package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +23 -17
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +37 -25
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerViewModule.kt +6 -6
- package/android/src/main/java/expo/modules/gaodemap/map/utils/GeometryUtils.kt +103 -0
- package/android/src/main/java/expo/modules/gaodemap/navigation/ExpoGaodeMapNaviView.kt +1 -1
- package/build/index.d.ts +10 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +6 -3
- package/build/index.js.map +1 -1
- package/build/map/ExpoGaodeMapModule.d.ts +15 -13
- package/build/map/ExpoGaodeMapModule.d.ts.map +1 -1
- package/build/map/ExpoGaodeMapModule.js +31 -39
- package/build/map/ExpoGaodeMapModule.js.map +1 -1
- package/build/map/ExpoGaodeMapView.d.ts +3 -4
- package/build/map/ExpoGaodeMapView.d.ts.map +1 -1
- package/build/map/ExpoGaodeMapView.js +28 -25
- package/build/map/ExpoGaodeMapView.js.map +1 -1
- package/build/map/components/overlays/Circle.d.ts.map +1 -1
- package/build/map/components/overlays/Circle.js +1 -30
- package/build/map/components/overlays/Circle.js.map +1 -1
- package/build/map/components/overlays/Cluster.d.ts.map +1 -1
- package/build/map/components/overlays/Cluster.js +1 -42
- package/build/map/components/overlays/Cluster.js.map +1 -1
- package/build/map/components/overlays/HeatMap.d.ts.map +1 -1
- package/build/map/components/overlays/HeatMap.js +1 -20
- package/build/map/components/overlays/HeatMap.js.map +1 -1
- package/build/map/components/overlays/Marker.d.ts.map +1 -1
- package/build/map/components/overlays/Marker.js +76 -80
- package/build/map/components/overlays/Marker.js.map +1 -1
- package/build/map/components/overlays/Polygon.d.ts.map +1 -1
- package/build/map/components/overlays/Polygon.js +1 -25
- package/build/map/components/overlays/Polygon.js.map +1 -1
- package/build/map/components/overlays/Polyline.d.ts.map +1 -1
- package/build/map/components/overlays/Polyline.js +1 -31
- package/build/map/components/overlays/Polyline.js.map +1 -1
- package/build/map/index.d.ts +6 -2
- package/build/map/index.d.ts.map +1 -1
- package/build/map/index.js +6 -2
- package/build/map/index.js.map +1 -1
- package/build/map/types/index.d.ts +2 -2
- package/build/map/types/index.d.ts.map +1 -1
- package/build/map/types/index.js.map +1 -1
- package/build/map/types/native-module.types.d.ts +11 -12
- package/build/map/types/native-module.types.d.ts.map +1 -1
- package/build/map/types/native-module.types.js.map +1 -1
- package/build/map/types/overlays.types.d.ts +9 -14
- package/build/map/types/overlays.types.d.ts.map +1 -1
- package/build/map/types/overlays.types.js.map +1 -1
- package/build/map/types/route-playback.types.d.ts +16 -0
- package/build/map/types/route-playback.types.d.ts.map +1 -1
- package/build/map/types/route-playback.types.js.map +1 -1
- package/build/types/coordinates.types.d.ts +3 -0
- package/build/types/coordinates.types.d.ts.map +1 -1
- package/build/types/coordinates.types.js.map +1 -1
- package/ios/ExpoGaodeMapNaviView.swift +31 -2
- package/ios/map/ExpoGaodeMapModule.swift +38 -6
- package/ios/map/ExpoGaodeMapView.swift +10 -3
- package/ios/map/GaodeMapPrivacyManager.swift +26 -18
- package/ios/map/cpp/GeometryEngine.cpp +112 -0
- package/ios/map/cpp/GeometryEngine.hpp +21 -0
- package/ios/map/modules/LocationManager.swift +1 -1
- package/ios/map/overlays/MarkerView.swift +11 -11
- package/ios/map/overlays/MarkerViewModule.swift +4 -4
- package/ios/map/utils/ClusterNative.h +8 -0
- package/ios/map/utils/ClusterNative.mm +27 -0
- package/package.json +6 -4
- package/scripts/check-expo-modules.js +68 -0
- package/shared/cpp/GeometryEngine.cpp +112 -0
- package/shared/cpp/GeometryEngine.hpp +21 -0
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { ImageSourcePropType, ViewStyle, NativeSyntheticEvent, TextStyle } from 'react-native';
|
|
6
6
|
import type { ColorValue, LatLng, LatLngPoint, Point } from './common.types';
|
|
7
|
+
import type { SmoothMoveEndEvent, SmoothMoveProgressEvent } from './route-playback.types';
|
|
7
8
|
/**
|
|
8
9
|
* 标记点属性
|
|
9
10
|
*/
|
|
@@ -84,20 +85,6 @@ export interface MarkerProps {
|
|
|
84
85
|
* 当使用 children 时,会将 React Native 组件渲染为图片显示在地图上
|
|
85
86
|
*/
|
|
86
87
|
children?: React.ReactNode;
|
|
87
|
-
/**
|
|
88
|
-
* 自定义视图宽度(像素)
|
|
89
|
-
* 仅在使用 children 属性时有效
|
|
90
|
-
* 通常可省略,组件会优先尝试自动测量 children 的布局尺寸
|
|
91
|
-
* 需要强制指定渲染尺寸时再传入
|
|
92
|
-
*/
|
|
93
|
-
customViewWidth?: number;
|
|
94
|
-
/**
|
|
95
|
-
* 自定义视图高度(像素)
|
|
96
|
-
* 仅在使用 children 属性时有效
|
|
97
|
-
* 通常可省略,组件会优先尝试自动测量 children 的布局尺寸
|
|
98
|
-
* 需要强制指定渲染尺寸时再传入
|
|
99
|
-
*/
|
|
100
|
-
customViewHeight?: number;
|
|
101
88
|
/**
|
|
102
89
|
* 缓存 key 建议使用 提高性能
|
|
103
90
|
*/
|
|
@@ -133,6 +120,14 @@ export interface MarkerProps {
|
|
|
133
120
|
* @default 10
|
|
134
121
|
*/
|
|
135
122
|
smoothMoveDuration?: number;
|
|
123
|
+
/**
|
|
124
|
+
* 平滑移动进度事件
|
|
125
|
+
*/
|
|
126
|
+
onSmoothMoveProgress?: (event: NativeSyntheticEvent<SmoothMoveProgressEvent>) => void;
|
|
127
|
+
/**
|
|
128
|
+
* 平滑移动完成事件
|
|
129
|
+
*/
|
|
130
|
+
onSmoothMoveEnd?: (event: NativeSyntheticEvent<SmoothMoveEndEvent>) => void;
|
|
136
131
|
}
|
|
137
132
|
/**
|
|
138
133
|
* 折线属性
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlays.types.d.ts","sourceRoot":"","sources":["../../../src/map/types/overlays.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"overlays.types.d.ts","sourceRoot":"","sources":["../../../src/map/types/overlays.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,wBAAwB,CAAC;AAEhC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,QAAQ,EAAE,WAAW,CAAC;IAEtB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IAEpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC;IAEf;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAE9G;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAE9D;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAElE;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAE7D;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAEhE;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,uBAAuB,CAAC,KAAK,IAAI,CAAC;IAEtF;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,kBAAkB,CAAC,KAAK,IAAI,CAAC;CAC7E;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,EAAE,WAAW,EAAE,CAAC;IAEtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,UAAU,CAAC;IAEzB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAEjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;IAExC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,UAAU,CAAC;IAEzB;;OAEG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAE3D;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAEjC;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;CACjH;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,MAAM,EAAE,WAAW,CAAC;IAEpB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,WAAW,CAAC,EAAE,UAAU,CAAC;IAEzB;;OAEG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;CAG3D;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,EAAE,UAAU,EAAE,CAAC;IAErB;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,IAAI,EAAE,WAAW,EAAE,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;IAE3B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,MAAM;IAC5C;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,MAAM,EAAE,cAAc,EAAE,CAAC;IAEzB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IAEpC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;CACpG;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC;IAEtB;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAC;IAEvB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,EAAE,CAAC;IAEvD;;OAEG;IACH,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAE7B;;OAEG;IACH,MAAM,EAAE,YAAY,EAAE,CAAC;IAEvB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,KAAK,CAAC,SAAS,CAAC;IAEvD;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,KAAK,CAAC,SAAS,CAAC;IAE3D;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;CACvE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlays.types.js","sourceRoot":"","sources":["../../../src/map/types/overlays.types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * 高德地图覆盖物相关类型定义\n * 基于 Expo Modules API\n */\n\nimport type { ImageSourcePropType, ViewStyle, NativeSyntheticEvent, TextStyle } from 'react-native';\nimport type { ColorValue, LatLng, LatLngPoint, Point } from './common.types';\n\n/**\n * 标记点属性\n */\nexport interface MarkerProps {\n /**\n * 坐标\n * 支持对象 {latitude, longitude} 或数组 [longitude, latitude]\n */\n position: LatLngPoint;\n\n /**\n * 图标\n */\n icon?: string | ImageSourcePropType;\n\n /**\n * 图标宽度(像素)\n * 仅在使用 icon 属性时有效\n */\n iconWidth?: number;\n\n /**\n * 图标高度(像素)\n * 仅在使用 icon 属性时有效\n */\n iconHeight?: number;\n\n /**\n * 标题\n */\n title?: string;\n\n /**\n * 描述\n */\n snippet?: string;\n\n /**\n * 透明度 [0, 1]\n * @platform android\n * @note iOS 不支持\n */\n opacity?: number;\n\n /**\n * 是否可拖拽\n * @default false\n */\n draggable?: boolean;\n\n /**\n * 是否平贴地图\n * @platform android\n * @note iOS 不支持\n */\n flat?: boolean;\n\n /**\n * 层级\n * @platform android\n * @note iOS 不支持 (使用 displayPriority)\n */\n zIndex?: number;\n\n /**\n * 覆盖物锚点比例\n * @platform android\n * @note iOS 使用 centerOffset\n */\n anchor?: Point;\n\n /**\n * 覆盖物偏移位置\n * @platform ios\n */\n centerOffset?: Point;\n\n /**\n * 是否显示动画\n * @platform ios\n */\n animatesDrop?: boolean;\n\n /**\n * 大头针颜色\n * Android 支持更多颜色,iOS 只支持 red, green, purple\n */\n pinColor?: 'red' | 'orange' | 'yellow' | 'green' | 'cyan' | 'blue' | 'violet' | 'magenta' | 'rose' | 'purple';\n\n /**\n * 自定义视图\n * 当使用 children 时,会将 React Native 组件渲染为图片显示在地图上\n */\n children?: React.ReactNode;\n\n /**\n *
|
|
1
|
+
{"version":3,"file":"overlays.types.js","sourceRoot":"","sources":["../../../src/map/types/overlays.types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * 高德地图覆盖物相关类型定义\n * 基于 Expo Modules API\n */\n\nimport type { ImageSourcePropType, ViewStyle, NativeSyntheticEvent, TextStyle } from 'react-native';\nimport type { ColorValue, LatLng, LatLngPoint, Point } from './common.types';\nimport type {\n SmoothMoveEndEvent,\n SmoothMoveProgressEvent,\n} from './route-playback.types';\n\n/**\n * 标记点属性\n */\nexport interface MarkerProps {\n /**\n * 坐标\n * 支持对象 {latitude, longitude} 或数组 [longitude, latitude]\n */\n position: LatLngPoint;\n\n /**\n * 图标\n */\n icon?: string | ImageSourcePropType;\n\n /**\n * 图标宽度(像素)\n * 仅在使用 icon 属性时有效\n */\n iconWidth?: number;\n\n /**\n * 图标高度(像素)\n * 仅在使用 icon 属性时有效\n */\n iconHeight?: number;\n\n /**\n * 标题\n */\n title?: string;\n\n /**\n * 描述\n */\n snippet?: string;\n\n /**\n * 透明度 [0, 1]\n * @platform android\n * @note iOS 不支持\n */\n opacity?: number;\n\n /**\n * 是否可拖拽\n * @default false\n */\n draggable?: boolean;\n\n /**\n * 是否平贴地图\n * @platform android\n * @note iOS 不支持\n */\n flat?: boolean;\n\n /**\n * 层级\n * @platform android\n * @note iOS 不支持 (使用 displayPriority)\n */\n zIndex?: number;\n\n /**\n * 覆盖物锚点比例\n * @platform android\n * @note iOS 使用 centerOffset\n */\n anchor?: Point;\n\n /**\n * 覆盖物偏移位置\n * @platform ios\n */\n centerOffset?: Point;\n\n /**\n * 是否显示动画\n * @platform ios\n */\n animatesDrop?: boolean;\n\n /**\n * 大头针颜色\n * Android 支持更多颜色,iOS 只支持 red, green, purple\n */\n pinColor?: 'red' | 'orange' | 'yellow' | 'green' | 'cyan' | 'blue' | 'violet' | 'magenta' | 'rose' | 'purple';\n\n /**\n * 自定义视图\n * 当使用 children 时,会将 React Native 组件渲染为图片显示在地图上\n */\n children?: React.ReactNode;\n\n /**\n * 缓存 key 建议使用 提高性能\n */\n cacheKey?: string;\n\n /**\n * 是否开启生长动画\n * @default false\n */\n growAnimation?: boolean;\n\n /**\n * 点击事件\n */\n onMarkerPress?: (event: NativeSyntheticEvent<LatLng>) => void;\n\n /**\n * 拖拽开始事件\n */\n onMarkerDragStart?: (event: NativeSyntheticEvent<LatLng>) => void;\n\n /**\n * 拖拽中事件\n */\n onMarkerDrag?: (event: NativeSyntheticEvent<LatLng>) => void;\n\n /**\n * 拖拽结束事件\n */\n onMarkerDragEnd?: (event: NativeSyntheticEvent<LatLng>) => void;\n\n /**\n * 平滑移动轨迹点数组\n * 设置后,Marker 会沿着轨迹平滑移动\n */\n smoothMovePath?: LatLng[];\n\n /**\n * 平滑移动总时长(秒)\n * @default 10\n */\n smoothMoveDuration?: number;\n\n /**\n * 平滑移动进度事件\n */\n onSmoothMoveProgress?: (event: NativeSyntheticEvent<SmoothMoveProgressEvent>) => void;\n\n /**\n * 平滑移动完成事件\n */\n onSmoothMoveEnd?: (event: NativeSyntheticEvent<SmoothMoveEndEvent>) => void;\n}\n\n/**\n * 折线属性\n */\nexport interface PolylineProps {\n /**\n * 节点坐标数组\n * 支持对象 {latitude, longitude} 或数组 [longitude, latitude]\n */\n points: LatLngPoint[];\n\n /**\n * 线宽\n */\n strokeWidth?: number;\n\n /**\n * 线条颜色\n */\n strokeColor?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 分段颜色\n */\n colors?: ColorValue[];\n\n /**\n * 是否使用渐变色\n * @platform android\n * @note iOS 不支持\n */\n gradient?: boolean;\n\n /**\n * 是否绘制大地线\n * @platform android\n * @note iOS 不支持\n */\n geodesic?: boolean;\n\n /**\n * 轨迹抽稀容差(米)\n * 设置大于 0 的值时启用 RDP 算法简化轨迹点\n * 建议值为 1.0 - 5.0,值越大简化程度越高\n */\n simplificationTolerance?: number;\n\n /**\n * 是否绘制虚线\n * @platform android\n * @note iOS 不支持\n */\n dotted?: boolean;\n\n /**\n * 纹理图片\n * 支持网络图片(http/https)、本地文件(file://)或资源名称\n */\n texture?: string;\n\n /**\n * 点击事件\n */\n onPolylinePress?: (event: NativeSyntheticEvent<{}>) => void;\n}\n\n/**\n * 多边形属性\n */\nexport interface PolygonProps {\n /**\n * 节点坐标数组\n * 支持对象 {latitude, longitude} 或数组 [longitude, latitude]\n * 同时也支持嵌套数组格式 [[p1, p2, ...], [p3, p4, ...]],用于定义带孔的多边形\n * 其中第一个数组为外轮廓,后续数组为内孔\n */\n points: LatLngPoint[] | LatLngPoint[][];\n\n /**\n * 边线宽度\n */\n strokeWidth?: number;\n\n /**\n * 边线颜色\n */\n strokeColor?: ColorValue;\n\n /**\n * 填充颜色\n */\n fillColor?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 点击事件\n */\n onPolygonPress?: (event: NativeSyntheticEvent<{}>) => void;\n\n /**\n * 轨迹抽稀容差(米)\n * 设置大于 0 的值时启用 RDP 算法简化多边形边界\n * 建议值为 1.0 - 5.0,值越大简化程度越高\n */\n simplificationTolerance?: number;\n\n /**\n * 简化完成事件\n */\n onPolygonSimplified?: (event: NativeSyntheticEvent<{ originalCount: number; simplifiedCount: number }>) => void;\n}\n\n/**\n * 圆形属性\n */\nexport interface CircleProps {\n /**\n * 圆心坐标\n * 支持对象 {latitude, longitude} 或数组 [longitude, latitude]\n */\n center: LatLngPoint;\n\n /**\n * 半径(米)\n */\n radius: number;\n\n /**\n * 边线宽度\n */\n strokeWidth?: number;\n\n /**\n * 边线颜色\n */\n strokeColor?: ColorValue;\n\n /**\n * 填充颜色\n */\n fillColor?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 点击事件\n */\n onCirclePress?: (event: NativeSyntheticEvent<{}>) => void;\n\n\n}\n\n/**\n * 热力图渐变配置\n */\nexport interface HeatMapGradient {\n /**\n * 颜色数组\n * 支持 '#RRGGBB', 'rgba()', 'red' 等\n */\n colors: ColorValue[];\n \n /**\n * 颜色起始点数组 [0-1]\n * 必须递增,例如 [0.2, 0.5, 0.9]\n */\n startPoints: number[];\n}\n\n/**\n * 热力图属性\n */\nexport interface HeatMapProps {\n /**\n * 热力点数据\n * 支持对象 {latitude, longitude} 或数组 [longitude, latitude]\n */\n data: LatLngPoint[];\n\n /**\n * 是否显示热力图(用于避免频繁卸载/重建导致卡顿)\n */\n visible?: boolean;\n\n /**\n * 热力半径(米)\n */\n radius?: number;\n\n /**\n * 透明度 [0, 1]\n */\n opacity?: number;\n\n /**\n * 热力图渐变配置\n */\n gradient?: HeatMapGradient;\n\n /**\n * 是否开启高清热力图(Retina适配)\n * @platform ios\n */\n allowRetinaAdapting?: boolean;\n}\n\n/**\n * 海量点标记项\n */\nexport interface MultiPointItem extends LatLng {\n /**\n * 唯一标识\n */\n id?: string | number;\n\n /**\n * 自定义数据\n */\n data?: unknown;\n}\n\n/**\n * 海量点属性\n */\nexport interface MultiPointProps {\n /**\n * 点集合\n */\n points: MultiPointItem[];\n\n /**\n * 图标\n */\n icon?: string | ImageSourcePropType; \n\n /**\n * 图标宽度\n */\n iconWidth?: number;\n\n /**\n * 图标高度\n */\n iconHeight?: number;\n\n /**\n * 点击事件\n */\n onMultiPointPress?: (event: NativeSyntheticEvent<{ index: number; item: MultiPointItem }>) => void;\n}\n\n/**\n * 聚合点参数\n */\nexport interface ClusterParams {\n /**\n * 包含的标记点数量\n */\n count: number;\n\n /**\n * 纬度\n */\n latitude: number;\n\n /**\n * 经度\n */\n longitude: number;\n\n /**\n * 包含的点数据列表\n */\n pois?: ClusterPoint[];\n\n /**\n * 唯一标识 (兼容性保留)\n */\n id?: number;\n\n /**\n * 聚合点坐标 (兼容性保留)\n */\n position?: LatLng;\n}\n\n/**\n * 聚合点项\n */\nexport interface ClusterPoint {\n /**\n * 纬度(原生 Cluster 使用)\n */\n latitude?: number;\n \n /**\n * 经度(原生 Cluster 使用)\n */\n longitude?: number;\n\n /**\n * 坐标(JS ClusterLayer 使用)\n */\n position?: LatLngPoint;\n\n /**\n * 自定义数据\n */\n properties?: Record<string, unknown>;\n}\n\n/**\n * 聚合图层属性\n */\nexport interface ClusterProps {\n /**\n * 聚合点基础图标\n * 当前支持远程 URL、本地文件路径或原生资源名称\n */\n icon?: string;\n\n /**\n * 聚合半径\n */\n radius?: number;\n\n /**\n * 最小聚合数量\n */\n minClusterSize?: number;\n\n /**\n * 聚合点样式\n */\n clusterStyle?: ViewStyle;\n\n /**\n * 分级聚合样式配置\n * 根据聚合数量动态设置样式\n */\n clusterBuckets?: ({ minPoints: number } & ViewStyle)[];\n\n /**\n * 聚合点文本样式\n */\n clusterTextStyle?: TextStyle;\n\n /**\n * 坐标点列表\n */\n points: ClusterPoint[];\n\n /**\n * 暂未实现,请勿使用\n */\n renderMarker?: (item: ClusterPoint) => React.ReactNode;\n\n /**\n * 暂未实现,请勿使用\n */\n renderCluster?: (params: ClusterParams) => React.ReactNode;\n\n /**\n * 聚合点点击事件\n */\n onClusterPress?: (event: NativeSyntheticEvent<ClusterParams>) => void;\n}\n"]}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import type { NativeSyntheticEvent } from 'react-native';
|
|
2
|
+
import type { LatLng } from './common.types';
|
|
3
|
+
export interface SmoothMoveProgressEvent {
|
|
4
|
+
position: LatLng;
|
|
5
|
+
angle: number;
|
|
6
|
+
progress: number;
|
|
7
|
+
distance: number;
|
|
8
|
+
totalDistance: number;
|
|
9
|
+
}
|
|
10
|
+
export interface SmoothMoveEndEvent {
|
|
11
|
+
position: LatLng;
|
|
12
|
+
angle: number;
|
|
13
|
+
totalDistance: number;
|
|
14
|
+
}
|
|
1
15
|
export interface FitToCoordinatesOptions {
|
|
2
16
|
duration?: number;
|
|
3
17
|
paddingFactor?: number;
|
|
@@ -9,4 +23,6 @@ export interface FitToCoordinatesOptions {
|
|
|
9
23
|
preserveBearing?: boolean;
|
|
10
24
|
preserveTilt?: boolean;
|
|
11
25
|
}
|
|
26
|
+
export type SmoothMoveProgressEventHandler = (event: NativeSyntheticEvent<SmoothMoveProgressEvent>) => void;
|
|
27
|
+
export type SmoothMoveEndEventHandler = (event: NativeSyntheticEvent<SmoothMoveEndEvent>) => void;
|
|
12
28
|
//# sourceMappingURL=route-playback.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-playback.types.d.ts","sourceRoot":"","sources":["../../../src/map/types/route-playback.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}
|
|
1
|
+
{"version":3,"file":"route-playback.types.d.ts","sourceRoot":"","sources":["../../../src/map/types/route-playback.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,8BAA8B,GAAG,CAC3C,KAAK,EAAE,oBAAoB,CAAC,uBAAuB,CAAC,KACjD,IAAI,CAAC;AAEV,MAAM,MAAM,yBAAyB,GAAG,CACtC,KAAK,EAAE,oBAAoB,CAAC,kBAAkB,CAAC,KAC5C,IAAI,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-playback.types.js","sourceRoot":"","sources":["../../../src/map/types/route-playback.types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"route-playback.types.js","sourceRoot":"","sources":["../../../src/map/types/route-playback.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { NativeSyntheticEvent } from 'react-native';\n\nimport type { LatLng } from './common.types';\n\nexport interface SmoothMoveProgressEvent {\n position: LatLng;\n angle: number;\n progress: number;\n distance: number;\n totalDistance: number;\n}\n\nexport interface SmoothMoveEndEvent {\n position: LatLng;\n angle: number;\n totalDistance: number;\n}\n\nexport interface FitToCoordinatesOptions {\n duration?: number;\n paddingFactor?: number;\n minZoom?: number;\n maxZoom?: number;\n singlePointZoom?: number;\n bearing?: number;\n tilt?: number;\n preserveBearing?: boolean;\n preserveTilt?: boolean;\n}\n\nexport type SmoothMoveProgressEventHandler = (\n event: NativeSyntheticEvent<SmoothMoveProgressEvent>\n) => void;\n\nexport type SmoothMoveEndEventHandler = (\n event: NativeSyntheticEvent<SmoothMoveEndEvent>\n) => void;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinates.types.d.ts","sourceRoot":"","sources":["../../src/types/coordinates.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,SAAS;IACT,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"coordinates.types.d.ts","sourceRoot":"","sources":["../../src/types/coordinates.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,SAAS;IACT,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinates.types.js","sourceRoot":"","sources":["../../src/types/coordinates.types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * 导航模块坐标类型定义\n * 简化版本,仅包含导航所需的基础坐标\n */\n\n/**\n * 导航坐标点(简化版)\n */\nexport interface NaviPoint {\n latitude: number;\n longitude: number;\n}\n\n/**\n * 带名称的坐标点(POI)\n */\nexport interface NamedCoordinates extends NaviPoint {\n /** 名称 */\n name?: string;\n /** POI ID */\n poiId?: string;\n}\n\n
|
|
1
|
+
{"version":3,"file":"coordinates.types.js","sourceRoot":"","sources":["../../src/types/coordinates.types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * 导航模块坐标类型定义\n * 简化版本,仅包含导航所需的基础坐标\n */\n\n/**\n * 导航坐标点(简化版)\n */\nexport interface NaviPoint {\n latitude: number;\n longitude: number;\n}\n\n/**\n * 带名称的坐标点(POI)\n */\nexport interface NamedCoordinates extends NaviPoint {\n /** 名称 */\n name?: string;\n /** POI ID */\n poiId?: string;\n}\n\n/**\n * @deprecated 请使用 `NaviPoint`\n */\nexport type Coordinates = NaviPoint;\n"]}
|
|
@@ -306,7 +306,7 @@ public class ExpoGaodeMapNaviView: ExpoView {
|
|
|
306
306
|
code: -1002,
|
|
307
307
|
userInfo: [
|
|
308
308
|
NSLocalizedDescriptionKey: "隐私协议未完成确认",
|
|
309
|
-
NSLocalizedFailureReasonErrorKey: "请先调用 setPrivacyConfig
|
|
309
|
+
NSLocalizedFailureReasonErrorKey: "请先调用 setPrivacyConfig 并确保参数为 true",
|
|
310
310
|
NSLocalizedRecoverySuggestionErrorKey: "建议在首次启动弹窗同意后再进入导航页面。"
|
|
311
311
|
]
|
|
312
312
|
)
|
|
@@ -427,6 +427,7 @@ public class ExpoGaodeMapNaviView: ExpoView {
|
|
|
427
427
|
private var walkManager: AMapNaviWalkManager?
|
|
428
428
|
private var rideManager: AMapNaviRideManager?
|
|
429
429
|
private var lastKnownSpeed: Int = 0
|
|
430
|
+
private var currentNaviRoute: AMapNaviRoute?
|
|
430
431
|
private var currentRouteTotalLength: Int?
|
|
431
432
|
private var lastNavigationInfoPayload: [String: Any]?
|
|
432
433
|
private var lastTurnIconType: Int?
|
|
@@ -911,6 +912,7 @@ public class ExpoGaodeMapNaviView: ExpoView {
|
|
|
911
912
|
hasStartedNavi = false
|
|
912
913
|
hasReceivedFirstNaviData = false
|
|
913
914
|
lastKnownSpeed = 0
|
|
915
|
+
currentNaviRoute = nil
|
|
914
916
|
currentRouteTotalLength = nil
|
|
915
917
|
trafficBarTotalLength = nil
|
|
916
918
|
lastNavigationInfoPayload = nil
|
|
@@ -2117,7 +2119,7 @@ public class ExpoGaodeMapNaviView: ExpoView {
|
|
|
2117
2119
|
}
|
|
2118
2120
|
|
|
2119
2121
|
private func navigationInfoPayload(from naviInfo: AMapNaviInfo) -> [String: Any] {
|
|
2120
|
-
[
|
|
2122
|
+
var payload: [String: Any] = [
|
|
2121
2123
|
"naviMode": naviInfo.naviMode.rawValue,
|
|
2122
2124
|
"currentRoadName": naviInfo.currentRoadName ?? "",
|
|
2123
2125
|
"nextRoadName": naviInfo.nextRoadName ?? "",
|
|
@@ -2135,6 +2137,12 @@ public class ExpoGaodeMapNaviView: ExpoView {
|
|
|
2135
2137
|
"driveDistance": naviInfo.routeDriveDistance,
|
|
2136
2138
|
"driveTime": naviInfo.routeDriveTime
|
|
2137
2139
|
]
|
|
2140
|
+
|
|
2141
|
+
if let nextIconType = resolveNextTurnIconType(currentSegmentIndex: naviInfo.currentSegmentIndex) {
|
|
2142
|
+
payload["nextIconType"] = nextIconType
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
return payload
|
|
2138
2146
|
}
|
|
2139
2147
|
|
|
2140
2148
|
private func handleNavigationInfoUpdate(_ naviInfo: AMapNaviInfo) {
|
|
@@ -2146,6 +2154,24 @@ public class ExpoGaodeMapNaviView: ExpoView {
|
|
|
2146
2154
|
emitNavigationInfoUpdate(navigationInfoPayload(from: naviInfo))
|
|
2147
2155
|
}
|
|
2148
2156
|
|
|
2157
|
+
private func resolveNextTurnIconType(currentSegmentIndex: Int) -> Int? {
|
|
2158
|
+
guard currentSegmentIndex >= 0 else {
|
|
2159
|
+
return nil
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
guard let routeSegments = currentNaviRoute?.routeSegments else {
|
|
2163
|
+
return nil
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
let nextSegmentIndex = currentSegmentIndex + 1
|
|
2167
|
+
guard routeSegments.indices.contains(nextSegmentIndex) else {
|
|
2168
|
+
return nil
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
let nextIconType = Int(routeSegments[nextSegmentIndex].iconType.rawValue)
|
|
2172
|
+
return nextIconType > 0 ? nextIconType : nil
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2149
2175
|
private func handleNavigationSound(_ soundString: String, soundStringType: AMapNaviSoundType) {
|
|
2150
2176
|
activateNavigationAudioSessionIfNeeded(reason: "play_navi_sound")
|
|
2151
2177
|
onNavigationText([
|
|
@@ -2467,6 +2493,7 @@ extension ExpoGaodeMapNaviView: AMapNaviDriveViewDelegate {
|
|
|
2467
2493
|
|
|
2468
2494
|
extension ExpoGaodeMapNaviView: AMapNaviDriveDataRepresentable {
|
|
2469
2495
|
public func driveManager(_ driveManager: AMapNaviDriveManager, update naviRoute: AMapNaviRoute?) {
|
|
2496
|
+
currentNaviRoute = naviRoute
|
|
2470
2497
|
if let routeLength = naviRoute?.routeLength, routeLength > 0 {
|
|
2471
2498
|
currentRouteTotalLength = routeLength
|
|
2472
2499
|
}
|
|
@@ -2604,6 +2631,7 @@ extension ExpoGaodeMapNaviView: AMapNaviWalkViewDelegate {
|
|
|
2604
2631
|
|
|
2605
2632
|
extension ExpoGaodeMapNaviView: AMapNaviWalkDataRepresentable {
|
|
2606
2633
|
public func walkManager(_ walkManager: AMapNaviWalkManager, update naviRoute: AMapNaviRoute?) {
|
|
2634
|
+
currentNaviRoute = naviRoute
|
|
2607
2635
|
if let routeLength = naviRoute?.routeLength, routeLength > 0 {
|
|
2608
2636
|
currentRouteTotalLength = routeLength
|
|
2609
2637
|
}
|
|
@@ -2680,6 +2708,7 @@ extension ExpoGaodeMapNaviView: AMapNaviRideViewDelegate {
|
|
|
2680
2708
|
|
|
2681
2709
|
extension ExpoGaodeMapNaviView: AMapNaviRideDataRepresentable {
|
|
2682
2710
|
public func rideManager(_ rideManager: AMapNaviRideManager, update naviRoute: AMapNaviRoute?) {
|
|
2711
|
+
currentNaviRoute = naviRoute
|
|
2683
2712
|
if let routeLength = naviRoute?.routeLength, routeLength > 0 {
|
|
2684
2713
|
currentRouteTotalLength = routeLength
|
|
2685
2714
|
}
|
|
@@ -48,12 +48,19 @@ public class ExpoGaodeMapModule: Module {
|
|
|
48
48
|
_ = self.trySetupApiKeyFromPlist()
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
Function("
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
Function("setPrivacyConfig") { (config: [String: Any]) in
|
|
52
|
+
let hasShow = config["hasShow"] as? Bool ?? false
|
|
53
|
+
let hasContainsPrivacy = config["hasContainsPrivacy"] as? Bool ?? hasShow
|
|
54
|
+
let hasAgree = config["hasAgree"] as? Bool ?? false
|
|
55
|
+
let privacyVersion = config["privacyVersion"] as? String
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
GaodeMapPrivacyManager.setPrivacyConfig(
|
|
58
|
+
hasShow: hasShow,
|
|
59
|
+
hasContainsPrivacy: hasContainsPrivacy,
|
|
60
|
+
hasAgree: hasAgree,
|
|
61
|
+
privacyVersion: privacyVersion,
|
|
62
|
+
updatesPrivacyVersion: config.keys.contains("privacyVersion")
|
|
63
|
+
)
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
Function("setPrivacyVersion") { (version: String) in
|
|
@@ -76,7 +83,7 @@ public class ExpoGaodeMapModule: Module {
|
|
|
76
83
|
*/
|
|
77
84
|
Function("initSDK") { (config: [String: String]) in
|
|
78
85
|
guard GaodeMapPrivacyManager.isReady else {
|
|
79
|
-
throw Exception(name: "PRIVACY_NOT_AGREED", description: "隐私协议未完成确认,请先调用
|
|
86
|
+
throw Exception(name: "PRIVACY_NOT_AGREED", description: "隐私协议未完成确认,请先调用 setPrivacyConfig")
|
|
80
87
|
}
|
|
81
88
|
GaodeMapPrivacyManager.applyPrivacyState()
|
|
82
89
|
|
|
@@ -272,6 +279,31 @@ public class ExpoGaodeMapModule: Module {
|
|
|
272
279
|
}
|
|
273
280
|
return ClusterNative.calculateDistance(lat1: coord1.latitude, lon1: coord1.longitude, lat2: coord2.latitude, lon2: coord2.longitude)
|
|
274
281
|
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* 根据多个坐标点计算可同时可见的推荐缩放级别
|
|
285
|
+
*/
|
|
286
|
+
Function("calculateFitZoom") {
|
|
287
|
+
(points: [Any]?, viewportWidthPx: Double?, viewportHeightPx: Double?, paddingPx: Double?, minZoom: Int?, maxZoom: Int?) -> Double in
|
|
288
|
+
let coords = LatLngParser.parseLatLngList(points)
|
|
289
|
+
let safeMinZoom = minZoom ?? 3
|
|
290
|
+
let safeMaxZoom = maxZoom ?? 20
|
|
291
|
+
if coords.isEmpty {
|
|
292
|
+
return Double(safeMinZoom)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
let lats = coords.map { NSNumber(value: $0.latitude) }
|
|
296
|
+
let lons = coords.map { NSNumber(value: $0.longitude) }
|
|
297
|
+
return ClusterNative.calculateFitZoom(
|
|
298
|
+
latitudes: lats,
|
|
299
|
+
longitudes: lons,
|
|
300
|
+
viewportWidthPx: viewportWidthPx ?? 390.0,
|
|
301
|
+
viewportHeightPx: viewportHeightPx ?? 844.0,
|
|
302
|
+
paddingPx: paddingPx ?? 48.0,
|
|
303
|
+
minZoom: Int32(safeMinZoom),
|
|
304
|
+
maxZoom: Int32(safeMaxZoom)
|
|
305
|
+
)
|
|
306
|
+
}
|
|
275
307
|
|
|
276
308
|
/**
|
|
277
309
|
* 计算多边形面积
|
|
@@ -1454,17 +1454,24 @@ extension ExpoGaodeMapView {
|
|
|
1454
1454
|
isHandlingAnnotationSelect = true
|
|
1455
1455
|
|
|
1456
1456
|
// 🔑 统一从 overlayViews 查找 MarkerView(新旧架构统一)
|
|
1457
|
-
for
|
|
1458
|
-
if let markerView =
|
|
1457
|
+
for overlayView in overlayViews {
|
|
1458
|
+
if let markerView = overlayView as? MarkerView {
|
|
1459
1459
|
if markerView.annotation === annotation {
|
|
1460
1460
|
let eventData: [String: Any] = [
|
|
1461
1461
|
"latitude": annotation.coordinate.latitude,
|
|
1462
1462
|
"longitude": annotation.coordinate.longitude
|
|
1463
1463
|
]
|
|
1464
1464
|
markerView.onMarkerPress(eventData)
|
|
1465
|
+
// iOS 对“已选中 annotation”再次点击通常不会重复触发 didSelect。
|
|
1466
|
+
// 对自定义 children marker(无系统 callout)这里主动取消选中,
|
|
1467
|
+
// 以保证同一 marker 可以连续触发点击(例如关闭 sheet 后再次点击)。
|
|
1468
|
+
if !markerView.subviews.isEmpty {
|
|
1469
|
+
mapView.deselectAnnotation(annotation, animated: false)
|
|
1470
|
+
isHandlingAnnotationSelect = false
|
|
1471
|
+
}
|
|
1465
1472
|
return
|
|
1466
1473
|
}
|
|
1467
|
-
} else if let clusterView =
|
|
1474
|
+
} else if let clusterView = overlayView as? ClusterView {
|
|
1468
1475
|
if clusterView.containsAnnotation(annotation) {
|
|
1469
1476
|
clusterView.handleAnnotationTap(annotation)
|
|
1470
1477
|
return
|
|
@@ -46,24 +46,6 @@ enum GaodeMapPrivacyManager {
|
|
|
46
46
|
applyPrivacyState()
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
static func setPrivacyShow(_ show: Bool, hasContainsPrivacy: Bool) {
|
|
50
|
-
let previousStatus = status()
|
|
51
|
-
hasShow = show
|
|
52
|
-
self.hasContainsPrivacy = hasContainsPrivacy
|
|
53
|
-
persistState()
|
|
54
|
-
applyPrivacyState()
|
|
55
|
-
notifyIfNeeded(previousStatus: previousStatus)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static func setPrivacyAgree(_ agree: Bool) {
|
|
59
|
-
let previousStatus = status()
|
|
60
|
-
hasAgree = agree
|
|
61
|
-
agreedPrivacyVersion = agree ? privacyVersion : nil
|
|
62
|
-
persistState()
|
|
63
|
-
applyPrivacyState()
|
|
64
|
-
notifyIfNeeded(previousStatus: previousStatus)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
49
|
static func setPrivacyVersion(_ version: String) {
|
|
68
50
|
let previousStatus = status()
|
|
69
51
|
privacyVersion = version.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
@@ -83,6 +65,32 @@ enum GaodeMapPrivacyManager {
|
|
|
83
65
|
notifyIfNeeded(previousStatus: previousStatus)
|
|
84
66
|
}
|
|
85
67
|
|
|
68
|
+
static func setPrivacyConfig(
|
|
69
|
+
hasShow: Bool,
|
|
70
|
+
hasContainsPrivacy: Bool,
|
|
71
|
+
hasAgree: Bool,
|
|
72
|
+
privacyVersion newPrivacyVersion: String?,
|
|
73
|
+
updatesPrivacyVersion: Bool
|
|
74
|
+
) {
|
|
75
|
+
let previousStatus = status()
|
|
76
|
+
|
|
77
|
+
if updatesPrivacyVersion {
|
|
78
|
+
privacyVersion = newPrivacyVersion?.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
79
|
+
if privacyVersion?.isEmpty == true {
|
|
80
|
+
privacyVersion = nil
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
self.hasShow = hasShow
|
|
85
|
+
self.hasContainsPrivacy = hasContainsPrivacy
|
|
86
|
+
self.hasAgree = hasAgree
|
|
87
|
+
agreedPrivacyVersion = hasAgree ? privacyVersion : nil
|
|
88
|
+
|
|
89
|
+
persistState()
|
|
90
|
+
applyPrivacyState()
|
|
91
|
+
notifyIfNeeded(previousStatus: previousStatus)
|
|
92
|
+
}
|
|
93
|
+
|
|
86
94
|
static func resetPrivacyConsent() {
|
|
87
95
|
let previousStatus = status()
|
|
88
96
|
clearConsentPersistedState(keepCurrentVersion: false)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include <cmath>
|
|
4
4
|
#include <map>
|
|
5
5
|
#include <algorithm>
|
|
6
|
+
#include <limits>
|
|
6
7
|
|
|
7
8
|
namespace gaodemap {
|
|
8
9
|
|
|
@@ -19,6 +20,54 @@ static inline double geo_toDegrees(double radians) {
|
|
|
19
20
|
return radians * kRadiansToDegrees;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
static inline double clampMercatorLatitude(double lat) {
|
|
24
|
+
static constexpr double kMaxMercatorLatitude = 85.05112878;
|
|
25
|
+
if (lat > kMaxMercatorLatitude) return kMaxMercatorLatitude;
|
|
26
|
+
if (lat < -kMaxMercatorLatitude) return -kMaxMercatorLatitude;
|
|
27
|
+
return lat;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static inline double mercatorX01(double lon) {
|
|
31
|
+
double wrapped = std::fmod(lon + 180.0, 360.0);
|
|
32
|
+
if (wrapped < 0.0) {
|
|
33
|
+
wrapped += 360.0;
|
|
34
|
+
}
|
|
35
|
+
return wrapped / 360.0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static inline double mercatorY01(double lat) {
|
|
39
|
+
const double clampedLat = clampMercatorLatitude(lat);
|
|
40
|
+
const double latRad = geo_toRadians(clampedLat);
|
|
41
|
+
const double y = (1.0 - std::asinh(std::tan(latRad)) / kPi) * 0.5;
|
|
42
|
+
if (y < 0.0) return 0.0;
|
|
43
|
+
if (y > 1.0) return 1.0;
|
|
44
|
+
return y;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static double wrappedSpan01(std::vector<double> xs) {
|
|
48
|
+
if (xs.size() <= 1) {
|
|
49
|
+
return 0.0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
std::sort(xs.begin(), xs.end());
|
|
53
|
+
double maxGap = 0.0;
|
|
54
|
+
|
|
55
|
+
for (size_t i = 0; i + 1 < xs.size(); ++i) {
|
|
56
|
+
const double gap = xs[i + 1] - xs[i];
|
|
57
|
+
if (gap > maxGap) {
|
|
58
|
+
maxGap = gap;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const double endGap = xs.front() + 1.0 - xs.back();
|
|
63
|
+
if (endGap > maxGap) {
|
|
64
|
+
maxGap = endGap;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const double span = 1.0 - maxGap;
|
|
68
|
+
return span < 0.0 ? 0.0 : span;
|
|
69
|
+
}
|
|
70
|
+
|
|
22
71
|
double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
|
|
23
72
|
const double radLat1 = geo_toRadians(lat1);
|
|
24
73
|
const double radLat2 = geo_toRadians(lat2);
|
|
@@ -512,6 +561,69 @@ GeoPoint pixelToLatLng(double x, double y, int zoom) {
|
|
|
512
561
|
return {lat, lon};
|
|
513
562
|
}
|
|
514
563
|
|
|
564
|
+
double calculateFitZoomForPoints(
|
|
565
|
+
const std::vector<GeoPoint>& points,
|
|
566
|
+
double viewportWidthPx,
|
|
567
|
+
double viewportHeightPx,
|
|
568
|
+
double paddingPx,
|
|
569
|
+
int minZoom,
|
|
570
|
+
int maxZoom
|
|
571
|
+
) {
|
|
572
|
+
if (minZoom > maxZoom) {
|
|
573
|
+
std::swap(minZoom, maxZoom);
|
|
574
|
+
}
|
|
575
|
+
if (points.empty()) {
|
|
576
|
+
return static_cast<double>(minZoom);
|
|
577
|
+
}
|
|
578
|
+
if (points.size() == 1) {
|
|
579
|
+
return static_cast<double>(maxZoom);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const double safeViewportWidth = viewportWidthPx > 1.0 ? viewportWidthPx : 390.0;
|
|
583
|
+
const double safeViewportHeight = viewportHeightPx > 1.0 ? viewportHeightPx : 844.0;
|
|
584
|
+
const double safePadding = std::max(0.0, paddingPx);
|
|
585
|
+
const double availableWidth = std::max(1.0, safeViewportWidth - safePadding * 2.0);
|
|
586
|
+
const double availableHeight = std::max(1.0, safeViewportHeight - safePadding * 2.0);
|
|
587
|
+
|
|
588
|
+
std::vector<double> projectedXs;
|
|
589
|
+
projectedXs.reserve(points.size());
|
|
590
|
+
|
|
591
|
+
double minY = std::numeric_limits<double>::max();
|
|
592
|
+
double maxY = -std::numeric_limits<double>::max();
|
|
593
|
+
|
|
594
|
+
for (const auto& p : points) {
|
|
595
|
+
projectedXs.push_back(mercatorX01(p.lon));
|
|
596
|
+
const double y = mercatorY01(p.lat);
|
|
597
|
+
if (y < minY) minY = y;
|
|
598
|
+
if (y > maxY) maxY = y;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const double spanX = wrappedSpan01(projectedXs);
|
|
602
|
+
const double spanY = std::max(0.0, maxY - minY);
|
|
603
|
+
static constexpr double kTileSize = 256.0;
|
|
604
|
+
static constexpr double kSpanEpsilon = 1e-12;
|
|
605
|
+
|
|
606
|
+
const double zoomX = spanX <= kSpanEpsilon
|
|
607
|
+
? static_cast<double>(maxZoom)
|
|
608
|
+
: std::log2(availableWidth / (kTileSize * spanX));
|
|
609
|
+
const double zoomY = spanY <= kSpanEpsilon
|
|
610
|
+
? static_cast<double>(maxZoom)
|
|
611
|
+
: std::log2(availableHeight / (kTileSize * spanY));
|
|
612
|
+
|
|
613
|
+
double fitZoom = std::min(zoomX, zoomY);
|
|
614
|
+
if (!std::isfinite(fitZoom)) {
|
|
615
|
+
fitZoom = static_cast<double>(minZoom);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (fitZoom < static_cast<double>(minZoom)) {
|
|
619
|
+
fitZoom = static_cast<double>(minZoom);
|
|
620
|
+
} else if (fitZoom > static_cast<double>(maxZoom)) {
|
|
621
|
+
fitZoom = static_cast<double>(maxZoom);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
return fitZoom;
|
|
625
|
+
}
|
|
626
|
+
|
|
515
627
|
// --- 批量地理围栏与热力图 ---
|
|
516
628
|
|
|
517
629
|
int findPointInPolygons(double pointLat, double pointLon, const std::vector<std::vector<GeoPoint>>& polygons) {
|
|
@@ -125,6 +125,27 @@ PixelResult latLngToPixel(double lat, double lon, int zoom);
|
|
|
125
125
|
*/
|
|
126
126
|
GeoPoint pixelToLatLng(double x, double y, int zoom);
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* 根据一组坐标点和视口尺寸计算“可同时看到所有点”的推荐缩放级别。
|
|
130
|
+
* 使用 Web Mercator 投影,在跨经线场景下会自动取更小经度跨度。
|
|
131
|
+
*
|
|
132
|
+
* @param points 坐标点集合,至少 1 个
|
|
133
|
+
* @param viewportWidthPx 视口宽度(像素)
|
|
134
|
+
* @param viewportHeightPx 视口高度(像素)
|
|
135
|
+
* @param paddingPx 四周预留的内边距(像素)
|
|
136
|
+
* @param minZoom 最小缩放级别
|
|
137
|
+
* @param maxZoom 最大缩放级别
|
|
138
|
+
* @return 推荐 zoom(已在 [minZoom, maxZoom] 范围内)
|
|
139
|
+
*/
|
|
140
|
+
double calculateFitZoomForPoints(
|
|
141
|
+
const std::vector<GeoPoint>& points,
|
|
142
|
+
double viewportWidthPx,
|
|
143
|
+
double viewportHeightPx,
|
|
144
|
+
double paddingPx,
|
|
145
|
+
int minZoom,
|
|
146
|
+
int maxZoom
|
|
147
|
+
);
|
|
148
|
+
|
|
128
149
|
// --- 批量地理围栏与热力图 ---
|
|
129
150
|
|
|
130
151
|
/**
|
|
@@ -225,7 +225,7 @@ class LocationManager: NSObject, AMapLocationManagerDelegate {
|
|
|
225
225
|
*/
|
|
226
226
|
func coordinateConvert(_ coordinate: [String: Double], type: Int, promise: Promise) {
|
|
227
227
|
guard GaodeMapPrivacyManager.isReady else {
|
|
228
|
-
promise.reject("PRIVACY_NOT_AGREED", "隐私协议未完成确认,请先调用
|
|
228
|
+
promise.reject("PRIVACY_NOT_AGREED", "隐私协议未完成确认,请先调用 setPrivacyConfig")
|
|
229
229
|
return
|
|
230
230
|
}
|
|
231
231
|
|
|
@@ -37,9 +37,9 @@ class MarkerView: ExpoView {
|
|
|
37
37
|
/// 图标高度(用于自定义图标 icon 属性)
|
|
38
38
|
var iconHeight: Double = 40
|
|
39
39
|
/// 自定义视图宽度(用于 children 属性)
|
|
40
|
-
var
|
|
40
|
+
var contentWidth: Double = 0
|
|
41
41
|
/// 自定义视图高度(用于 children 属性)
|
|
42
|
-
var
|
|
42
|
+
var contentHeight: Double = 0
|
|
43
43
|
/// 中心偏移
|
|
44
44
|
var centerOffset: [String: Double]?
|
|
45
45
|
/// 是否显示动画
|
|
@@ -585,9 +585,9 @@ class MarkerView: ExpoView {
|
|
|
585
585
|
return defaultSize
|
|
586
586
|
}
|
|
587
587
|
|
|
588
|
-
if
|
|
589
|
-
let width =
|
|
590
|
-
let height =
|
|
588
|
+
if contentWidth > 0 || contentHeight > 0 {
|
|
589
|
+
let width = contentWidth > 0 ? CGFloat(contentWidth) : defaultSize.width
|
|
590
|
+
let height = contentHeight > 0 ? CGFloat(contentHeight) : defaultSize.height
|
|
591
591
|
return CGSize(width: width, height: height)
|
|
592
592
|
}
|
|
593
593
|
|
|
@@ -1000,17 +1000,17 @@ class MarkerView: ExpoView {
|
|
|
1000
1000
|
}
|
|
1001
1001
|
}
|
|
1002
1002
|
|
|
1003
|
-
func
|
|
1004
|
-
guard
|
|
1005
|
-
|
|
1003
|
+
func setContentWidth(_ width: Double) {
|
|
1004
|
+
guard contentWidth != width else { return }
|
|
1005
|
+
contentWidth = width
|
|
1006
1006
|
if !subviews.isEmpty {
|
|
1007
1007
|
refreshAnnotationAppearance(invalidateChildrenCache: true)
|
|
1008
1008
|
}
|
|
1009
1009
|
}
|
|
1010
1010
|
|
|
1011
|
-
func
|
|
1012
|
-
guard
|
|
1013
|
-
|
|
1011
|
+
func setContentHeight(_ height: Double) {
|
|
1012
|
+
guard contentHeight != height else { return }
|
|
1013
|
+
contentHeight = height
|
|
1014
1014
|
if !subviews.isEmpty {
|
|
1015
1015
|
refreshAnnotationAppearance(invalidateChildrenCache: true)
|
|
1016
1016
|
}
|