expo-gaode-map 1.1.7 → 2.0.0-alpha.1
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.en.md +32 -46
- package/README.md +51 -71
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +37 -237
- package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapViewModule.kt +1 -49
- package/android/src/main/java/expo/modules/gaodemap/managers/CameraManager.kt +30 -7
- package/android/src/main/java/expo/modules/gaodemap/managers/UIManager.kt +1 -0
- package/android/src/main/java/expo/modules/gaodemap/modules/LocationManager.kt +10 -1
- package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +38 -14
- package/android/src/main/java/expo/modules/gaodemap/overlays/CircleViewModule.kt +3 -3
- package/android/src/main/java/expo/modules/gaodemap/overlays/ClusterView.kt +8 -1
- package/android/src/main/java/expo/modules/gaodemap/overlays/HeatMapView.kt +4 -1
- package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerView.kt +322 -93
- package/android/src/main/java/expo/modules/gaodemap/overlays/MarkerViewModule.kt +11 -3
- package/android/src/main/java/expo/modules/gaodemap/overlays/MultiPointView.kt +4 -1
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolygonView.kt +25 -11
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolygonViewModule.kt +3 -3
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +20 -10
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineViewModule.kt +6 -2
- package/build/ExpoGaodeMap.types.d.ts +27 -6
- package/build/ExpoGaodeMap.types.d.ts.map +1 -1
- package/build/ExpoGaodeMap.types.js +3 -0
- package/build/ExpoGaodeMap.types.js.map +1 -1
- package/build/ExpoGaodeMapModule.d.ts +157 -10
- package/build/ExpoGaodeMapModule.d.ts.map +1 -1
- package/build/ExpoGaodeMapModule.js +4 -0
- package/build/ExpoGaodeMapModule.js.map +1 -1
- package/build/ExpoGaodeMapView.d.ts +1 -17
- package/build/ExpoGaodeMapView.d.ts.map +1 -1
- package/build/ExpoGaodeMapView.js +4 -209
- package/build/ExpoGaodeMapView.js.map +1 -1
- package/build/components/overlays/Circle.d.ts +10 -1
- package/build/components/overlays/Circle.d.ts.map +1 -1
- package/build/components/overlays/Circle.js +11 -86
- package/build/components/overlays/Circle.js.map +1 -1
- package/build/components/overlays/Cluster.d.ts.map +1 -1
- package/build/components/overlays/Cluster.js.map +1 -1
- package/build/components/overlays/Marker.d.ts +13 -1
- package/build/components/overlays/Marker.d.ts.map +1 -1
- package/build/components/overlays/Marker.js +51 -115
- package/build/components/overlays/Marker.js.map +1 -1
- package/build/components/overlays/Polygon.d.ts +7 -15
- package/build/components/overlays/Polygon.d.ts.map +1 -1
- package/build/components/overlays/Polygon.js +10 -80
- package/build/components/overlays/Polygon.js.map +1 -1
- package/build/components/overlays/Polyline.d.ts +7 -14
- package/build/components/overlays/Polyline.d.ts.map +1 -1
- package/build/components/overlays/Polyline.js +9 -66
- package/build/components/overlays/Polyline.js.map +1 -1
- package/build/index.d.ts +1 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -10
- package/build/index.js.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js.map +1 -1
- package/build/types/map-view.types.d.ts +0 -76
- package/build/types/map-view.types.d.ts.map +1 -1
- package/build/types/map-view.types.js.map +1 -1
- package/build/types/overlays.types.d.ts +11 -16
- package/build/types/overlays.types.d.ts.map +1 -1
- package/build/types/overlays.types.js.map +1 -1
- package/docs/API.en.md +1 -21
- package/docs/API.md +84 -56
- package/docs/EXAMPLES.en.md +0 -48
- package/docs/EXAMPLES.md +49 -102
- package/docs/INITIALIZATION.md +59 -71
- package/docs/MIGRATION.md +423 -0
- package/ios/ExpoGaodeMapView.swift +317 -258
- package/ios/ExpoGaodeMapViewModule.swift +3 -50
- package/ios/managers/CameraManager.swift +23 -2
- package/ios/managers/UIManager.swift +10 -5
- package/ios/modules/LocationManager.swift +10 -0
- package/ios/overlays/CircleView.swift +98 -19
- package/ios/overlays/CircleViewModule.swift +21 -0
- package/ios/overlays/ClusterView.swift +33 -4
- package/ios/overlays/HeatMapView.swift +16 -4
- package/ios/overlays/MarkerView.swift +235 -146
- package/ios/overlays/MarkerViewModule.swift +7 -3
- package/ios/overlays/MultiPointView.swift +30 -1
- package/ios/overlays/PolygonView.swift +63 -12
- package/ios/overlays/PolygonViewModule.swift +17 -0
- package/ios/overlays/PolylineView.swift +95 -25
- package/ios/overlays/PolylineViewModule.swift +17 -8
- package/ios/utils/PermissionManager.swift +9 -14
- package/package.json +4 -3
- package/src/ExpoGaodeMap.types.ts +28 -3
- package/src/ExpoGaodeMapModule.ts +201 -12
- package/src/ExpoGaodeMapView.tsx +11 -225
- package/src/components/overlays/Circle.tsx +12 -104
- package/src/components/overlays/Cluster.tsx +0 -1
- package/src/components/overlays/Marker.tsx +63 -138
- package/src/components/overlays/Polygon.tsx +12 -92
- package/src/components/overlays/Polyline.tsx +11 -77
- package/src/index.ts +4 -29
- package/src/types/index.ts +1 -1
- package/src/types/map-view.types.ts +1 -69
- package/src/types/overlays.types.ts +11 -16
- package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +0 -574
- package/build/modules/AMapLocation.d.ts +0 -78
- package/build/modules/AMapLocation.d.ts.map +0 -1
- package/build/modules/AMapLocation.js +0 -132
- package/build/modules/AMapLocation.js.map +0 -1
- package/build/modules/AMapPermissions.d.ts +0 -29
- package/build/modules/AMapPermissions.d.ts.map +0 -1
- package/build/modules/AMapPermissions.js +0 -23
- package/build/modules/AMapPermissions.js.map +0 -1
- package/build/modules/AMapSDK.d.ts +0 -22
- package/build/modules/AMapSDK.d.ts.map +0 -1
- package/build/modules/AMapSDK.js +0 -25
- package/build/modules/AMapSDK.js.map +0 -1
- package/build/modules/AMapView.d.ts +0 -44
- package/build/modules/AMapView.d.ts.map +0 -1
- package/build/modules/AMapView.js +0 -65
- package/build/modules/AMapView.js.map +0 -1
- package/ios/managers/OverlayManager.swift +0 -522
- package/src/modules/AMapLocation.ts +0 -165
- package/src/modules/AMapPermissions.ts +0 -41
- package/src/modules/AMapSDK.ts +0 -31
- package/src/modules/AMapView.ts +0 -72
- package/test/ClockMapView.tsx +0 -532
- package/test/useMap.ts +0 -1360
|
@@ -9,7 +9,7 @@ public class ExpoGaodeMapViewModule: Module {
|
|
|
9
9
|
Name("ExpoGaodeMapView")
|
|
10
10
|
|
|
11
11
|
View(ExpoGaodeMapView.self) {
|
|
12
|
-
Events("onMapPress", "onMapLongPress", "onLoad", "onLocation"
|
|
12
|
+
Events("onMapPress", "onMapLongPress", "onLoad", "onLocation")
|
|
13
13
|
|
|
14
14
|
Prop("mapType") { (view: ExpoGaodeMapView, type: Int) in
|
|
15
15
|
view.mapType = type
|
|
@@ -102,54 +102,7 @@ public class ExpoGaodeMapViewModule: Module {
|
|
|
102
102
|
AsyncFunction("getCameraPosition") { (view: ExpoGaodeMapView) -> [String: Any] in
|
|
103
103
|
return view.getCameraPosition()
|
|
104
104
|
}
|
|
105
|
-
|
|
106
|
-
AsyncFunction("addCircle") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
107
|
-
view.addCircle(id: id, props: props)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
AsyncFunction("removeCircle") { (view: ExpoGaodeMapView, id: String) in
|
|
111
|
-
view.removeCircle(id: id)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
AsyncFunction("updateCircle") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
115
|
-
view.updateCircle(id: id, props: props)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
AsyncFunction("addMarker") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
119
|
-
view.addMarker(id: id, props: props)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
AsyncFunction("removeMarker") { (view: ExpoGaodeMapView, id: String) in
|
|
123
|
-
view.removeMarker(id: id)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
AsyncFunction("updateMarker") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
127
|
-
view.updateMarker(id: id, props: props)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
AsyncFunction("addPolyline") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
131
|
-
view.addPolyline(id: id, props: props)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
AsyncFunction("removePolyline") { (view: ExpoGaodeMapView, id: String) in
|
|
135
|
-
view.removePolyline(id: id)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
AsyncFunction("updatePolyline") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
139
|
-
view.updatePolyline(id: id, props: props)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
AsyncFunction("addPolygon") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
143
|
-
view.addPolygon(id: id, props: props)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
AsyncFunction("removePolygon") { (view: ExpoGaodeMapView, id: String) in
|
|
147
|
-
view.removePolygon(id: id)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
AsyncFunction("updatePolygon") { (view: ExpoGaodeMapView, id: String, props: [String: Any]) in
|
|
151
|
-
view.updatePolygon(id: id, props: props)
|
|
152
|
-
}
|
|
105
|
+
|
|
153
106
|
}
|
|
154
107
|
}
|
|
155
|
-
}
|
|
108
|
+
}
|
|
@@ -49,11 +49,18 @@ class CameraManager {
|
|
|
49
49
|
if let target = position["target"] as? [String: Double],
|
|
50
50
|
let latitude = target["latitude"],
|
|
51
51
|
let longitude = target["longitude"] {
|
|
52
|
+
// 🔑 坐标验证
|
|
53
|
+
guard latitude >= -90 && latitude <= 90,
|
|
54
|
+
longitude >= -180 && longitude <= 180 else {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
52
57
|
status.centerCoordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
if let zoom = position["zoom"] as? Double {
|
|
56
|
-
|
|
61
|
+
// 🔑 缩放级别范围限制 (3-20)
|
|
62
|
+
let validZoom = max(3, min(20, zoom))
|
|
63
|
+
status.zoomLevel = CGFloat(validZoom)
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
if let bearing = position["bearing"] as? Double {
|
|
@@ -82,6 +89,11 @@ class CameraManager {
|
|
|
82
89
|
if let target = position["target"] as? [String: Double],
|
|
83
90
|
let latitude = target["latitude"],
|
|
84
91
|
let longitude = target["longitude"] {
|
|
92
|
+
// 🔑 坐标验证
|
|
93
|
+
guard latitude >= -90 && latitude <= 90,
|
|
94
|
+
longitude >= -180 && longitude <= 180 else {
|
|
95
|
+
return
|
|
96
|
+
}
|
|
85
97
|
status.centerCoordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
|
|
86
98
|
} else {
|
|
87
99
|
status.centerCoordinate = mapView.centerCoordinate
|
|
@@ -120,6 +132,13 @@ class CameraManager {
|
|
|
120
132
|
guard let mapView = mapView,
|
|
121
133
|
let latitude = center["latitude"],
|
|
122
134
|
let longitude = center["longitude"] else { return }
|
|
135
|
+
|
|
136
|
+
// 🔑 坐标验证
|
|
137
|
+
guard latitude >= -90 && latitude <= 90,
|
|
138
|
+
longitude >= -180 && longitude <= 180 else {
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
|
|
123
142
|
mapView.setCenter(CLLocationCoordinate2D(latitude: latitude, longitude: longitude), animated: animated)
|
|
124
143
|
}
|
|
125
144
|
|
|
@@ -129,7 +148,9 @@ class CameraManager {
|
|
|
129
148
|
* @param animated 是否使用动画
|
|
130
149
|
*/
|
|
131
150
|
func setZoomLevel(zoom: CGFloat, animated: Bool) {
|
|
132
|
-
|
|
151
|
+
// 🔑 缩放级别范围限制 (3-20)
|
|
152
|
+
let validZoom = max(3, min(20, zoom))
|
|
153
|
+
mapView?.setZoomLevel(validZoom, animated: animated)
|
|
133
154
|
}
|
|
134
155
|
|
|
135
156
|
// MARK: - 相机信息获取
|
|
@@ -126,11 +126,16 @@ class UIManager: NSObject, MAMapViewDelegate {
|
|
|
126
126
|
*/
|
|
127
127
|
public func mapView(_ mapView: MAMapView, didUpdate userLocation: MAUserLocation, updatingLocation: Bool) {
|
|
128
128
|
guard updatingLocation, let location = userLocation.location else { return }
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
|
|
130
|
+
// 🔑 坐标验证
|
|
131
|
+
let latitude = location.coordinate.latitude
|
|
132
|
+
let longitude = location.coordinate.longitude
|
|
133
|
+
guard latitude >= -90 && latitude <= 90,
|
|
134
|
+
longitude >= -180 && longitude <= 180 else {
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
onLocationChanged?(latitude, longitude, location.horizontalAccuracy)
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
/**
|
|
@@ -165,7 +165,11 @@ class LocationManager: NSObject, AMapLocationManagerDelegate {
|
|
|
165
165
|
*/
|
|
166
166
|
func destroy() {
|
|
167
167
|
locationManager?.stopUpdatingLocation()
|
|
168
|
+
locationManager?.stopUpdatingHeading()
|
|
169
|
+
locationManager?.delegate = nil
|
|
168
170
|
locationManager = nil
|
|
171
|
+
onLocationUpdate = nil
|
|
172
|
+
onHeadingUpdate = nil
|
|
169
173
|
}
|
|
170
174
|
|
|
171
175
|
/**
|
|
@@ -194,6 +198,12 @@ class LocationManager: NSObject, AMapLocationManagerDelegate {
|
|
|
194
198
|
* @param reGeocode 逆地理信息
|
|
195
199
|
*/
|
|
196
200
|
func amapLocationManager(_ manager: AMapLocationManager!, didUpdate location: CLLocation!, reGeocode: AMapLocationReGeocode!) {
|
|
201
|
+
// 🔑 坐标验证:防止无效坐标
|
|
202
|
+
guard location.coordinate.latitude >= -90 && location.coordinate.latitude <= 90,
|
|
203
|
+
location.coordinate.longitude >= -180 && location.coordinate.longitude <= 180 else {
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
197
207
|
var locationData: [String: Any] = [
|
|
198
208
|
"latitude": location.coordinate.latitude,
|
|
199
209
|
"longitude": location.coordinate.longitude,
|
|
@@ -10,8 +10,8 @@ import MAMapKit
|
|
|
10
10
|
* - 响应属性变化并更新渲染
|
|
11
11
|
*/
|
|
12
12
|
class CircleView: ExpoView {
|
|
13
|
-
/// 事件派发器
|
|
14
|
-
let
|
|
13
|
+
/// 事件派发器 - 使用 onCirclePress 避免与 MarkerPress 冲突
|
|
14
|
+
let onCirclePress = EventDispatcher()
|
|
15
15
|
|
|
16
16
|
/// 圆心坐标
|
|
17
17
|
var circleCenter: [String: Double] = [:]
|
|
@@ -23,16 +23,47 @@ class CircleView: ExpoView {
|
|
|
23
23
|
var strokeColor: Any?
|
|
24
24
|
/// 边框宽度
|
|
25
25
|
var strokeWidth: Float = 0
|
|
26
|
+
/// z-index 图层顺序
|
|
27
|
+
var zIndex: Double = 0
|
|
26
28
|
|
|
27
|
-
///
|
|
29
|
+
/// 地图视图引用
|
|
28
30
|
private var mapView: MAMapView?
|
|
29
31
|
/// 圆形覆盖物对象
|
|
30
32
|
var circle: MACircle?
|
|
31
33
|
/// 圆形渲染器
|
|
32
34
|
private var renderer: MACircleRenderer?
|
|
35
|
+
/// 上次设置的地图引用(防止重复调用)
|
|
36
|
+
private weak var lastSetMapView: MAMapView?
|
|
33
37
|
|
|
34
38
|
required init(appContext: AppContext? = nil) {
|
|
35
39
|
super.init(appContext: appContext)
|
|
40
|
+
|
|
41
|
+
// 🔑 关键修复:CircleView 不应该拦截触摸事件
|
|
42
|
+
self.isUserInteractionEnabled = false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 重写 hitTest,让触摸事件完全穿透此视图
|
|
47
|
+
* 这是解决覆盖物视图阻挡地图触摸的关键
|
|
48
|
+
*/
|
|
49
|
+
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
50
|
+
// 始终返回 nil,让触摸事件穿透到地图
|
|
51
|
+
return nil
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 重写 point(inside:with:),确保此视图不响应任何触摸
|
|
56
|
+
*/
|
|
57
|
+
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
|
58
|
+
// 始终返回 false,表示点击不在此视图内
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 检查地图是否已连接
|
|
64
|
+
*/
|
|
65
|
+
func isMapConnected() -> Bool {
|
|
66
|
+
return mapView != nil
|
|
36
67
|
}
|
|
37
68
|
|
|
38
69
|
/**
|
|
@@ -40,6 +71,12 @@ class CircleView: ExpoView {
|
|
|
40
71
|
* @param map 地图视图
|
|
41
72
|
*/
|
|
42
73
|
func setMap(_ map: MAMapView) {
|
|
74
|
+
// 🔑 关键优化:如果是同一个地图引用,跳过重复设置
|
|
75
|
+
if lastSetMapView === map {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
lastSetMapView = map
|
|
43
80
|
self.mapView = map
|
|
44
81
|
updateCircle()
|
|
45
82
|
}
|
|
@@ -48,32 +85,40 @@ class CircleView: ExpoView {
|
|
|
48
85
|
* 更新圆形覆盖物
|
|
49
86
|
*/
|
|
50
87
|
private func updateCircle() {
|
|
51
|
-
guard let mapView = mapView
|
|
52
|
-
|
|
88
|
+
guard let mapView = mapView else {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
guard let latitude = circleCenter["latitude"],
|
|
53
93
|
let longitude = circleCenter["longitude"],
|
|
54
94
|
radius > 0 else {
|
|
55
|
-
print("❌ CircleView.updateCircle: 条件不满足")
|
|
56
95
|
return
|
|
57
96
|
}
|
|
58
97
|
|
|
59
|
-
|
|
60
|
-
|
|
98
|
+
// 🔑 坐标验证:防止无效坐标导致崩溃
|
|
99
|
+
guard latitude >= -90 && latitude <= 90,
|
|
100
|
+
longitude >= -180 && longitude <= 180 else {
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 🔑 半径验证:防止负数或过大的半径
|
|
105
|
+
let validRadius = max(0.1, min(radius, 1000000))
|
|
61
106
|
|
|
62
107
|
if circle == nil {
|
|
63
108
|
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
|
|
64
|
-
circle = MACircle(center: coordinate, radius:
|
|
109
|
+
circle = MACircle(center: coordinate, radius: validRadius)
|
|
65
110
|
mapView.add(circle!)
|
|
66
|
-
print("🔵 CircleView.updateCircle: 创建新圆形")
|
|
67
111
|
} else {
|
|
68
|
-
|
|
69
|
-
circle?.radius = radius
|
|
112
|
+
// 先移除旧的
|
|
70
113
|
mapView.remove(circle!)
|
|
114
|
+
// 更新属性
|
|
115
|
+
circle?.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
|
|
116
|
+
circle?.radius = validRadius
|
|
117
|
+
// 重新添加
|
|
71
118
|
mapView.add(circle!)
|
|
72
|
-
print("🔵 CircleView.updateCircle: 更新现有圆形")
|
|
73
119
|
}
|
|
74
120
|
|
|
75
121
|
renderer = nil
|
|
76
|
-
print("🔵 CircleView.updateCircle: renderer 已清空")
|
|
77
122
|
}
|
|
78
123
|
|
|
79
124
|
/**
|
|
@@ -88,10 +133,10 @@ class CircleView: ExpoView {
|
|
|
88
133
|
renderer?.fillColor = parsedFillColor ?? UIColor.clear
|
|
89
134
|
renderer?.strokeColor = parsedStrokeColor ?? UIColor.clear
|
|
90
135
|
renderer?.lineWidth = CGFloat(strokeWidth)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
136
|
+
}
|
|
137
|
+
// 确保即使 renderer 存在,它也与当前的 circle 实例关联
|
|
138
|
+
if renderer?.circle !== circle {
|
|
139
|
+
renderer = MACircleRenderer(circle: circle)
|
|
95
140
|
}
|
|
96
141
|
return renderer!
|
|
97
142
|
}
|
|
@@ -145,11 +190,45 @@ class CircleView: ExpoView {
|
|
|
145
190
|
}
|
|
146
191
|
|
|
147
192
|
/**
|
|
148
|
-
*
|
|
193
|
+
* 设置 z-index
|
|
194
|
+
* @param zIndex z-index 值,数值越大越在上层
|
|
195
|
+
*
|
|
196
|
+
* 注意:iOS 高德地图的 MACircle 不直接支持 zIndex 属性
|
|
197
|
+
* overlay 的渲染顺序由添加顺序决定,后添加的在上层
|
|
198
|
+
* 这里通过重新添加来尝试改变顺序
|
|
199
|
+
*/
|
|
200
|
+
func setZIndex(_ zIndex: Double) {
|
|
201
|
+
self.zIndex = zIndex
|
|
202
|
+
renderer = nil
|
|
203
|
+
updateCircle()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 视图即将从父视图移除时调用
|
|
208
|
+
* 🔑 关键修复:旧架构下,React Native 移除视图时不一定立即调用 deinit
|
|
209
|
+
* 需要在 willMove(toSuperview:) 中立即清理地图覆盖物
|
|
210
|
+
*/
|
|
211
|
+
override func willMove(toSuperview newSuperview: UIView?) {
|
|
212
|
+
super.willMove(toSuperview: newSuperview)
|
|
213
|
+
|
|
214
|
+
// 当 newSuperview 为 nil 时,表示视图正在从父视图移除
|
|
215
|
+
if newSuperview == nil {
|
|
216
|
+
if let mapView = mapView, let circle = circle {
|
|
217
|
+
mapView.remove(circle)
|
|
218
|
+
self.circle = nil
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* 析构时移除圆形(双重保险)
|
|
149
225
|
*/
|
|
150
226
|
deinit {
|
|
151
227
|
if let mapView = mapView, let circle = circle {
|
|
152
228
|
mapView.remove(circle)
|
|
153
229
|
}
|
|
230
|
+
mapView = nil
|
|
231
|
+
circle = nil
|
|
232
|
+
renderer = nil
|
|
154
233
|
}
|
|
155
234
|
}
|
|
@@ -5,6 +5,8 @@ public class CircleViewModule: Module {
|
|
|
5
5
|
Name("CircleView")
|
|
6
6
|
|
|
7
7
|
View(CircleView.self) {
|
|
8
|
+
Events("onCirclePress")
|
|
9
|
+
|
|
8
10
|
Prop("center") { (view: CircleView, center: [String: Double]) in
|
|
9
11
|
view.setCenter(center)
|
|
10
12
|
}
|
|
@@ -24,6 +26,25 @@ public class CircleViewModule: Module {
|
|
|
24
26
|
Prop("strokeWidth") { (view: CircleView, width: Double) in
|
|
25
27
|
view.setStrokeWidth(Float(width))
|
|
26
28
|
}
|
|
29
|
+
|
|
30
|
+
Prop("zIndex") { (view: CircleView, zIndex: Double) in
|
|
31
|
+
view.setZIndex(zIndex)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
OnViewDidUpdateProps { (view: CircleView) in
|
|
35
|
+
// 属性更新完成后,如果还没连接地图,尝试连接
|
|
36
|
+
if !view.isMapConnected() {
|
|
37
|
+
// 查找父视图 ExpoGaodeMapView
|
|
38
|
+
var parent = view.superview
|
|
39
|
+
while parent != nil {
|
|
40
|
+
if let mapView = parent as? ExpoGaodeMapView {
|
|
41
|
+
view.setMap(mapView.mapView)
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
parent = parent?.superview
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
27
48
|
}
|
|
28
49
|
}
|
|
29
50
|
}
|
|
@@ -36,10 +36,11 @@ class ClusterView: ExpoView {
|
|
|
36
36
|
private func updateCluster() {
|
|
37
37
|
guard let mapView = mapView else { return }
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
// 先移除旧的注释
|
|
40
|
+
removeAllAnnotations()
|
|
41
|
+
|
|
42
|
+
// 验证数据有效性
|
|
43
|
+
guard !points.isEmpty else { return }
|
|
43
44
|
|
|
44
45
|
for point in points {
|
|
45
46
|
guard let latitude = point["latitude"] as? Double,
|
|
@@ -53,4 +54,32 @@ class ClusterView: ExpoView {
|
|
|
53
54
|
annotations.append(annotation)
|
|
54
55
|
}
|
|
55
56
|
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 移除所有标注
|
|
60
|
+
*/
|
|
61
|
+
private func removeAllAnnotations() {
|
|
62
|
+
guard let mapView = mapView else { return }
|
|
63
|
+
|
|
64
|
+
for annotation in annotations {
|
|
65
|
+
mapView.removeAnnotation(annotation)
|
|
66
|
+
}
|
|
67
|
+
annotations.removeAll()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 从父视图移除时清理标注
|
|
72
|
+
*/
|
|
73
|
+
override func removeFromSuperview() {
|
|
74
|
+
super.removeFromSuperview()
|
|
75
|
+
removeAllAnnotations()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 析构时移除标注
|
|
80
|
+
*/
|
|
81
|
+
deinit {
|
|
82
|
+
removeAllAnnotations()
|
|
83
|
+
mapView = nil
|
|
84
|
+
}
|
|
56
85
|
}
|
|
@@ -71,19 +71,30 @@ class HeatMapView: ExpoView {
|
|
|
71
71
|
// 移除旧的热力图
|
|
72
72
|
if let oldHeatmap = heatmapOverlay {
|
|
73
73
|
mapView.remove(oldHeatmap)
|
|
74
|
+
heatmapOverlay = nil
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
// 验证数据有效性
|
|
78
|
+
guard !data.isEmpty else { return }
|
|
79
|
+
|
|
76
80
|
// 创建热力图数据
|
|
77
81
|
var heatmapData: [MAHeatMapNode] = []
|
|
78
82
|
for point in data {
|
|
79
83
|
guard let latitude = point["latitude"] as? Double,
|
|
80
|
-
let longitude = point["longitude"] as? Double
|
|
84
|
+
let longitude = point["longitude"] as? Double,
|
|
85
|
+
latitude >= -90 && latitude <= 90,
|
|
86
|
+
longitude >= -180 && longitude <= 180 else {
|
|
81
87
|
continue
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
let node = MAHeatMapNode()
|
|
85
91
|
node.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
|
|
86
|
-
|
|
92
|
+
// 支持自定义强度,默认为 1.0
|
|
93
|
+
if let intensity = point["intensity"] as? Double {
|
|
94
|
+
node.intensity = Float(max(0, min(1, intensity)))
|
|
95
|
+
} else {
|
|
96
|
+
node.intensity = 1.0
|
|
97
|
+
}
|
|
87
98
|
heatmapData.append(node)
|
|
88
99
|
}
|
|
89
100
|
|
|
@@ -92,8 +103,8 @@ class HeatMapView: ExpoView {
|
|
|
92
103
|
// 创建热力图图层
|
|
93
104
|
let heatmap = MAHeatMapTileOverlay()
|
|
94
105
|
heatmap.data = heatmapData
|
|
95
|
-
heatmap.radius = radius
|
|
96
|
-
heatmap.opacity = CGFloat(opacity)
|
|
106
|
+
heatmap.radius = max(1, radius) // 确保半径至少为 1
|
|
107
|
+
heatmap.opacity = CGFloat(max(0, min(1, opacity))) // 限制透明度范围
|
|
97
108
|
|
|
98
109
|
mapView.add(heatmap)
|
|
99
110
|
heatmapOverlay = heatmap
|
|
@@ -121,5 +132,6 @@ class HeatMapView: ExpoView {
|
|
|
121
132
|
*/
|
|
122
133
|
deinit {
|
|
123
134
|
removeHeatMap()
|
|
135
|
+
mapView = nil
|
|
124
136
|
}
|
|
125
137
|
}
|