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
|
@@ -1,522 +0,0 @@
|
|
|
1
|
-
import MAMapKit
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 覆盖物管理器
|
|
5
|
-
*
|
|
6
|
-
* 负责:
|
|
7
|
-
* - 管理地图覆盖物(圆形、折线、多边形)
|
|
8
|
-
* - 管理标记点(Marker)
|
|
9
|
-
* - 处理覆盖物样式和渲染
|
|
10
|
-
* - 支持纹理贴图
|
|
11
|
-
*/
|
|
12
|
-
class OverlayManager {
|
|
13
|
-
/// 地图视图弱引用
|
|
14
|
-
private weak var mapView: MAMapView?
|
|
15
|
-
/// 覆盖物字典 (id -> overlay)
|
|
16
|
-
private var overlays: [String: MAOverlay] = [:]
|
|
17
|
-
/// 覆盖物样式字典 (id -> style)
|
|
18
|
-
private var overlayStyles: [String: [String: Any]] = [:]
|
|
19
|
-
/// 标记点字典 (id -> annotation)
|
|
20
|
-
private var annotations: [String: MAPointAnnotation] = [:]
|
|
21
|
-
/// 标记点属性字典 (id -> props)
|
|
22
|
-
private var markerProps: [String: [String: Any]] = [:]
|
|
23
|
-
/// Circle 点击回调
|
|
24
|
-
var onCirclePress: (([String: Any]) -> Void)?
|
|
25
|
-
/// Circle ID 映射 (overlay -> id)
|
|
26
|
-
private var circleIdMap: [MACircle: String] = [:]
|
|
27
|
-
/// Polygon ID 映射 (overlay -> id)
|
|
28
|
-
private var polygonIdMap: [MAPolygon: String] = [:]
|
|
29
|
-
/// Polyline ID 映射 (overlay -> id)
|
|
30
|
-
private var polylineIdMap: [MAPolyline: String] = [:]
|
|
31
|
-
/// Polygon 点击回调
|
|
32
|
-
var onPolygonPress: (([String: Any]) -> Void)?
|
|
33
|
-
/// Polyline 点击回调
|
|
34
|
-
var onPolylinePress: (([String: Any]) -> Void)?
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* 初始化覆盖物管理器
|
|
38
|
-
* @param mapView 地图视图实例
|
|
39
|
-
*/
|
|
40
|
-
init(mapView: MAMapView) {
|
|
41
|
-
self.mapView = mapView
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 检查点击位置是否在圆形内
|
|
46
|
-
*/
|
|
47
|
-
func checkCirclePress(at coordinate: CLLocationCoordinate2D) -> Bool {
|
|
48
|
-
for (circle, circleId) in circleIdMap {
|
|
49
|
-
let circleCenter = circle.coordinate
|
|
50
|
-
let fromLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
|
|
51
|
-
let toLocation = CLLocation(latitude: circleCenter.latitude, longitude: circleCenter.longitude)
|
|
52
|
-
let distance = fromLocation.distance(from: toLocation)
|
|
53
|
-
|
|
54
|
-
if distance <= circle.radius {
|
|
55
|
-
onCirclePress?([
|
|
56
|
-
"circleId": circleId,
|
|
57
|
-
"latitude": coordinate.latitude,
|
|
58
|
-
"longitude": coordinate.longitude
|
|
59
|
-
])
|
|
60
|
-
return true
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return false
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// MARK: - Circle 圆形
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 添加圆形覆盖物
|
|
70
|
-
* @param id 圆形唯一标识
|
|
71
|
-
* @param props 圆形属性(center, radius, fillColor, strokeColor, strokeWidth)
|
|
72
|
-
*/
|
|
73
|
-
func addCircle(id: String, props: [String: Any]) {
|
|
74
|
-
guard let mapView = mapView,
|
|
75
|
-
let center = props["center"] as? [String: Double],
|
|
76
|
-
let latitude = center["latitude"],
|
|
77
|
-
let longitude = center["longitude"],
|
|
78
|
-
let radius = props["radius"] as? Double else { return }
|
|
79
|
-
|
|
80
|
-
let circle = MACircle(center: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), radius: radius)
|
|
81
|
-
overlayStyles[id] = props
|
|
82
|
-
overlays[id] = circle
|
|
83
|
-
circleIdMap[circle!] = id
|
|
84
|
-
mapView.add(circle!)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* 移除圆形覆盖物
|
|
89
|
-
* @param id 圆形唯一标识
|
|
90
|
-
*/
|
|
91
|
-
func removeCircle(id: String) {
|
|
92
|
-
guard let mapView = mapView, let circle = overlays[id] as? MACircle else { return }
|
|
93
|
-
mapView.remove(circle)
|
|
94
|
-
overlays.removeValue(forKey: id)
|
|
95
|
-
overlayStyles.removeValue(forKey: id)
|
|
96
|
-
circleIdMap.removeValue(forKey: circle)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* 更新圆形覆盖物
|
|
101
|
-
* @param id 圆形唯一标识
|
|
102
|
-
* @param props 新的圆形属性
|
|
103
|
-
*/
|
|
104
|
-
func updateCircle(id: String, props: [String: Any]) {
|
|
105
|
-
removeCircle(id: id)
|
|
106
|
-
addCircle(id: id, props: props)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// MARK: - Marker 标记点
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* 添加标记点
|
|
113
|
-
* @param id 标记点唯一标识
|
|
114
|
-
* @param props 标记点属性(position, title, description)
|
|
115
|
-
*/
|
|
116
|
-
func addMarker(id: String, props: [String: Any]) {
|
|
117
|
-
guard let mapView = mapView,
|
|
118
|
-
let position = props["position"] as? [String: Double],
|
|
119
|
-
let latitude = position["latitude"],
|
|
120
|
-
let longitude = position["longitude"] else { return }
|
|
121
|
-
|
|
122
|
-
let annotation = MAPointAnnotation()
|
|
123
|
-
annotation.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
|
|
124
|
-
annotation.title = props["title"] as? String
|
|
125
|
-
annotation.subtitle = props["snippet"] as? String ?? props["description"] as? String
|
|
126
|
-
|
|
127
|
-
// 先保存 props 和 annotation,再添加到地图
|
|
128
|
-
// 这样 viewFor annotation 回调时就能找到 props
|
|
129
|
-
annotations[id] = annotation
|
|
130
|
-
markerProps[id] = props
|
|
131
|
-
|
|
132
|
-
mapView.addAnnotation(annotation)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 根据 annotation 获取 marker 属性
|
|
137
|
-
* @param annotation 标记点对象
|
|
138
|
-
* @return 对应的属性字典
|
|
139
|
-
*/
|
|
140
|
-
func getMarkerProps(for annotation: MAAnnotation) -> [String: Any]? {
|
|
141
|
-
guard let id = getMarkerId(for: annotation) else { return nil }
|
|
142
|
-
return markerProps[id]
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* 移除标记点
|
|
147
|
-
* @param id 标记点唯一标识
|
|
148
|
-
*/
|
|
149
|
-
func removeMarker(id: String) {
|
|
150
|
-
guard let mapView = mapView, let annotation = annotations[id] else { return }
|
|
151
|
-
mapView.removeAnnotation(annotation)
|
|
152
|
-
annotations.removeValue(forKey: id)
|
|
153
|
-
markerProps.removeValue(forKey: id)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* 更新标记点
|
|
158
|
-
* @param id 标记点唯一标识
|
|
159
|
-
* @param props 新的标记点属性
|
|
160
|
-
*/
|
|
161
|
-
func updateMarker(id: String, props: [String: Any]) {
|
|
162
|
-
removeMarker(id: id)
|
|
163
|
-
addMarker(id: id, props: props)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* 根据 annotation 获取 markerId
|
|
168
|
-
* @param annotation 标记点对象
|
|
169
|
-
* @return 对应的 markerId,如果未找到返回 nil
|
|
170
|
-
*/
|
|
171
|
-
func getMarkerId(for annotation: MAAnnotation) -> String? {
|
|
172
|
-
return annotations.first(where: { $0.value === annotation })?.key
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// MARK: - Polyline 折线
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* 添加折线覆盖物
|
|
179
|
-
* @param id 折线唯一标识
|
|
180
|
-
* @param props 折线属性(points, strokeWidth, strokeColor, texture)
|
|
181
|
-
*/
|
|
182
|
-
func addPolyline(id: String, props: [String: Any]) {
|
|
183
|
-
guard let mapView = mapView,
|
|
184
|
-
let points = props["points"] as? [[String: Double]] else {
|
|
185
|
-
return
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
var coordinates: [CLLocationCoordinate2D] = []
|
|
189
|
-
for point in points {
|
|
190
|
-
guard let lat = point["latitude"], let lng = point["longitude"] else { continue }
|
|
191
|
-
coordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lng))
|
|
192
|
-
}
|
|
193
|
-
guard coordinates.count >= 2 else {
|
|
194
|
-
return
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
let polyline = MAPolyline(coordinates: &coordinates, count: UInt(coordinates.count))!
|
|
198
|
-
|
|
199
|
-
// 先保存样式和 overlay,再添加到地图
|
|
200
|
-
overlayStyles[id] = props
|
|
201
|
-
overlays[id] = polyline
|
|
202
|
-
polylineIdMap[polyline] = id
|
|
203
|
-
mapView.add(polyline)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* 移除折线覆盖物
|
|
208
|
-
* @param id 折线唯一标识
|
|
209
|
-
*/
|
|
210
|
-
func removePolyline(id: String) {
|
|
211
|
-
guard let mapView = mapView, let polyline = overlays[id] as? MAPolyline else { return }
|
|
212
|
-
mapView.remove(polyline)
|
|
213
|
-
overlays.removeValue(forKey: id)
|
|
214
|
-
overlayStyles.removeValue(forKey: id)
|
|
215
|
-
polylineIdMap.removeValue(forKey: polyline)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* 更新折线覆盖物
|
|
220
|
-
* @param id 折线唯一标识
|
|
221
|
-
* @param props 新的折线属性
|
|
222
|
-
*/
|
|
223
|
-
func updatePolyline(id: String, props: [String: Any]) {
|
|
224
|
-
removePolyline(id: id)
|
|
225
|
-
addPolyline(id: id, props: props)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// MARK: - Polygon 多边形
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* 添加多边形覆盖物
|
|
232
|
-
* @param id 多边形唯一标识
|
|
233
|
-
* @param props 多边形属性(points, fillColor, strokeColor, strokeWidth)
|
|
234
|
-
*/
|
|
235
|
-
func addPolygon(id: String, props: [String: Any]) {
|
|
236
|
-
guard let mapView = mapView,
|
|
237
|
-
let points = props["points"] as? [[String: Double]] else { return }
|
|
238
|
-
var coordinates: [CLLocationCoordinate2D] = []
|
|
239
|
-
for point in points {
|
|
240
|
-
guard let lat = point["latitude"], let lng = point["longitude"] else { continue }
|
|
241
|
-
coordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lng))
|
|
242
|
-
}
|
|
243
|
-
guard !coordinates.isEmpty else { return }
|
|
244
|
-
let polygon = MAPolygon(coordinates: &coordinates, count: UInt(coordinates.count))
|
|
245
|
-
overlayStyles[id] = props
|
|
246
|
-
overlays[id] = polygon
|
|
247
|
-
polygonIdMap[polygon!] = id
|
|
248
|
-
mapView.add(polygon!)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* 移除多边形覆盖物
|
|
253
|
-
* @param id 多边形唯一标识
|
|
254
|
-
*/
|
|
255
|
-
func removePolygon(id: String) {
|
|
256
|
-
guard let mapView = mapView, let polygon = overlays[id] as? MAPolygon else { return }
|
|
257
|
-
mapView.remove(polygon)
|
|
258
|
-
overlays.removeValue(forKey: id)
|
|
259
|
-
overlayStyles.removeValue(forKey: id)
|
|
260
|
-
polygonIdMap.removeValue(forKey: polygon)
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* 更新多边形覆盖物
|
|
265
|
-
* @param id 多边形唯一标识
|
|
266
|
-
* @param props 新的多边形属性
|
|
267
|
-
*/
|
|
268
|
-
func updatePolygon(id: String, props: [String: Any]) {
|
|
269
|
-
removePolygon(id: id)
|
|
270
|
-
addPolygon(id: id, props: props)
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// MARK: - Renderer 渲染器
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* 获取覆盖物渲染器
|
|
277
|
-
* @param overlay 覆盖物对象
|
|
278
|
-
* @return 对应的渲染器
|
|
279
|
-
*/
|
|
280
|
-
func getRenderer(for overlay: MAOverlay) -> MAOverlayRenderer? {
|
|
281
|
-
let id = overlays.first(where: { $0.value === overlay })?.key
|
|
282
|
-
let style = id != nil ? overlayStyles[id!] : nil
|
|
283
|
-
|
|
284
|
-
if let circle = overlay as? MACircle {
|
|
285
|
-
guard let renderer = MACircleRenderer(circle: circle) else {
|
|
286
|
-
return nil
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if let fillColor = style?["fillColor"] {
|
|
290
|
-
renderer.fillColor = ColorParser.parseColor(fillColor)
|
|
291
|
-
}
|
|
292
|
-
if let strokeColor = style?["strokeColor"] {
|
|
293
|
-
renderer.strokeColor = ColorParser.parseColor(strokeColor)
|
|
294
|
-
}
|
|
295
|
-
if let strokeWidth = style?["strokeWidth"] as? Double {
|
|
296
|
-
renderer.lineWidth = CGFloat(strokeWidth)
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return renderer
|
|
300
|
-
} else if let polyline = overlay as? MAPolyline {
|
|
301
|
-
let renderer = MAPolylineRenderer(polyline: polyline)!
|
|
302
|
-
|
|
303
|
-
print("🔷 OverlayManager.getRenderer(Polyline): style=\(String(describing: style))")
|
|
304
|
-
|
|
305
|
-
// 设置线宽
|
|
306
|
-
if let width = style?["width"] as? Double {
|
|
307
|
-
renderer.lineWidth = CGFloat(width)
|
|
308
|
-
|
|
309
|
-
} else if let strokeWidth = style?["strokeWidth"] as? Double {
|
|
310
|
-
renderer.lineWidth = CGFloat(strokeWidth)
|
|
311
|
-
|
|
312
|
-
} else {
|
|
313
|
-
renderer.lineWidth = 8
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// 设置线条样式
|
|
318
|
-
renderer.lineJoinType = kMALineJoinRound
|
|
319
|
-
renderer.lineCapType = kMALineCapRound
|
|
320
|
-
|
|
321
|
-
// 设置纹理或颜色
|
|
322
|
-
if let textureUrl = style?["texture"] as? String, !textureUrl.isEmpty {
|
|
323
|
-
loadPolylineTexture(url: textureUrl, renderer: renderer)
|
|
324
|
-
} else {
|
|
325
|
-
if let color = style?["color"] {
|
|
326
|
-
let parsedColor = ColorParser.parseColor(color)
|
|
327
|
-
renderer.strokeColor = parsedColor ?? .red
|
|
328
|
-
} else if let strokeColor = style?["strokeColor"] {
|
|
329
|
-
let parsedColor = ColorParser.parseColor(strokeColor)
|
|
330
|
-
renderer.strokeColor = parsedColor ?? .red
|
|
331
|
-
} else {
|
|
332
|
-
renderer.strokeColor = .red
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
return renderer
|
|
337
|
-
} else if let polygon = overlay as? MAPolygon {
|
|
338
|
-
guard let renderer = MAPolygonRenderer(polygon: polygon) else {
|
|
339
|
-
return nil
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// 设置填充颜色
|
|
343
|
-
if let fillColor = style?["fillColor"] {
|
|
344
|
-
let parsedColor = ColorParser.parseColor(fillColor)
|
|
345
|
-
renderer.fillColor = parsedColor
|
|
346
|
-
|
|
347
|
-
}
|
|
348
|
-
// 设置边框颜色
|
|
349
|
-
if let strokeColor = style?["strokeColor"] {
|
|
350
|
-
let parsedColor = ColorParser.parseColor(strokeColor)
|
|
351
|
-
renderer.strokeColor = parsedColor
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
// 设置边框宽度
|
|
355
|
-
if let strokeWidth = style?["strokeWidth"] as? Double {
|
|
356
|
-
renderer.lineWidth = CGFloat(strokeWidth)
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
return renderer
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
return nil
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* 加载折线纹理图片
|
|
368
|
-
* @param url 图片 URL (支持 http/https/file/本地资源)
|
|
369
|
-
* @param renderer 折线渲染器
|
|
370
|
-
*/
|
|
371
|
-
private func loadPolylineTexture(url: String, renderer: MAPolylineRenderer) {
|
|
372
|
-
if url.hasPrefix("http://") || url.hasPrefix("https://") {
|
|
373
|
-
// 网络图片
|
|
374
|
-
guard let imageUrl = URL(string: url) else {
|
|
375
|
-
return
|
|
376
|
-
}
|
|
377
|
-
URLSession.shared.dataTask(with: imageUrl) { [weak self] data, _, error in
|
|
378
|
-
if let error = error {
|
|
379
|
-
return
|
|
380
|
-
}
|
|
381
|
-
guard let data = data, let image = UIImage(data: data) else {
|
|
382
|
-
return
|
|
383
|
-
}
|
|
384
|
-
DispatchQueue.main.async {
|
|
385
|
-
self?.applyPolylineTexture(image: image, to: renderer)
|
|
386
|
-
}
|
|
387
|
-
}.resume()
|
|
388
|
-
} else if url.hasPrefix("file://") {
|
|
389
|
-
// 本地文件
|
|
390
|
-
let path = String(url.dropFirst(7))
|
|
391
|
-
if let image = UIImage(contentsOfFile: path) {
|
|
392
|
-
applyPolylineTexture(image: image, to: renderer)
|
|
393
|
-
}
|
|
394
|
-
} else {
|
|
395
|
-
// 资源文件
|
|
396
|
-
if let image = UIImage(named: url) {
|
|
397
|
-
applyPolylineTexture(image: image, to: renderer)
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* 应用纹理到折线渲染器
|
|
404
|
-
* @param image 纹理图片
|
|
405
|
-
* @param renderer 折线渲染器
|
|
406
|
-
*/
|
|
407
|
-
private func applyPolylineTexture(image: UIImage, to renderer: MAPolylineRenderer) {
|
|
408
|
-
renderer.strokeImage = image
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* 检查点击位置是否在多边形内
|
|
413
|
-
*/
|
|
414
|
-
func checkPolygonPress(at coordinate: CLLocationCoordinate2D) -> Bool {
|
|
415
|
-
for (polygon, polygonId) in polygonIdMap {
|
|
416
|
-
let count = Int(polygon.pointCount)
|
|
417
|
-
guard count >= 3 else { continue }
|
|
418
|
-
|
|
419
|
-
var coords = [CLLocationCoordinate2D](repeating: CLLocationCoordinate2D(), count: count)
|
|
420
|
-
polygon.getCoordinates(&coords, range: NSRange(location: 0, length: count))
|
|
421
|
-
|
|
422
|
-
if isPoint(coordinate, inPolygon: coords) {
|
|
423
|
-
onPolygonPress?([
|
|
424
|
-
"polygonId": polygonId,
|
|
425
|
-
"latitude": coordinate.latitude,
|
|
426
|
-
"longitude": coordinate.longitude
|
|
427
|
-
])
|
|
428
|
-
return true
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return false
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* 检查点击位置是否在折线附近
|
|
436
|
-
*/
|
|
437
|
-
func checkPolylinePress(at coordinate: CLLocationCoordinate2D) -> Bool {
|
|
438
|
-
let threshold: Double = 20.0
|
|
439
|
-
for (polyline, polylineId) in polylineIdMap {
|
|
440
|
-
let count = Int(polyline.pointCount)
|
|
441
|
-
guard count >= 2 else { continue }
|
|
442
|
-
|
|
443
|
-
var coords = [CLLocationCoordinate2D](repeating: CLLocationCoordinate2D(), count: count)
|
|
444
|
-
polyline.getCoordinates(&coords, range: NSRange(location: 0, length: count))
|
|
445
|
-
|
|
446
|
-
if isPoint(coordinate, nearPolyline: coords, threshold: threshold) {
|
|
447
|
-
onPolylinePress?([
|
|
448
|
-
"polylineId": polylineId,
|
|
449
|
-
"latitude": coordinate.latitude,
|
|
450
|
-
"longitude": coordinate.longitude
|
|
451
|
-
])
|
|
452
|
-
return true
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
return false
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
private func isPoint(_ point: CLLocationCoordinate2D, inPolygon coords: [CLLocationCoordinate2D]) -> Bool {
|
|
459
|
-
var inside = false
|
|
460
|
-
var j = coords.count - 1
|
|
461
|
-
|
|
462
|
-
for i in 0..<coords.count {
|
|
463
|
-
if ((coords[i].latitude > point.latitude) != (coords[j].latitude > point.latitude)) {
|
|
464
|
-
let slope = (coords[j].longitude - coords[i].longitude) * (point.latitude - coords[i].latitude) / (coords[j].latitude - coords[i].latitude)
|
|
465
|
-
if point.longitude < slope + coords[i].longitude {
|
|
466
|
-
inside = !inside
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
j = i
|
|
470
|
-
}
|
|
471
|
-
return inside
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
private func isPoint(_ point: CLLocationCoordinate2D, nearPolyline coords: [CLLocationCoordinate2D], threshold: Double) -> Bool {
|
|
475
|
-
for i in 0..<(coords.count - 1) {
|
|
476
|
-
let distance = distanceFromPoint(point, toLineSegment: (coords[i], coords[i + 1]))
|
|
477
|
-
if distance <= threshold {
|
|
478
|
-
return true
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
return false
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
private func distanceFromPoint(_ point: CLLocationCoordinate2D, toLineSegment line: (CLLocationCoordinate2D, CLLocationCoordinate2D)) -> Double {
|
|
485
|
-
let p = CLLocation(latitude: point.latitude, longitude: point.longitude)
|
|
486
|
-
let a = CLLocation(latitude: line.0.latitude, longitude: line.0.longitude)
|
|
487
|
-
let b = CLLocation(latitude: line.1.latitude, longitude: line.1.longitude)
|
|
488
|
-
|
|
489
|
-
let ab = a.distance(from: b)
|
|
490
|
-
if ab == 0 { return a.distance(from: p) }
|
|
491
|
-
|
|
492
|
-
let t = max(0, min(1, ((p.coordinate.latitude - a.coordinate.latitude) * (b.coordinate.latitude - a.coordinate.latitude) +
|
|
493
|
-
(p.coordinate.longitude - a.coordinate.longitude) * (b.coordinate.longitude - a.coordinate.longitude)) /
|
|
494
|
-
(ab * ab)))
|
|
495
|
-
|
|
496
|
-
let projection = CLLocationCoordinate2D(
|
|
497
|
-
latitude: a.coordinate.latitude + t * (b.coordinate.latitude - a.coordinate.latitude),
|
|
498
|
-
longitude: a.coordinate.longitude + t * (b.coordinate.longitude - a.coordinate.longitude)
|
|
499
|
-
)
|
|
500
|
-
|
|
501
|
-
return p.distance(from: CLLocation(latitude: projection.latitude, longitude: projection.longitude))
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* 清除所有覆盖物和标记点
|
|
506
|
-
*/
|
|
507
|
-
func clear() {
|
|
508
|
-
guard let mapView = mapView else { return }
|
|
509
|
-
for overlay in overlays.values {
|
|
510
|
-
mapView.remove(overlay)
|
|
511
|
-
}
|
|
512
|
-
for annotation in annotations.values {
|
|
513
|
-
mapView.removeAnnotation(annotation)
|
|
514
|
-
}
|
|
515
|
-
overlays.removeAll()
|
|
516
|
-
overlayStyles.removeAll()
|
|
517
|
-
annotations.removeAll()
|
|
518
|
-
circleIdMap.removeAll()
|
|
519
|
-
polygonIdMap.removeAll()
|
|
520
|
-
polylineIdMap.removeAll()
|
|
521
|
-
}
|
|
522
|
-
}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
//高德地图定位模块
|
|
2
|
-
|
|
3
|
-
import { EventSubscription } from 'expo-modules-core';
|
|
4
|
-
import ExpoGaodeMapModule from '../ExpoGaodeMapModule';
|
|
5
|
-
import type {
|
|
6
|
-
Coordinates,
|
|
7
|
-
ReGeocode,
|
|
8
|
-
LocationOptions,
|
|
9
|
-
LocationListener,
|
|
10
|
-
LatLng,
|
|
11
|
-
CoordinateType,
|
|
12
|
-
} from '../types';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 配置方法映射表
|
|
17
|
-
* @type {Record<keyof LocationOptions, string>}
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
const CONFIG_MAP: Record<keyof LocationOptions, string> = {
|
|
21
|
-
withReGeocode: 'setLocatingWithReGeocode',
|
|
22
|
-
accuracy: 'setDesiredAccuracy',
|
|
23
|
-
mode: 'setLocationMode',
|
|
24
|
-
onceLocation: 'setOnceLocation',
|
|
25
|
-
interval: 'setInterval',
|
|
26
|
-
timeout: 'setLocationTimeout',
|
|
27
|
-
reGeocodeTimeout: 'setReGeocodeTimeout',
|
|
28
|
-
distanceFilter: 'setDistanceFilter',
|
|
29
|
-
sensorEnable: 'setSensorEnable',
|
|
30
|
-
wifiScan: 'setWifiScan',
|
|
31
|
-
gpsFirst: 'setGpsFirst',
|
|
32
|
-
onceLocationLatest: 'setOnceLocationLatest',
|
|
33
|
-
geoLanguage: 'setGeoLanguage',
|
|
34
|
-
allowsBackgroundLocationUpdates: 'setAllowsBackgroundLocationUpdates',
|
|
35
|
-
pausesLocationUpdatesAutomatically: 'setPausesLocationUpdatesAutomatically',
|
|
36
|
-
locationCacheEnable: 'setLocationCacheEnable',
|
|
37
|
-
httpTimeout: 'setHttpTimeOut',
|
|
38
|
-
protocol: 'setLocationProtocol',
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 配置高德地图定位选项
|
|
43
|
-
* @param {LocationOptions} options - 定位配置选项对象
|
|
44
|
-
* @throws {Error} 当传入的配置方法不存在或不可调用时抛出错误
|
|
45
|
-
*/
|
|
46
|
-
export function configure(options: LocationOptions): void {
|
|
47
|
-
Object.entries(options).forEach(([key, value]) => {
|
|
48
|
-
if (value !== undefined) {
|
|
49
|
-
const methodName = CONFIG_MAP[key as keyof LocationOptions];
|
|
50
|
-
const method = ExpoGaodeMapModule[methodName as keyof typeof ExpoGaodeMapModule];
|
|
51
|
-
if (typeof method === 'function') {
|
|
52
|
-
(method as any).call(ExpoGaodeMapModule, value);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 启动高德地图模块,开始连续定位
|
|
61
|
-
* @throws 如果模块未初始化或启动失败时抛出异常
|
|
62
|
-
*/
|
|
63
|
-
export function start(): void {
|
|
64
|
-
ExpoGaodeMapModule.start?.();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 停止高德地图相关功能,停止定位
|
|
70
|
-
* @returns {void} 无返回值
|
|
71
|
-
*/
|
|
72
|
-
export function stop(): void {
|
|
73
|
-
ExpoGaodeMapModule.stop?.();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* 检查高德地图模块是否已启动,是否正在定位
|
|
79
|
-
* @returns {Promise<boolean>} 返回一个Promise,解析为布尔值表示模块是否已启动
|
|
80
|
-
*/
|
|
81
|
-
export async function isStarted(): Promise<boolean> {
|
|
82
|
-
return ExpoGaodeMapModule.isStarted?.() || Promise.resolve(false);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* 获取设备当前位置信息,单次定位
|
|
88
|
-
* @returns {Promise<Coordinates | ReGeocode>} 返回包含坐标或逆地理编码信息的Promise
|
|
89
|
-
* @throws 如果定位服务不可用或权限被拒绝时抛出错误
|
|
90
|
-
*/
|
|
91
|
-
export async function getCurrentLocation(): Promise<Coordinates | ReGeocode> {
|
|
92
|
-
return ExpoGaodeMapModule.getCurrentLocation?.();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* 添加位置更新监听器
|
|
98
|
-
* @param {LocationListener} listener - 位置更新时的回调函数
|
|
99
|
-
* @returns {EventSubscription} 事件订阅对象,包含移除监听器的方法
|
|
100
|
-
* @throws 如果底层模块不可用,返回一个空操作的订阅对象
|
|
101
|
-
*/
|
|
102
|
-
export function addLocationListener(listener: LocationListener): EventSubscription {
|
|
103
|
-
return ExpoGaodeMapModule.addListener?.('onLocationUpdate', listener) || {
|
|
104
|
-
remove: () => {},
|
|
105
|
-
} as EventSubscription;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* 将坐标点转换为指定坐标系下的坐标
|
|
111
|
-
* @param {LatLng} coordinate - 需要转换的原始坐标点
|
|
112
|
-
* @param {CoordinateType} type - 目标坐标系类型
|
|
113
|
-
* @returns {Promise<LatLng>} 转换后的坐标点Promise
|
|
114
|
-
* @throws 如果底层模块不可用,则返回原始坐标
|
|
115
|
-
*/
|
|
116
|
-
export async function coordinateConvert(
|
|
117
|
-
coordinate: LatLng,
|
|
118
|
-
type: CoordinateType
|
|
119
|
-
): Promise<LatLng> {
|
|
120
|
-
return ExpoGaodeMapModule.coordinateConvert?.(coordinate, type) || Promise.resolve(coordinate);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* 开始更新设备方向(罗盘朝向)
|
|
126
|
-
* 调用原生模块方法启动方向更新功能
|
|
127
|
-
* @throws 如果原生模块未实现此方法会抛出异常
|
|
128
|
-
* @platform ios
|
|
129
|
-
*/
|
|
130
|
-
export function startUpdatingHeading(): void {
|
|
131
|
-
ExpoGaodeMapModule.startUpdatingHeading?.();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 停止更新设备方向(罗盘朝向)
|
|
137
|
-
* 调用原生模块方法停止监听设备方向变化
|
|
138
|
-
* @throws 如果原生模块未实现此方法会抛出异常
|
|
139
|
-
* @platform ios
|
|
140
|
-
*/
|
|
141
|
-
export function stopUpdatingHeading(): void {
|
|
142
|
-
ExpoGaodeMapModule.stopUpdatingHeading?.();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* 设置高德地图的API密钥
|
|
147
|
-
* @param {string} key - 高德地图的API密钥
|
|
148
|
-
* @returns {void}
|
|
149
|
-
*/
|
|
150
|
-
export function setApiKey(key: string): void {
|
|
151
|
-
ExpoGaodeMapModule.setApiKey?.(key);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export default {
|
|
155
|
-
configure,
|
|
156
|
-
start,
|
|
157
|
-
stop,
|
|
158
|
-
isStarted,
|
|
159
|
-
getCurrentLocation,
|
|
160
|
-
addLocationListener,
|
|
161
|
-
coordinateConvert,
|
|
162
|
-
startUpdatingHeading,
|
|
163
|
-
stopUpdatingHeading,
|
|
164
|
-
setApiKey,
|
|
165
|
-
};
|