expo-gaode-map 0.1.6 → 1.0.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.
Files changed (50) hide show
  1. package/PUBLISHING.md +1 -1
  2. package/README.md +68 -27
  3. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +117 -26
  4. package/android/src/main/java/expo/modules/gaodemap/ExpoGaodeMapView.kt +97 -36
  5. package/android/src/main/java/expo/modules/gaodemap/managers/CameraManager.kt +27 -21
  6. package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +4 -23
  7. package/android/src/main/java/expo/modules/gaodemap/managers/UIManager.kt +30 -27
  8. package/android/src/main/java/expo/modules/gaodemap/modules/LocationManager.kt +49 -4
  9. package/android/src/main/java/expo/modules/gaodemap/modules/SDKInitializer.kt +13 -5
  10. package/android/src/main/java/expo/modules/gaodemap/overlays/CircleView.kt +0 -6
  11. package/build/ExpoGaodeMapView.js +2 -2
  12. package/build/ExpoGaodeMapView.js.map +1 -1
  13. package/build/index.d.ts +2 -0
  14. package/build/index.d.ts.map +1 -1
  15. package/build/index.js +3 -1
  16. package/build/index.js.map +1 -1
  17. package/build/modules/AMapPermissions.d.ts +27 -0
  18. package/build/modules/AMapPermissions.d.ts.map +1 -0
  19. package/build/modules/AMapPermissions.js +31 -0
  20. package/build/modules/AMapPermissions.js.map +1 -0
  21. package/build/modules/AMapView.d.ts +7 -2
  22. package/build/modules/AMapView.d.ts.map +1 -1
  23. package/build/modules/AMapView.js +15 -3
  24. package/build/modules/AMapView.js.map +1 -1
  25. package/build/types/common.types.d.ts +1 -0
  26. package/build/types/common.types.d.ts.map +1 -1
  27. package/build/types/common.types.js +1 -0
  28. package/build/types/common.types.js.map +1 -1
  29. package/docs/API.md +5 -1
  30. package/docs/ARCHITECTURE.md +421 -0
  31. package/docs/EXAMPLES.md +166 -24
  32. package/docs/INITIALIZATION.md +335 -0
  33. package/ios/ExpoGaodeMapModule.swift +95 -9
  34. package/ios/ExpoGaodeMapView.swift +88 -6
  35. package/ios/managers/CameraManager.swift +58 -0
  36. package/ios/managers/OverlayManager.swift +105 -29
  37. package/ios/managers/UIManager.swift +73 -1
  38. package/ios/modules/LocationManager.swift +109 -3
  39. package/ios/overlays/CircleView.swift +53 -0
  40. package/ios/overlays/HeatMapView.swift +27 -0
  41. package/ios/overlays/MarkerView.swift +29 -1
  42. package/ios/overlays/PolygonView.swift +51 -0
  43. package/ios/overlays/PolylineView.swift +61 -14
  44. package/ios/utils/PermissionManager.swift +58 -0
  45. package/package.json +1 -1
  46. package/src/ExpoGaodeMapView.tsx +2 -2
  47. package/src/index.ts +9 -1
  48. package/src/modules/AMapPermissions.ts +48 -0
  49. package/src/modules/AMapView.ts +15 -3
  50. package/src/types/common.types.ts +1 -0
@@ -1,25 +1,47 @@
1
1
  import ExpoModulesCore
2
2
  import MAMapKit
3
3
 
4
+ /**
5
+ * 多边形覆盖物视图
6
+ *
7
+ * 负责:
8
+ * - 在地图上绘制多边形
9
+ * - 管理多边形样式(填充色、边框色、边框宽度)
10
+ * - 响应属性变化并更新渲染
11
+ */
4
12
  class PolygonView: ExpoView {
13
+ /// 多边形点数组
5
14
  var points: [[String: Double]] = []
15
+ /// 填充颜色
6
16
  var fillColor: Any?
17
+ /// 边框颜色
7
18
  var strokeColor: Any?
19
+ /// 边框宽度
8
20
  var strokeWidth: Float = 0
9
21
 
22
+ /// 地图视图弱引用
10
23
  private var mapView: MAMapView?
24
+ /// 多边形覆盖物对象
11
25
  var polygon: MAPolygon?
26
+ /// 多边形渲染器
12
27
  private var renderer: MAPolygonRenderer?
13
28
 
14
29
  required init(appContext: AppContext? = nil) {
15
30
  super.init(appContext: appContext)
16
31
  }
17
32
 
33
+ /**
34
+ * 设置地图实例
35
+ * @param map 地图视图
36
+ */
18
37
  func setMap(_ map: MAMapView) {
19
38
  self.mapView = map
20
39
  updatePolygon()
21
40
  }
22
41
 
42
+ /**
43
+ * 更新多边形覆盖物
44
+ */
23
45
  private func updatePolygon() {
24
46
  guard let mapView = mapView else { return }
25
47
  if let old = polygon { mapView.remove(old) }
@@ -34,6 +56,10 @@ class PolygonView: ExpoView {
34
56
  mapView.add(polygon!)
35
57
  }
36
58
 
59
+ /**
60
+ * 获取多边形渲染器
61
+ * @return 渲染器实例
62
+ */
37
63
  func getRenderer() -> MAOverlayRenderer {
38
64
  if renderer == nil, let polygon = polygon {
39
65
  renderer = MAPolygonRenderer(polygon: polygon)
@@ -44,27 +70,52 @@ class PolygonView: ExpoView {
44
70
  return renderer!
45
71
  }
46
72
 
73
+ /**
74
+ * 设置多边形点数组
75
+ * @param points 点数组
76
+ */
47
77
  func setPoints(_ points: [[String: Double]]) {
48
78
  self.points = points
49
79
  renderer = nil
50
80
  updatePolygon()
51
81
  }
52
82
 
83
+ /**
84
+ * 设置填充颜色
85
+ * @param color 颜色值
86
+ */
53
87
  func setFillColor(_ color: Any?) {
54
88
  fillColor = color
55
89
  renderer = nil
56
90
  updatePolygon()
57
91
  }
58
92
 
93
+ /**
94
+ * 设置边框颜色
95
+ * @param color 颜色值
96
+ */
59
97
  func setStrokeColor(_ color: Any?) {
60
98
  strokeColor = color
61
99
  renderer = nil
62
100
  updatePolygon()
63
101
  }
64
102
 
103
+ /**
104
+ * 设置边框宽度
105
+ * @param width 宽度值
106
+ */
65
107
  func setStrokeWidth(_ width: Float) {
66
108
  strokeWidth = width
67
109
  renderer = nil
68
110
  updatePolygon()
69
111
  }
112
+
113
+ /**
114
+ * 析构时移除多边形
115
+ */
116
+ deinit {
117
+ if let mapView = mapView, let polygon = polygon {
118
+ mapView.remove(polygon)
119
+ }
120
+ }
70
121
  }
@@ -1,25 +1,47 @@
1
1
  import ExpoModulesCore
2
2
  import MAMapKit
3
3
 
4
+ /**
5
+ * 折线覆盖物视图
6
+ *
7
+ * 负责:
8
+ * - 在地图上绘制折线
9
+ * - 支持纹理贴图
10
+ * - 管理折线样式(线宽、颜色)
11
+ */
4
12
  class PolylineView: ExpoView {
13
+ /// 折线点数组
5
14
  var points: [[String: Double]] = []
15
+ /// 线宽
6
16
  var strokeWidth: Float = 0
17
+ /// 线条颜色
7
18
  var strokeColor: Any?
19
+ /// 纹理图片 URL
8
20
  var textureUrl: String?
9
21
 
22
+ /// 地图视图弱引用
10
23
  private var mapView: MAMapView?
24
+ /// 折线覆盖物对象
11
25
  var polyline: MAPolyline?
26
+ /// 折线渲染器
12
27
  private var renderer: MAPolylineRenderer?
13
28
 
14
29
  required init(appContext: AppContext? = nil) {
15
30
  super.init(appContext: appContext)
16
31
  }
17
32
 
33
+ /**
34
+ * 设置地图实例
35
+ * @param map 地图视图
36
+ */
18
37
  func setMap(_ map: MAMapView) {
19
38
  self.mapView = map
20
39
  updatePolyline()
21
40
  }
22
41
 
42
+ /**
43
+ * 更新折线覆盖物
44
+ */
23
45
  private func updatePolyline() {
24
46
  guard let mapView = mapView else { return }
25
47
  if let old = polyline { mapView.remove(old) }
@@ -34,13 +56,16 @@ class PolylineView: ExpoView {
34
56
  mapView.add(polyline!)
35
57
  }
36
58
 
59
+ /**
60
+ * 获取折线渲染器
61
+ * @return 渲染器实例
62
+ */
37
63
  func getRenderer() -> MAOverlayRenderer {
38
64
  if renderer == nil, let polyline = polyline {
39
65
  renderer = MAPolylineRenderer(polyline: polyline)
40
66
  renderer?.lineWidth = CGFloat(strokeWidth)
41
67
 
42
68
  if let url = textureUrl {
43
- print("🎨 PolylineView: 加载纹理 URL: \(url)")
44
69
  loadTexture(url: url, renderer: renderer!)
45
70
  } else {
46
71
  renderer?.strokeColor = ColorParser.parseColor(strokeColor) ?? UIColor.clear
@@ -49,22 +74,23 @@ class PolylineView: ExpoView {
49
74
  return renderer!
50
75
  }
51
76
 
77
+ /**
78
+ * 加载纹理图片
79
+ * @param url 图片 URL (支持 http/https/file/本地资源)
80
+ * @param renderer 折线渲染器
81
+ */
52
82
  private func loadTexture(url: String, renderer: MAPolylineRenderer) {
53
83
  if url.hasPrefix("http://") || url.hasPrefix("https://") {
54
84
  guard let imageUrl = URL(string: url) else {
55
- print("❌ PolylineView: 无效的 URL: \(url)")
56
85
  return
57
86
  }
58
87
  URLSession.shared.dataTask(with: imageUrl) { [weak self] data, _, error in
59
88
  if let error = error {
60
- print("❌ PolylineView: 下载图片失败: \(error)")
61
89
  return
62
90
  }
63
91
  guard let data = data, let image = UIImage(data: data) else {
64
- print("❌ PolylineView: 无法创建图片")
65
92
  return
66
93
  }
67
- print("✅ PolylineView: 图片下载成功,大小: \(image.size)")
68
94
  DispatchQueue.main.async {
69
95
  self?.applyTexture(image: image, to: renderer)
70
96
  }
@@ -72,53 +98,74 @@ class PolylineView: ExpoView {
72
98
  } else if url.hasPrefix("file://") {
73
99
  let path = String(url.dropFirst(7))
74
100
  if let image = UIImage(contentsOfFile: path) {
75
- print("✅ PolylineView: 本地图片加载成功")
76
101
  applyTexture(image: image, to: renderer)
77
- } else {
78
- print("❌ PolylineView: 本地图片加载失败: \(path)")
79
102
  }
80
103
  } else {
81
104
  if let image = UIImage(named: url) {
82
- print("✅ PolylineView: 资源图片加载成功")
83
105
  applyTexture(image: image, to: renderer)
84
- } else {
85
- print("❌ PolylineView: 资源图片加载失败: \(url)")
86
106
  }
87
107
  }
88
108
  }
89
109
 
110
+ /**
111
+ * 应用纹理到折线渲染器
112
+ * @param image 纹理图片
113
+ * @param renderer 折线渲染器
114
+ */
90
115
  private func applyTexture(image: UIImage, to renderer: MAPolylineRenderer) {
91
116
  let selector = NSSelectorFromString("loadStrokeTextureImage:")
92
117
  if renderer.responds(to: selector) {
93
118
  renderer.perform(selector, with: image)
94
- print("✅ PolylineView: 纹理已应用")
95
119
  mapView?.setNeedsDisplay()
96
- } else {
97
- print("❌ PolylineView: renderer 不支持 loadStrokeTextureImage 方法")
98
120
  }
99
121
  }
100
122
 
123
+ /**
124
+ * 设置折线点数组
125
+ * @param points 点数组
126
+ */
101
127
  func setPoints(_ points: [[String: Double]]) {
102
128
  self.points = points
103
129
  renderer = nil
104
130
  updatePolyline()
105
131
  }
106
132
 
133
+ /**
134
+ * 设置线宽
135
+ * @param width 线宽值
136
+ */
107
137
  func setStrokeWidth(_ width: Float) {
108
138
  strokeWidth = width
109
139
  renderer = nil
110
140
  updatePolyline()
111
141
  }
112
142
 
143
+ /**
144
+ * 设置线条颜色
145
+ * @param color 颜色值
146
+ */
113
147
  func setStrokeColor(_ color: Any?) {
114
148
  strokeColor = color
115
149
  renderer = nil
116
150
  updatePolyline()
117
151
  }
118
152
 
153
+ /**
154
+ * 设置纹理图片
155
+ * @param url 图片 URL
156
+ */
119
157
  func setTexture(_ url: String?) {
120
158
  textureUrl = url
121
159
  renderer = nil
122
160
  updatePolyline()
123
161
  }
162
+
163
+ /**
164
+ * 析构时移除折线
165
+ */
166
+ deinit {
167
+ if let mapView = mapView, let polyline = polyline {
168
+ mapView.remove(polyline)
169
+ }
170
+ }
124
171
  }
@@ -0,0 +1,58 @@
1
+ import Foundation
2
+ import CoreLocation
3
+
4
+ /**
5
+ * 位置权限管理器
6
+ *
7
+ * 负责:
8
+ * - 请求位置权限
9
+ * - 监听权限状态变化
10
+ * - 返回权限结果
11
+ */
12
+ class PermissionManager: NSObject, CLLocationManagerDelegate {
13
+ /// 位置管理器实例
14
+ private var locationManager: CLLocationManager?
15
+ /// 权限请求回调
16
+ private var permissionCallback: ((Bool, String) -> Void)?
17
+
18
+ /**
19
+ * 请求位置权限
20
+ * @param callback 权限结果回调 (granted, status)
21
+ */
22
+ func requestPermission(callback: @escaping (Bool, String) -> Void) {
23
+ self.permissionCallback = callback
24
+
25
+ if locationManager == nil {
26
+ locationManager = CLLocationManager()
27
+ locationManager?.delegate = self
28
+ }
29
+
30
+ locationManager?.requestWhenInUseAuthorization()
31
+ }
32
+
33
+ /**
34
+ * 权限状态变化回调
35
+ */
36
+ func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
37
+ let status = manager.authorizationStatus
38
+ let granted = status == .authorizedAlways || status == .authorizedWhenInUse
39
+ let statusString = getAuthorizationStatusString(status)
40
+
41
+ permissionCallback?(granted, statusString)
42
+ permissionCallback = nil
43
+ }
44
+
45
+ /**
46
+ * 将权限状态转换为字符串
47
+ */
48
+ private func getAuthorizationStatusString(_ status: CLAuthorizationStatus) -> String {
49
+ switch status {
50
+ case .notDetermined: return "notDetermined"
51
+ case .restricted: return "restricted"
52
+ case .denied: return "denied"
53
+ case .authorizedAlways: return "authorizedAlways"
54
+ case .authorizedWhenInUse: return "authorizedWhenInUse"
55
+ @unknown default: return "unknown"
56
+ }
57
+ }
58
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-gaode-map",
3
- "version": "0.1.6",
3
+ "version": "1.0.1",
4
4
  "description": "一个功能完整的高德地图 React Native 组件库,基于 Expo Modules 开发,提供地图显示、定位、覆盖物等功能。",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -2,7 +2,7 @@
2
2
  * @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
3
3
  * @Date : 2025-11-13 14:03:56
4
4
  * @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
5
- * @LastEditTime : 2025-11-13 19:35:20
5
+ * @LastEditTime : 2025-11-15 01:50:18
6
6
  * @FilePath : /expo-gaode-map/src/ExpoGaodeMapView.tsx
7
7
  * @Description : 高德地图视图组件
8
8
  *
@@ -62,7 +62,7 @@ const ExpoGaodeMapView = React.forwardRef<MapViewRef, MapViewProps>((props, ref)
62
62
  const internalRef = React.useRef<MapViewRef | null>(null);
63
63
 
64
64
  const apiRef: MapViewRef = React.useMemo(() => ({
65
- moveCamera: async (position: CameraPosition, duration: number = 0) => {
65
+ moveCamera: async (position: CameraPosition, duration: number = 300) => {
66
66
  if (!nativeRef.current) throw new Error('MapView not initialized');
67
67
  return nativeRef.current.moveCamera(position, duration);
68
68
  },
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
3
3
  * @Date : 2025-11-13 14:45:15
4
4
  * @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
5
- * @LastEditTime : 2025-11-14 16:15:52
5
+ * @LastEditTime : 2025-11-15 02:21:17
6
6
  * @FilePath : /expo-gaode-map/src/index.ts
7
7
  * @Description : 高德地图 Expo Module 主导出文件
8
8
  *
@@ -33,6 +33,14 @@ export {
33
33
  stopUpdatingHeading,
34
34
  } from './modules/AMapLocation';
35
35
 
36
+ // 导出权限管理模块
37
+ export {
38
+ default as AMapPermissions,
39
+ checkLocationPermission,
40
+ requestLocationPermission,
41
+ } from './modules/AMapPermissions';
42
+ export type { PermissionStatus } from './modules/AMapPermissions';
43
+
36
44
  // 地图视图控制已移至 MapView 的 ref 调用
37
45
  // 使用方式: const mapRef = useRef<MapViewRef>(null); mapRef.current.moveCamera() 等
38
46
 
@@ -0,0 +1,48 @@
1
+ /*
2
+ * @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
3
+ * @Date : 2025-11-15 02:20:56
4
+ * @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
5
+ * @LastEditTime : 2025-11-15 02:20:58
6
+ * @FilePath : /expo-gaode-map/src/modules/AMapPermissions.ts
7
+ * @Description :
8
+ *
9
+ * Copyright (c) 2025 by 尚博信_王强, All Rights Reserved.
10
+ */
11
+ /*
12
+ * 高德地图权限管理模块
13
+ */
14
+
15
+ import ExpoGaodeMapModule from '../ExpoGaodeMapModule';
16
+
17
+ /**
18
+ * 权限状态
19
+ */
20
+ export interface PermissionStatus {
21
+ /** 是否已授权 */
22
+ granted: boolean;
23
+ /** iOS 权限状态字符串 */
24
+ status?: 'notDetermined' | 'restricted' | 'denied' | 'authorizedAlways' | 'authorizedWhenInUse' | 'unknown';
25
+ /** Android 精确位置权限 */
26
+ fineLocation?: boolean;
27
+ /** Android 粗略位置权限 */
28
+ coarseLocation?: boolean;
29
+ }
30
+
31
+ /**
32
+ * 检查位置权限状态
33
+ */
34
+ export async function checkLocationPermission(): Promise<PermissionStatus> {
35
+ return await ExpoGaodeMapModule.checkLocationPermission();
36
+ }
37
+
38
+ /**
39
+ * 请求位置权限
40
+ */
41
+ export async function requestLocationPermission(): Promise<PermissionStatus> {
42
+ return await ExpoGaodeMapModule.requestLocationPermission();
43
+ }
44
+
45
+ export default {
46
+ checkLocationPermission,
47
+ requestLocationPermission,
48
+ };
@@ -2,10 +2,17 @@
2
2
  * @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
3
3
  * @Date : 2025-11-13 14:57:30
4
4
  * @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
5
- * @LastEditTime : 2025-11-13 14:57:35
5
+ * @LastEditTime : 2025-11-14 19:38:00
6
6
  * @FilePath : /expo-gaode-map/src/modules/AMapView.ts
7
7
  * @Description : 高德地图视图控制模块
8
8
  *
9
+ * ⚠️ 警告: 此模块中的方法已不推荐使用
10
+ * 请使用 MapView 的 ref 方式调用这些方法
11
+ *
12
+ * 示例:
13
+ * const mapRef = useRef<MapViewRef>(null);
14
+ * mapRef.current?.moveCamera({ target: { latitude: 39.9, longitude: 116.4 }, zoom: 10 });
15
+ *
9
16
  * Copyright (c) 2025 by 尚博信_王强, All Rights Reserved.
10
17
  */
11
18
 
@@ -14,8 +21,9 @@ import type { CameraPosition, Point, LatLng } from '../types';
14
21
 
15
22
  /**
16
23
  * 移动地图相机到指定位置
24
+ * @deprecated 不推荐使用,请使用 MapView ref 的 moveCamera 方法
17
25
  * @param cameraPosition 相机位置参数
18
- * @param duration 动画时长(毫秒),默认为0(无动画)
26
+ * @param duration 动画时长(毫秒),默认为0(无动画)
19
27
  */
20
28
  export function moveCamera(cameraPosition: CameraPosition, duration = 0): void {
21
29
  ExpoGaodeMapModule.moveCamera?.(cameraPosition, duration);
@@ -23,6 +31,7 @@ export function moveCamera(cameraPosition: CameraPosition, duration = 0): void {
23
31
 
24
32
  /**
25
33
  * 将屏幕坐标转换为地理坐标
34
+ * @deprecated 不推荐使用,请使用 MapView ref 的 getLatLng 方法
26
35
  * @param point 屏幕坐标点
27
36
  * @returns 地理坐标
28
37
  */
@@ -32,6 +41,7 @@ export async function getLatLng(point: Point): Promise<LatLng> {
32
41
 
33
42
  /**
34
43
  * 设置地图中心点
44
+ * @deprecated 不推荐使用,请使用 MapView ref 的 setCenter 方法
35
45
  * @param center 中心点坐标
36
46
  * @param animated 是否使用动画
37
47
  */
@@ -41,7 +51,8 @@ export function setCenter(center: LatLng, animated = true): void {
41
51
 
42
52
  /**
43
53
  * 设置地图缩放级别
44
- * @param zoom 缩放级别(3-20)
54
+ * @deprecated 不推荐使用,请使用 MapView ref 的 setZoom 方法
55
+ * @param zoom 缩放级别(3-20)
45
56
  * @param animated 是否使用动画
46
57
  */
47
58
  export function setZoom(zoom: number, animated = true): void {
@@ -50,6 +61,7 @@ export function setZoom(zoom: number, animated = true): void {
50
61
 
51
62
  /**
52
63
  * 获取当前地图状态
64
+ * @deprecated 不推荐使用,请使用 MapView ref 的 getCameraPosition 方法
53
65
  * @returns 当前相机位置
54
66
  */
55
67
  export async function getCameraPosition(): Promise<CameraPosition> {
@@ -112,6 +112,7 @@ export enum MapType {
112
112
 
113
113
  /**
114
114
  * 公交地图
115
+ * @platform android
115
116
  */
116
117
  Bus = 4,
117
118
  }