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
|
@@ -653,6 +653,62 @@ Java_expo_modules_gaodemap_map_utils_GeometryUtils_nativeCalculateCentroid(
|
|
|
653
653
|
#endif
|
|
654
654
|
}
|
|
655
655
|
|
|
656
|
+
extern "C" JNIEXPORT jdouble JNICALL
|
|
657
|
+
Java_expo_modules_gaodemap_map_utils_GeometryUtils_nativeCalculateFitZoom(
|
|
658
|
+
JNIEnv* env,
|
|
659
|
+
jclass,
|
|
660
|
+
jdoubleArray latitudes,
|
|
661
|
+
jdoubleArray longitudes,
|
|
662
|
+
jdouble viewportWidthPx,
|
|
663
|
+
jdouble viewportHeightPx,
|
|
664
|
+
jdouble paddingPx,
|
|
665
|
+
jint minZoom,
|
|
666
|
+
jint maxZoom
|
|
667
|
+
) {
|
|
668
|
+
#if GAODE_HAVE_JNI
|
|
669
|
+
if (!latitudes || !longitudes) {
|
|
670
|
+
return static_cast<jdouble>(minZoom);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const jsize countLat = env->GetArrayLength(latitudes);
|
|
674
|
+
const jsize countLon = env->GetArrayLength(longitudes);
|
|
675
|
+
if (countLat == 0 || countLat != countLon) {
|
|
676
|
+
return static_cast<jdouble>(minZoom);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
jdouble* latValues = env->GetDoubleArrayElements(latitudes, nullptr);
|
|
680
|
+
jdouble* lonValues = env->GetDoubleArrayElements(longitudes, nullptr);
|
|
681
|
+
|
|
682
|
+
std::vector<gaodemap::GeoPoint> points;
|
|
683
|
+
points.reserve(static_cast<size_t>(countLat));
|
|
684
|
+
for (jsize i = 0; i < countLat; ++i) {
|
|
685
|
+
points.push_back({latValues[i], lonValues[i]});
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
env->ReleaseDoubleArrayElements(latitudes, latValues, JNI_ABORT);
|
|
689
|
+
env->ReleaseDoubleArrayElements(longitudes, lonValues, JNI_ABORT);
|
|
690
|
+
|
|
691
|
+
return static_cast<jdouble>(gaodemap::calculateFitZoomForPoints(
|
|
692
|
+
points,
|
|
693
|
+
static_cast<double>(viewportWidthPx),
|
|
694
|
+
static_cast<double>(viewportHeightPx),
|
|
695
|
+
static_cast<double>(paddingPx),
|
|
696
|
+
static_cast<int>(minZoom),
|
|
697
|
+
static_cast<int>(maxZoom)
|
|
698
|
+
));
|
|
699
|
+
#else
|
|
700
|
+
(void)env;
|
|
701
|
+
(void)latitudes;
|
|
702
|
+
(void)longitudes;
|
|
703
|
+
(void)viewportWidthPx;
|
|
704
|
+
(void)viewportHeightPx;
|
|
705
|
+
(void)paddingPx;
|
|
706
|
+
(void)minZoom;
|
|
707
|
+
(void)maxZoom;
|
|
708
|
+
return 3.0;
|
|
709
|
+
#endif
|
|
710
|
+
}
|
|
711
|
+
|
|
656
712
|
extern "C" JNIEXPORT jstring JNICALL
|
|
657
713
|
Java_expo_modules_gaodemap_map_utils_GeometryUtils_nativeEncodeGeoHash(
|
|
658
714
|
JNIEnv* env,
|
|
@@ -51,7 +51,7 @@ class ExpoGaodeMapModule : Module() {
|
|
|
51
51
|
} else if (!SDKInitializer.isPrivacyReady()) {
|
|
52
52
|
throw expo.modules.kotlin.exception.CodedException(
|
|
53
53
|
"PRIVACY_NOT_AGREED",
|
|
54
|
-
"隐私协议未完成确认,请先调用
|
|
54
|
+
"隐私协议未完成确认,请先调用 setPrivacyConfig",
|
|
55
55
|
null
|
|
56
56
|
)
|
|
57
57
|
} else {
|
|
@@ -68,12 +68,20 @@ class ExpoGaodeMapModule : Module() {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
Function("
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
Function("setPrivacyConfig") { config: Map<String, Any?> ->
|
|
72
|
+
val hasShow = config["hasShow"] as? Boolean ?: false
|
|
73
|
+
val hasContainsPrivacy = config["hasContainsPrivacy"] as? Boolean ?: hasShow
|
|
74
|
+
val hasAgree = config["hasAgree"] as? Boolean ?: false
|
|
75
|
+
val privacyVersion = config["privacyVersion"] as? String
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
SDKInitializer.setPrivacyConfig(
|
|
78
|
+
appContext.reactContext!!,
|
|
79
|
+
hasShow,
|
|
80
|
+
hasContainsPrivacy,
|
|
81
|
+
hasAgree,
|
|
82
|
+
privacyVersion,
|
|
83
|
+
config.containsKey("privacyVersion")
|
|
84
|
+
)
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
Function("setPrivacyVersion") { version: String ->
|
|
@@ -186,6 +194,37 @@ class ExpoGaodeMapModule : Module() {
|
|
|
186
194
|
}
|
|
187
195
|
}
|
|
188
196
|
|
|
197
|
+
/**
|
|
198
|
+
* 根据多个坐标点计算可同时可见的推荐缩放级别
|
|
199
|
+
* @param points 坐标点(至少 1 个)
|
|
200
|
+
* @param viewportWidthPx 视口宽度(像素)
|
|
201
|
+
* @param viewportHeightPx 视口高度(像素)
|
|
202
|
+
* @param paddingPx 内边距(像素)
|
|
203
|
+
* @param minZoom 最小缩放
|
|
204
|
+
* @param maxZoom 最大缩放
|
|
205
|
+
*/
|
|
206
|
+
Function("calculateFitZoom") {
|
|
207
|
+
points: List<Any>?,
|
|
208
|
+
viewportWidthPx: Double?,
|
|
209
|
+
viewportHeightPx: Double?,
|
|
210
|
+
paddingPx: Double?,
|
|
211
|
+
minZoom: Int?,
|
|
212
|
+
maxZoom: Int? ->
|
|
213
|
+
val normalized = LatLngParser.parseLatLngList(points)
|
|
214
|
+
val safeMinZoom = minZoom ?: 3
|
|
215
|
+
val safeMaxZoom = maxZoom ?: 20
|
|
216
|
+
if (normalized.isEmpty()) return@Function safeMinZoom.toDouble()
|
|
217
|
+
|
|
218
|
+
GeometryUtils.calculateFitZoom(
|
|
219
|
+
normalized,
|
|
220
|
+
viewportWidthPx ?: 390.0,
|
|
221
|
+
viewportHeightPx ?: 844.0,
|
|
222
|
+
paddingPx ?: 48.0,
|
|
223
|
+
safeMinZoom,
|
|
224
|
+
safeMaxZoom
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
|
|
189
228
|
/**
|
|
190
229
|
* 计算多边形面积
|
|
191
230
|
* @param points 多边形顶点坐标数组,支持嵌套数组(多边形空洞)
|
|
@@ -56,22 +56,6 @@ object SDKInitializer {
|
|
|
56
56
|
applyPrivacyState(appContext)
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
fun setPrivacyShow(context: Context, hasShow: Boolean, hasContainsPrivacy: Boolean) {
|
|
60
|
-
privacyShown = hasShow
|
|
61
|
-
privacyContains = hasContainsPrivacy
|
|
62
|
-
val appContext = resolveContext(context)
|
|
63
|
-
persistState(appContext)
|
|
64
|
-
applyPrivacyState(appContext)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
fun setPrivacyAgree(context: Context, hasAgree: Boolean) {
|
|
68
|
-
privacyAgreed = hasAgree
|
|
69
|
-
agreedPrivacyVersion = if (hasAgree) privacyVersion else null
|
|
70
|
-
val appContext = resolveContext(context)
|
|
71
|
-
persistState(appContext)
|
|
72
|
-
applyPrivacyState(appContext)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
59
|
fun setPrivacyVersion(context: Context, version: String) {
|
|
76
60
|
val sanitizedVersion = version.trim().takeIf { it.isNotEmpty() }
|
|
77
61
|
privacyVersion = sanitizedVersion
|
|
@@ -89,6 +73,28 @@ object SDKInitializer {
|
|
|
89
73
|
applyPrivacyState(appContext)
|
|
90
74
|
}
|
|
91
75
|
|
|
76
|
+
fun setPrivacyConfig(
|
|
77
|
+
context: Context,
|
|
78
|
+
hasShow: Boolean,
|
|
79
|
+
hasContainsPrivacy: Boolean,
|
|
80
|
+
hasAgree: Boolean,
|
|
81
|
+
version: String?,
|
|
82
|
+
shouldUpdateVersion: Boolean
|
|
83
|
+
) {
|
|
84
|
+
val appContext = resolveContext(context)
|
|
85
|
+
|
|
86
|
+
if (shouldUpdateVersion) {
|
|
87
|
+
privacyVersion = version?.trim()?.takeIf { it.isNotEmpty() }
|
|
88
|
+
}
|
|
89
|
+
privacyShown = hasShow
|
|
90
|
+
privacyContains = hasContainsPrivacy
|
|
91
|
+
privacyAgreed = hasAgree
|
|
92
|
+
agreedPrivacyVersion = if (hasAgree) privacyVersion else null
|
|
93
|
+
|
|
94
|
+
persistState(appContext)
|
|
95
|
+
applyPrivacyState(appContext)
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
fun resetPrivacyConsent(context: Context) {
|
|
93
99
|
val appContext = resolveContext(context)
|
|
94
100
|
clearConsentPersistedState(appContext, keepCurrentVersion = false)
|
|
@@ -138,7 +144,7 @@ object SDKInitializer {
|
|
|
138
144
|
if (!isPrivacyReady()) {
|
|
139
145
|
throw expo.modules.kotlin.exception.CodedException(
|
|
140
146
|
"PRIVACY_NOT_AGREED",
|
|
141
|
-
"隐私协议未完成确认,请先调用
|
|
147
|
+
"隐私协议未完成确认,请先调用 setPrivacyConfig",
|
|
142
148
|
null
|
|
143
149
|
)
|
|
144
150
|
}
|
|
@@ -99,16 +99,16 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
99
99
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
100
100
|
val selfParams = this.layoutParams
|
|
101
101
|
if (selfParams == null || selfParams !is LayoutParams) {
|
|
102
|
-
val width = if (
|
|
103
|
-
|
|
102
|
+
val width = if (contentWidth > 0) {
|
|
103
|
+
contentWidth
|
|
104
104
|
} else if (selfParams != null && selfParams.width > 0) {
|
|
105
105
|
selfParams.width
|
|
106
106
|
} else {
|
|
107
107
|
LayoutParams.WRAP_CONTENT
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
val height = if (
|
|
111
|
-
|
|
110
|
+
val height = if (contentHeight > 0) {
|
|
111
|
+
contentHeight
|
|
112
112
|
} else if (selfParams != null && selfParams.height > 0) {
|
|
113
113
|
selfParams.height
|
|
114
114
|
} else {
|
|
@@ -140,12 +140,12 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
140
140
|
val fallbackHeightSize = resolveExplicitMeasureSize(parentHeightSize, false)
|
|
141
141
|
|
|
142
142
|
val contentWidthSpec = when {
|
|
143
|
-
|
|
143
|
+
contentWidth > 0 -> MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY)
|
|
144
144
|
fallbackWidthSize > 0 -> MeasureSpec.makeMeasureSpec(fallbackWidthSize, MeasureSpec.AT_MOST)
|
|
145
145
|
else -> MeasureSpec.makeMeasureSpec(1, MeasureSpec.EXACTLY)
|
|
146
146
|
}
|
|
147
147
|
val contentHeightSpec = when {
|
|
148
|
-
|
|
148
|
+
contentHeight > 0 -> MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY)
|
|
149
149
|
fallbackHeightSize > 0 -> MeasureSpec.makeMeasureSpec(fallbackHeightSize, MeasureSpec.AT_MOST)
|
|
150
150
|
else -> MeasureSpec.makeMeasureSpec(1, MeasureSpec.EXACTLY)
|
|
151
151
|
}
|
|
@@ -175,13 +175,13 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
175
175
|
measuredContentHeight = max(measuredContentHeight, childBounds?.height() ?: child.measuredHeight)
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
val desiredWidth = if (
|
|
179
|
-
|
|
178
|
+
val desiredWidth = if (contentWidth > 0) {
|
|
179
|
+
contentWidth
|
|
180
180
|
} else {
|
|
181
181
|
measuredContentWidth + paddingLeft + paddingRight
|
|
182
182
|
}
|
|
183
|
-
val desiredHeight = if (
|
|
184
|
-
|
|
183
|
+
val desiredHeight = if (contentHeight > 0) {
|
|
184
|
+
contentHeight
|
|
185
185
|
} else {
|
|
186
186
|
measuredContentHeight + paddingTop + paddingBottom
|
|
187
187
|
}
|
|
@@ -235,8 +235,8 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
235
235
|
private var pendingLongitude: Double? = null // 临时存储经度
|
|
236
236
|
private var iconWidth: Int = 0 // 用于自定义图标的宽度
|
|
237
237
|
private var iconHeight: Int = 0 // 用于自定义图标的高度
|
|
238
|
-
private var
|
|
239
|
-
private var
|
|
238
|
+
private var contentWidth: Int = 0 // 用于自定义视图(children)的宽度
|
|
239
|
+
private var contentHeight: Int = 0 // 用于自定义视图(children)的高度
|
|
240
240
|
private val mainHandler = Handler(Looper.getMainLooper())
|
|
241
241
|
private var isRemoving = false // 标记是否正在被移除
|
|
242
242
|
private var pendingMarkerIconUpdate: Runnable? = null
|
|
@@ -733,21 +733,33 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
733
733
|
}
|
|
734
734
|
|
|
735
735
|
/**
|
|
736
|
-
*
|
|
736
|
+
* 设置内容宽度(用于 children 属性)
|
|
737
737
|
* 注意:React Native 传入的是 DP 值,需要转换为 PX
|
|
738
738
|
*/
|
|
739
|
-
fun
|
|
739
|
+
fun setContentWidth(width: Int) {
|
|
740
740
|
val density = context.resources.displayMetrics.density
|
|
741
|
-
|
|
741
|
+
val resolvedWidth = (width * density).toInt()
|
|
742
|
+
if (contentWidth == resolvedWidth) {
|
|
743
|
+
return
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
contentWidth = resolvedWidth
|
|
747
|
+
scheduleMarkerIconUpdate()
|
|
742
748
|
}
|
|
743
749
|
|
|
744
750
|
/**
|
|
745
|
-
*
|
|
751
|
+
* 设置内容高度(用于 children 属性)
|
|
746
752
|
* 注意:React Native 传入的是 DP 值,需要转换为 PX
|
|
747
753
|
*/
|
|
748
|
-
fun
|
|
754
|
+
fun setContentHeight(height: Int) {
|
|
749
755
|
val density = context.resources.displayMetrics.density
|
|
750
|
-
|
|
756
|
+
val resolvedHeight = (height * density).toInt()
|
|
757
|
+
if (contentHeight == resolvedHeight) {
|
|
758
|
+
return
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
contentHeight = resolvedHeight
|
|
762
|
+
scheduleMarkerIconUpdate()
|
|
751
763
|
}
|
|
752
764
|
|
|
753
765
|
/**
|
|
@@ -897,8 +909,8 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
897
909
|
val measuredWidth = contentBounds?.width() ?: contentView?.measuredWidth ?: measuredChild?.measuredWidth ?: 0
|
|
898
910
|
val measuredHeight = contentBounds?.height() ?: contentView?.measuredHeight ?: measuredChild?.measuredHeight ?: 0
|
|
899
911
|
|
|
900
|
-
val finalWidth = if (measuredWidth > 0) measuredWidth else (if (
|
|
901
|
-
val finalHeight = if (measuredHeight > 0) measuredHeight else (if (
|
|
912
|
+
val finalWidth = if (measuredWidth > 0) measuredWidth else (if (contentWidth > 0) contentWidth else 0)
|
|
913
|
+
val finalHeight = if (measuredHeight > 0) measuredHeight else (if (contentHeight > 0) contentHeight else 0)
|
|
902
914
|
|
|
903
915
|
// 🔑 修复:如果尺寸为 0,说明 View 还没准备好,不要生成 Bitmap,否则会导致动画位置偏移
|
|
904
916
|
if (finalWidth <= 0 || finalHeight <= 0) {
|
|
@@ -978,7 +990,7 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
978
990
|
childView.isDrawingCacheEnabled = false
|
|
979
991
|
childView.destroyDrawingCache()
|
|
980
992
|
|
|
981
|
-
val shouldTrimTransparentPadding =
|
|
993
|
+
val shouldTrimTransparentPadding = contentWidth <= 0 && contentHeight <= 0
|
|
982
994
|
return if (shouldTrimTransparentPadding) trimTransparentPadding(bitmap) else bitmap
|
|
983
995
|
} catch (_: Exception) {
|
|
984
996
|
// 遇到异常时返回 null,让上层使用默认图标
|
|
@@ -1079,8 +1091,8 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
1079
1091
|
val child = getChildAt(0)
|
|
1080
1092
|
val contentView = resolveRenderableContentView(child)
|
|
1081
1093
|
val contentBounds = computeContentBounds(child)
|
|
1082
|
-
val measuredWidth = contentBounds?.width() ?: contentView?.measuredWidth ?: child?.measuredWidth ?:
|
|
1083
|
-
val measuredHeight = contentBounds?.height() ?: contentView?.measuredHeight ?: child?.measuredHeight ?:
|
|
1094
|
+
val measuredWidth = contentBounds?.width() ?: contentView?.measuredWidth ?: child?.measuredWidth ?: contentWidth
|
|
1095
|
+
val measuredHeight = contentBounds?.height() ?: contentView?.measuredHeight ?: child?.measuredHeight ?: contentHeight
|
|
1084
1096
|
val fullCacheKey = "$keyPart|${measuredWidth}x${measuredHeight}"
|
|
1085
1097
|
|
|
1086
1098
|
// 确定锚点:优先使用用户指定的 pendingAnchor,否则对于自定义 View 使用中心点 (0.5, 0.5)
|
|
@@ -1236,13 +1248,13 @@ class MarkerView(context: Context, appContext: AppContext) : ExpoView(context, a
|
|
|
1236
1248
|
val childCountBefore = childCount
|
|
1237
1249
|
|
|
1238
1250
|
val sourceWidth = when {
|
|
1239
|
-
|
|
1251
|
+
contentWidth > 0 -> contentWidth
|
|
1240
1252
|
params?.width != null && params.width > 0 -> params.width
|
|
1241
1253
|
else -> LayoutParams.WRAP_CONTENT
|
|
1242
1254
|
}
|
|
1243
1255
|
|
|
1244
1256
|
val sourceHeight = when {
|
|
1245
|
-
|
|
1257
|
+
contentHeight > 0 -> contentHeight
|
|
1246
1258
|
params?.height != null && params.height > 0 -> params.height
|
|
1247
1259
|
else -> LayoutParams.WRAP_CONTENT
|
|
1248
1260
|
}
|
|
@@ -69,13 +69,13 @@ class MarkerViewModule : Module() {
|
|
|
69
69
|
Prop<Int>("iconHeight") { view, height ->
|
|
70
70
|
view.setIconHeight(height)
|
|
71
71
|
}
|
|
72
|
-
//
|
|
73
|
-
Prop<Int>("
|
|
74
|
-
view.
|
|
72
|
+
// 内容宽度
|
|
73
|
+
Prop<Int>("contentWidth") { view, width ->
|
|
74
|
+
view.setContentWidth(width)
|
|
75
75
|
}
|
|
76
|
-
//
|
|
77
|
-
Prop<Int>("
|
|
78
|
-
view.
|
|
76
|
+
// 内容高度
|
|
77
|
+
Prop<Int>("contentHeight") { view, height ->
|
|
78
|
+
view.setContentHeight(height)
|
|
79
79
|
}
|
|
80
80
|
// 缓存key
|
|
81
81
|
Prop<String?>("cacheKey") { view, key ->
|
|
@@ -83,6 +83,16 @@ object GeometryUtils {
|
|
|
83
83
|
longitudes: DoubleArray
|
|
84
84
|
): DoubleArray?
|
|
85
85
|
|
|
86
|
+
private external fun nativeCalculateFitZoom(
|
|
87
|
+
latitudes: DoubleArray,
|
|
88
|
+
longitudes: DoubleArray,
|
|
89
|
+
viewportWidthPx: Double,
|
|
90
|
+
viewportHeightPx: Double,
|
|
91
|
+
paddingPx: Double,
|
|
92
|
+
minZoom: Int,
|
|
93
|
+
maxZoom: Int
|
|
94
|
+
): Double
|
|
95
|
+
|
|
86
96
|
private external fun nativeEncodeGeoHash(
|
|
87
97
|
lat: Double,
|
|
88
98
|
lon: Double,
|
|
@@ -401,6 +411,99 @@ object GeometryUtils {
|
|
|
401
411
|
}
|
|
402
412
|
}
|
|
403
413
|
|
|
414
|
+
private fun mercatorX01(lon: Double): Double {
|
|
415
|
+
var wrapped = (lon + 180.0) % 360.0
|
|
416
|
+
if (wrapped < 0.0) wrapped += 360.0
|
|
417
|
+
return wrapped / 360.0
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
private fun mercatorY01(lat: Double): Double {
|
|
421
|
+
val clamped = lat.coerceIn(-85.05112878, 85.05112878)
|
|
422
|
+
val rad = Math.toRadians(clamped)
|
|
423
|
+
val y = (1.0 - asinh(tan(rad)) / Math.PI) * 0.5
|
|
424
|
+
return y.coerceIn(0.0, 1.0)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
private fun wrappedSpan01(values: List<Double>): Double {
|
|
428
|
+
if (values.size <= 1) return 0.0
|
|
429
|
+
val sorted = values.sorted()
|
|
430
|
+
var maxGap = 0.0
|
|
431
|
+
for (i in 0 until sorted.size - 1) {
|
|
432
|
+
maxGap = max(maxGap, sorted[i + 1] - sorted[i])
|
|
433
|
+
}
|
|
434
|
+
maxGap = max(maxGap, sorted.first() + 1.0 - sorted.last())
|
|
435
|
+
return (1.0 - maxGap).coerceAtLeast(0.0)
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
private fun fallbackCalculateFitZoom(
|
|
439
|
+
points: List<LatLng>,
|
|
440
|
+
viewportWidthPx: Double,
|
|
441
|
+
viewportHeightPx: Double,
|
|
442
|
+
paddingPx: Double,
|
|
443
|
+
minZoom: Int,
|
|
444
|
+
maxZoom: Int
|
|
445
|
+
): Double {
|
|
446
|
+
if (points.isEmpty()) return minZoom.toDouble()
|
|
447
|
+
if (points.size == 1) return maxZoom.toDouble()
|
|
448
|
+
|
|
449
|
+
val safeMinZoom = min(minZoom, maxZoom)
|
|
450
|
+
val safeMaxZoom = max(minZoom, maxZoom)
|
|
451
|
+
val safeWidth = if (viewportWidthPx > 1.0) viewportWidthPx else 390.0
|
|
452
|
+
val safeHeight = if (viewportHeightPx > 1.0) viewportHeightPx else 844.0
|
|
453
|
+
val safePadding = max(0.0, paddingPx)
|
|
454
|
+
val availableWidth = max(1.0, safeWidth - safePadding * 2.0)
|
|
455
|
+
val availableHeight = max(1.0, safeHeight - safePadding * 2.0)
|
|
456
|
+
|
|
457
|
+
val xs = points.map { mercatorX01(it.longitude) }
|
|
458
|
+
val ys = points.map { mercatorY01(it.latitude) }
|
|
459
|
+
val spanX = wrappedSpan01(xs)
|
|
460
|
+
val spanY = (ys.maxOrNull() ?: 0.0) - (ys.minOrNull() ?: 0.0)
|
|
461
|
+
val tileSize = 256.0
|
|
462
|
+
|
|
463
|
+
val zoomX = if (spanX <= 1e-12) safeMaxZoom.toDouble() else log2(availableWidth / (tileSize * spanX))
|
|
464
|
+
val zoomY = if (spanY <= 1e-12) safeMaxZoom.toDouble() else log2(availableHeight / (tileSize * spanY))
|
|
465
|
+
val fitZoom = min(zoomX, zoomY)
|
|
466
|
+
if (!fitZoom.isFinite()) return safeMinZoom.toDouble()
|
|
467
|
+
return fitZoom.coerceIn(safeMinZoom.toDouble(), safeMaxZoom.toDouble())
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
fun calculateFitZoom(
|
|
471
|
+
points: List<LatLng>,
|
|
472
|
+
viewportWidthPx: Double,
|
|
473
|
+
viewportHeightPx: Double,
|
|
474
|
+
paddingPx: Double,
|
|
475
|
+
minZoom: Int,
|
|
476
|
+
maxZoom: Int
|
|
477
|
+
): Double {
|
|
478
|
+
if (points.isEmpty()) return minZoom.toDouble()
|
|
479
|
+
return try {
|
|
480
|
+
val latitudes = DoubleArray(points.size)
|
|
481
|
+
val longitudes = DoubleArray(points.size)
|
|
482
|
+
for (i in points.indices) {
|
|
483
|
+
latitudes[i] = points[i].latitude
|
|
484
|
+
longitudes[i] = points[i].longitude
|
|
485
|
+
}
|
|
486
|
+
nativeCalculateFitZoom(
|
|
487
|
+
latitudes,
|
|
488
|
+
longitudes,
|
|
489
|
+
viewportWidthPx,
|
|
490
|
+
viewportHeightPx,
|
|
491
|
+
paddingPx,
|
|
492
|
+
minZoom,
|
|
493
|
+
maxZoom
|
|
494
|
+
)
|
|
495
|
+
} catch (_: Throwable) {
|
|
496
|
+
fallbackCalculateFitZoom(
|
|
497
|
+
points,
|
|
498
|
+
viewportWidthPx,
|
|
499
|
+
viewportHeightPx,
|
|
500
|
+
paddingPx,
|
|
501
|
+
minZoom,
|
|
502
|
+
maxZoom
|
|
503
|
+
)
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
404
507
|
fun encodeGeoHash(point: LatLng, precision: Int): String {
|
|
405
508
|
return try {
|
|
406
509
|
nativeEncodeGeoHash(point.latitude, point.longitude, precision)
|
|
@@ -1267,7 +1267,7 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
|
|
|
1267
1267
|
SDKInitializer.restorePersistedState(appCtx)
|
|
1268
1268
|
if (!SDKInitializer.isPrivacyReady()) {
|
|
1269
1269
|
throw IllegalStateException(
|
|
1270
|
-
"隐私协议未完成确认,请先调用 setPrivacyConfig
|
|
1270
|
+
"隐私协议未完成确认,请先调用 setPrivacyConfig"
|
|
1271
1271
|
)
|
|
1272
1272
|
}
|
|
1273
1273
|
|
package/build/index.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import ExpoGaodeMapNavigationModule from './ExpoGaodeMapNavigationModule';
|
|
2
|
+
import { ExpoGaodeMapNaviView, type ExpoGaodeMapNaviViewRef } from './ExpoGaodeMapNaviView';
|
|
2
3
|
export * from './map';
|
|
3
4
|
import { RouteType, DriveStrategy, WalkStrategy, RideStrategy, TruckSize, TravelStrategy, type TransitRouteOptions } from './types';
|
|
4
5
|
import type { NaviPoint, RouteOptions, DriveRouteOptions, WalkRouteOptions, RideRouteOptions, EBikeRouteOptions, TransitRouteOptions as TransitRouteOptionsType, TruckRouteOptions, OfficialNaviPageOptions, RouteResult, DriveRouteResult, IndependentRouteResult, IndependentDriveRouteOptions, IndependentTruckRouteOptions, IndependentWalkRouteOptions, IndependentRideRouteOptions, SelectIndependentRouteOptions, StartNaviWithIndependentPathOptions, ClearIndependentRouteOptions, MotorcycleRouteOptions, IndependentMotorcycleRouteOptions, BuildAnchorWaypointsOptions, FollowWebPlannedRouteOptions, FollowWebPlannedRouteResult, FollowWebPlannedRouteCandidate, WebPlannedRoute, NaviInfoUpdateEvent, NaviLaneInfoEvent, NaviTrafficStatusesEvent, NaviVisualStateEvent, ExpoGaodeMapNaviViewProps } from './types';
|
|
5
6
|
export declare function buildAnchorWaypointsFromWebRoute(options: BuildAnchorWaypointsOptions): NaviPoint[];
|
|
6
7
|
export declare function followWebPlannedRoute(options: FollowWebPlannedRouteOptions): Promise<FollowWebPlannedRouteResult>;
|
|
7
|
-
export { ExpoGaodeMapNaviView, type ExpoGaodeMapNaviViewRef
|
|
8
|
+
export { ExpoGaodeMapNaviView, type ExpoGaodeMapNaviViewRef };
|
|
9
|
+
/**
|
|
10
|
+
* @deprecated 请使用 `ExpoGaodeMapNaviView`
|
|
11
|
+
*/
|
|
12
|
+
export declare const NaviView: import("react").ForwardRefExoticComponent<ExpoGaodeMapNaviViewProps & import("react").RefAttributes<ExpoGaodeMapNaviViewRef>>;
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated 请使用 `ExpoGaodeMapNaviViewRef`
|
|
15
|
+
*/
|
|
16
|
+
export type NaviViewRef = ExpoGaodeMapNaviViewRef;
|
|
8
17
|
/**
|
|
9
18
|
* 初始化导航模块(可选)
|
|
10
19
|
*/
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/build/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ExpoGaodeMapNavigationModule from './ExpoGaodeMapNavigationModule';
|
|
2
2
|
import { ExpoGaodeMapModule } from './map';
|
|
3
|
+
import { ExpoGaodeMapNaviView, } from './ExpoGaodeMapNaviView';
|
|
3
4
|
// 重新导出地图模块的所有内容
|
|
4
5
|
export * from './map';
|
|
5
6
|
import { RouteType, DriveStrategy, WalkStrategy, RideStrategy, TruckSize, TravelStrategy, } from './types';
|
|
@@ -461,9 +462,11 @@ function isMotorcycleRouteOptions(options) {
|
|
|
461
462
|
return 'motorcycleCC' in options;
|
|
462
463
|
}
|
|
463
464
|
// 导出官方导航界面组件
|
|
464
|
-
export { ExpoGaodeMapNaviView
|
|
465
|
-
|
|
466
|
-
|
|
465
|
+
export { ExpoGaodeMapNaviView };
|
|
466
|
+
/**
|
|
467
|
+
* @deprecated 请使用 `ExpoGaodeMapNaviView`
|
|
468
|
+
*/
|
|
469
|
+
export const NaviView = ExpoGaodeMapNaviView;
|
|
467
470
|
/**
|
|
468
471
|
* 初始化导航模块(可选)
|
|
469
472
|
*/
|