expo-gaode-map 0.1.5 → 0.1.6
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/java/expo/modules/gaodemap/ExpoGaodeMapModule.kt +4 -0
- package/android/src/main/java/expo/modules/gaodemap/managers/OverlayManager.kt +34 -2
- package/android/src/main/java/expo/modules/gaodemap/overlays/PolylineView.kt +54 -3
- package/build/components/overlays/Polyline.d.ts.map +1 -1
- package/build/components/overlays/Polyline.js +12 -14
- package/build/components/overlays/Polyline.js.map +1 -1
- package/build/types/overlays.types.d.ts +5 -0
- package/build/types/overlays.types.d.ts.map +1 -1
- package/build/types/overlays.types.js.map +1 -1
- package/docs/EXAMPLES.md +66 -5
- package/ios/ExpoGaodeMapModule.swift +4 -0
- package/ios/managers/OverlayManager.swift +89 -23
- package/ios/overlays/PolylineView.swift +63 -1
- package/ios/{ColorParser.swift → utils/ColorParser.swift} +13 -7
- package/package.json +1 -1
- package/src/components/overlays/Polyline.tsx +13 -16
- package/src/types/overlays.types.ts +6 -0
- package/ios/UIColorExtension.swift +0 -11
|
@@ -368,6 +368,10 @@ class ExpoGaodeMapModule : Module() {
|
|
|
368
368
|
Prop<Int>("strokeColor") { view: PolylineView, color ->
|
|
369
369
|
view.setStrokeColor(color)
|
|
370
370
|
}
|
|
371
|
+
|
|
372
|
+
Prop<String?>("texture") { view: PolylineView, texture ->
|
|
373
|
+
view.setTexture(texture)
|
|
374
|
+
}
|
|
371
375
|
}
|
|
372
376
|
|
|
373
377
|
// Polygon - 多边形
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
package expo.modules.gaodemap.managers
|
|
2
2
|
|
|
3
3
|
import android.util.Log
|
|
4
|
+
import android.graphics.BitmapFactory
|
|
4
5
|
import com.amap.api.maps.AMap
|
|
5
6
|
import com.amap.api.maps.model.LatLng
|
|
7
|
+
import com.amap.api.maps.model.BitmapDescriptorFactory
|
|
6
8
|
import expo.modules.gaodemap.utils.ColorParser
|
|
9
|
+
import java.net.URL
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* 覆盖物管理器
|
|
@@ -151,9 +154,14 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
151
154
|
@Suppress("UNCHECKED_CAST")
|
|
152
155
|
val points = props["points"] as? List<Map<String, Double>>
|
|
153
156
|
val width = (props["width"] as? Number)?.toFloat() ?: 10f
|
|
154
|
-
val
|
|
157
|
+
val texture = props["texture"] as? String
|
|
158
|
+
val color = if (!texture.isNullOrEmpty()) {
|
|
159
|
+
android.graphics.Color.TRANSPARENT
|
|
160
|
+
} else {
|
|
161
|
+
ColorParser.parseColor(props["color"])
|
|
162
|
+
}
|
|
155
163
|
|
|
156
|
-
if (points != null && points.
|
|
164
|
+
if (points != null && points.size >= 2) {
|
|
157
165
|
val latLngs = points.map { point ->
|
|
158
166
|
val lat = point["latitude"] ?: 0.0
|
|
159
167
|
val lng = point["longitude"] ?: 0.0
|
|
@@ -166,6 +174,30 @@ class OverlayManager(private val aMap: AMap) {
|
|
|
166
174
|
.color(color)
|
|
167
175
|
|
|
168
176
|
val polyline = aMap.addPolyline(options)
|
|
177
|
+
|
|
178
|
+
// 处理纹理
|
|
179
|
+
if (!texture.isNullOrEmpty()) {
|
|
180
|
+
Thread {
|
|
181
|
+
try {
|
|
182
|
+
val bitmap = if (texture.startsWith("http://") || texture.startsWith("https://")) {
|
|
183
|
+
BitmapFactory.decodeStream(URL(texture).openStream())
|
|
184
|
+
} else if (texture.startsWith("file://")) {
|
|
185
|
+
BitmapFactory.decodeFile(texture.substring(7))
|
|
186
|
+
} else {
|
|
187
|
+
null
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
bitmap?.let {
|
|
191
|
+
val descriptor = BitmapDescriptorFactory.fromBitmap(it)
|
|
192
|
+
polyline.setCustomTexture(descriptor)
|
|
193
|
+
Log.d(TAG, "✅ 纹理设置成功")
|
|
194
|
+
}
|
|
195
|
+
} catch (e: Exception) {
|
|
196
|
+
Log.e(TAG, "纹理加载失败: ${e.message}")
|
|
197
|
+
}
|
|
198
|
+
}.start()
|
|
199
|
+
}
|
|
200
|
+
|
|
169
201
|
polylines[id] = polyline
|
|
170
202
|
Log.d(TAG, "✅ 折线创建成功")
|
|
171
203
|
}
|
|
@@ -3,12 +3,14 @@ package expo.modules.gaodemap.overlays
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.graphics.Color
|
|
5
5
|
import com.amap.api.maps.AMap
|
|
6
|
+
import com.amap.api.maps.model.BitmapDescriptorFactory
|
|
6
7
|
import com.amap.api.maps.model.LatLng
|
|
7
8
|
import com.amap.api.maps.model.Polyline
|
|
8
9
|
import com.amap.api.maps.model.PolylineOptions
|
|
9
10
|
import expo.modules.kotlin.AppContext
|
|
10
11
|
import expo.modules.kotlin.viewevent.EventDispatcher
|
|
11
12
|
import expo.modules.kotlin.views.ExpoView
|
|
13
|
+
import java.net.URL
|
|
12
14
|
|
|
13
15
|
class PolylineView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
|
|
14
16
|
|
|
@@ -17,6 +19,7 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
17
19
|
private var polyline: Polyline? = null
|
|
18
20
|
private var aMap: AMap? = null
|
|
19
21
|
private var points: List<LatLng> = emptyList()
|
|
22
|
+
private var textureUrl: String? = null
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
25
|
* 设置地图实例
|
|
@@ -92,7 +95,6 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
92
95
|
* 设置透明度
|
|
93
96
|
*/
|
|
94
97
|
fun setOpacity(opacity: Float) {
|
|
95
|
-
// 通过修改颜色的 alpha 通道实现透明度
|
|
96
98
|
polyline?.let { line ->
|
|
97
99
|
val currentColor = line.color
|
|
98
100
|
val alpha = (opacity * 255).toInt()
|
|
@@ -100,20 +102,69 @@ class PolylineView(context: Context, appContext: AppContext) : ExpoView(context,
|
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
/**
|
|
106
|
+
* 设置纹理图片
|
|
107
|
+
*/
|
|
108
|
+
fun setTexture(url: String?) {
|
|
109
|
+
textureUrl = url
|
|
110
|
+
createOrUpdatePolyline()
|
|
111
|
+
}
|
|
112
|
+
|
|
103
113
|
/**
|
|
104
114
|
* 创建或更新折线
|
|
105
115
|
*/
|
|
106
116
|
private fun createOrUpdatePolyline() {
|
|
107
117
|
aMap?.let { map ->
|
|
108
|
-
|
|
118
|
+
// 移除旧折线
|
|
119
|
+
polyline?.remove()
|
|
120
|
+
polyline = null
|
|
121
|
+
|
|
122
|
+
if (points.isNotEmpty()) {
|
|
109
123
|
val options = PolylineOptions()
|
|
110
124
|
.addAll(points)
|
|
111
125
|
.width(10f)
|
|
112
126
|
.color(Color.BLUE)
|
|
113
127
|
|
|
128
|
+
// 设置纹理
|
|
129
|
+
textureUrl?.let { url ->
|
|
130
|
+
try {
|
|
131
|
+
when {
|
|
132
|
+
url.startsWith("http://") || url.startsWith("https://") -> {
|
|
133
|
+
// 网络图片异步加载
|
|
134
|
+
Thread {
|
|
135
|
+
try {
|
|
136
|
+
val connection = URL(url).openConnection()
|
|
137
|
+
val inputStream = connection.getInputStream()
|
|
138
|
+
val bitmap = android.graphics.BitmapFactory.decodeStream(inputStream)
|
|
139
|
+
inputStream.close()
|
|
140
|
+
post {
|
|
141
|
+
polyline?.setCustomTexture(BitmapDescriptorFactory.fromBitmap(bitmap))
|
|
142
|
+
}
|
|
143
|
+
} catch (e: Exception) {
|
|
144
|
+
e.printStackTrace()
|
|
145
|
+
}
|
|
146
|
+
}.start()
|
|
147
|
+
}
|
|
148
|
+
url.startsWith("file://") -> {
|
|
149
|
+
val path = url.substring(7)
|
|
150
|
+
val bitmap = android.graphics.BitmapFactory.decodeFile(path)
|
|
151
|
+
bitmap?.let { options.setCustomTexture(BitmapDescriptorFactory.fromBitmap(it)) }
|
|
152
|
+
}
|
|
153
|
+
else -> {
|
|
154
|
+
val resId = context.resources.getIdentifier(url, "drawable", context.packageName)
|
|
155
|
+
if (resId != 0) {
|
|
156
|
+
val bitmap = android.graphics.BitmapFactory.decodeResource(context.resources, resId)
|
|
157
|
+
options.setCustomTexture(BitmapDescriptorFactory.fromBitmap(bitmap))
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
} catch (e: Exception) {
|
|
162
|
+
e.printStackTrace()
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
114
166
|
polyline = map.addPolyline(options)
|
|
115
167
|
|
|
116
|
-
// 设置点击监听
|
|
117
168
|
map.setOnPolylineClickListener { clickedPolyline ->
|
|
118
169
|
if (clickedPolyline == polyline) {
|
|
119
170
|
onPress(mapOf("id" to clickedPolyline.id))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Polyline.d.ts","sourceRoot":"","sources":["../../../src/components/overlays/Polyline.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"Polyline.d.ts","sourceRoot":"","sources":["../../../src/components/overlays/Polyline.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAK,EAAE,aAAa,QAyBpD"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
3
3
|
* @Date : 2025-11-13 15:01:30
|
|
4
4
|
* @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
5
|
-
* @LastEditTime : 2025-11-
|
|
5
|
+
* @LastEditTime : 2025-11-15 01:08:27
|
|
6
6
|
* @FilePath : /expo-gaode-map/src/components/overlays/Polyline.tsx
|
|
7
7
|
* @Description : 地图折线组件 - 使用命令式 API
|
|
8
8
|
*
|
|
@@ -29,25 +29,23 @@ import { MapContext } from '../../ExpoGaodeMapView';
|
|
|
29
29
|
*/
|
|
30
30
|
export default function Polyline(props) {
|
|
31
31
|
const mapRef = React.useContext(MapContext);
|
|
32
|
-
const polylineIdRef = React.useRef(
|
|
33
|
-
const isInitialMount = React.useRef(true);
|
|
32
|
+
const polylineIdRef = React.useRef(null);
|
|
34
33
|
// 添加折线
|
|
35
34
|
React.useEffect(() => {
|
|
36
|
-
const polylineId =
|
|
37
|
-
|
|
35
|
+
const polylineId = `polyline_${Date.now()}_${Math.random()}`;
|
|
36
|
+
polylineIdRef.current = polylineId;
|
|
37
|
+
// 只传递必要的属性
|
|
38
|
+
const polylineProps = {
|
|
39
|
+
points: props.points,
|
|
40
|
+
width: props.width,
|
|
41
|
+
color: props.color,
|
|
42
|
+
...(props.texture && { texture: props.texture }),
|
|
43
|
+
};
|
|
44
|
+
mapRef?.current?.addPolyline?.(polylineId, polylineProps);
|
|
38
45
|
return () => {
|
|
39
46
|
mapRef?.current?.removePolyline?.(polylineId);
|
|
40
47
|
};
|
|
41
48
|
}, []);
|
|
42
|
-
// 监听 Props 变化,更新折线(跳过初始渲染)
|
|
43
|
-
React.useEffect(() => {
|
|
44
|
-
if (isInitialMount.current) {
|
|
45
|
-
isInitialMount.current = false;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const polylineId = polylineIdRef.current;
|
|
49
|
-
mapRef?.current?.updatePolyline?.(polylineId, props);
|
|
50
|
-
}, [props.points, props.width, props.color]);
|
|
51
49
|
return null;
|
|
52
50
|
}
|
|
53
51
|
//# sourceMappingURL=Polyline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Polyline.js","sourceRoot":"","sources":["../../../src/components/overlays/Polyline.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAoB;IACnD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"Polyline.js","sourceRoot":"","sources":["../../../src/components/overlays/Polyline.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,KAAoB;IACnD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAgB,IAAI,CAAC,CAAC;IAExD,OAAO;IACP,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,UAAU,GAAG,YAAY,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAC7D,aAAa,CAAC,OAAO,GAAG,UAAU,CAAC;QAEnC,WAAW;QACX,MAAM,aAAa,GAAG;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;SACjD,CAAC;QAEF,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAE1D,OAAO,GAAG,EAAE;YACV,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,UAAU,CAAC,CAAC;QAChD,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["/*\n * @Author : 尚博信_王强 wangqiang03@sunboxsoft.com\n * @Date : 2025-11-13 15:01:30\n * @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com\n * @LastEditTime : 2025-11-15 01:08:27\n * @FilePath : /expo-gaode-map/src/components/overlays/Polyline.tsx\n * @Description : 地图折线组件 - 使用命令式 API\n * \n * Copyright (c) 2025 by 尚博信_王强, All Rights Reserved. \n */\n\nimport * as React from 'react';\nimport { MapContext } from '../../ExpoGaodeMapView';\nimport type { PolylineProps } from '../../types';\n\n/**\n * 地图折线组件\n * \n * @example\n * ```tsx\n * <MapView>\n * <Polyline\n * points={[\n * { latitude: 39.9, longitude: 116.4 },\n * { latitude: 39.91, longitude: 116.41 },\n * ]}\n * color=\"#FF0000\"\n * width={5}\n * />\n * </MapView>\n * ```\n */\nexport default function Polyline(props: PolylineProps) {\n const mapRef = React.useContext(MapContext);\n const polylineIdRef = React.useRef<string | null>(null);\n\n // 添加折线\n React.useEffect(() => {\n const polylineId = `polyline_${Date.now()}_${Math.random()}`;\n polylineIdRef.current = polylineId;\n \n // 只传递必要的属性\n const polylineProps = {\n points: props.points,\n width: props.width,\n color: props.color,\n ...(props.texture && { texture: props.texture }),\n };\n \n mapRef?.current?.addPolyline?.(polylineId, polylineProps);\n\n return () => {\n mapRef?.current?.removePolyline?.(polylineId);\n };\n }, []);\n\n return null;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlays.types.d.ts","sourceRoot":"","sources":["../../src/types/overlays.types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"overlays.types.d.ts","sourceRoot":"","sources":["../../src/types/overlays.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlays.types.js","sourceRoot":"","sources":["../../src/types/overlays.types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * 高德地图覆盖物相关类型定义\n * 基于 Expo Modules API\n */\n\nimport type { ImageSourcePropType, ViewStyle } from 'react-native';\nimport type { ColorValue, LatLng, Point } from './common.types';\n\n/**\n * 标记点属性\n */\nexport interface MarkerProps {\n /**\n * 坐标\n */\n position: LatLng;\n\n /**\n * 图标\n */\n icon?: ImageSourcePropType;\n\n /**\n * 标题\n */\n title?: string;\n\n /**\n * 描述\n */\n snippet?: string;\n\n /**\n * 透明度 [0, 1]\n * @platform android\n */\n opacity?: number;\n\n /**\n * 是否可拖拽\n */\n draggable?: boolean;\n\n /**\n * 是否平贴地图\n * @platform android\n */\n flat?: boolean;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 覆盖物锚点比例\n * @platform android\n */\n anchor?: Point;\n\n /**\n * 覆盖物偏移位置\n * @platform ios\n */\n centerOffset?: Point;\n\n /**\n * 自定义视图\n */\n children?: React.ReactNode;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n\n /**\n * 拖拽开始事件\n */\n onDragStart?: () => void;\n\n /**\n * 拖拽中事件\n */\n onDrag?: () => void;\n\n /**\n * 拖拽结束事件\n */\n onDragEnd?: (event: { nativeEvent: LatLng }) => void;\n}\n\n/**\n * 折线属性\n */\nexport interface PolylineProps {\n /**\n * 节点坐标数组\n */\n points: LatLng[];\n\n /**\n * 线宽\n */\n width?: number;\n\n /**\n * 线条颜色\n */\n color?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 分段颜色\n */\n colors?: ColorValue[];\n\n /**\n * 是否使用渐变色\n */\n gradient?: boolean;\n\n /**\n * 是否绘制大地线\n */\n geodesic?: boolean;\n\n /**\n * 是否绘制虚线\n */\n dotted?: boolean;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n}\n\n/**\n * 多边形属性\n */\nexport interface PolygonProps {\n /**\n * 节点坐标数组\n */\n points: LatLng[];\n\n /**\n * 边线宽度\n */\n strokeWidth?: number;\n\n /**\n * 边线颜色\n */\n strokeColor?: ColorValue;\n\n /**\n * 填充颜色\n */\n fillColor?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n}\n\n/**\n * 圆形属性\n */\nexport interface CircleProps {\n /**\n * 圆心坐标\n */\n center: LatLng;\n\n /**\n * 半径(米)\n */\n radius: number;\n\n /**\n * 边线宽度\n */\n strokeWidth?: number;\n\n /**\n * 边线颜色\n */\n strokeColor?: ColorValue;\n\n /**\n * 填充颜色\n */\n fillColor?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n}\n\n/**\n * 热力图属性\n */\nexport interface HeatMapProps {\n /**\n * 热力点数据\n */\n data: LatLng[];\n\n /**\n * 热力半径(米)\n */\n radius?: number;\n\n /**\n * 透明度 [0, 1]\n */\n opacity?: number;\n}\n\n/**\n * 海量点标记项\n */\nexport interface MultiPointItem extends LatLng {\n /**\n * 唯一标识\n */\n id?: string | number;\n\n /**\n * 自定义数据\n */\n data?: any;\n}\n\n/**\n * 海量点属性\n */\nexport interface MultiPointProps {\n /**\n * 点集合\n */\n items: MultiPointItem[];\n\n /**\n * 图标\n */\n icon?: ImageSourcePropType;\n\n /**\n * 点击事件\n */\n onPress?: (event: { nativeEvent: { index: number; item: MultiPointItem } }) => void;\n}\n\n/**\n * 聚合点参数\n */\nexport interface ClusterParams {\n /**\n * 唯一标识\n */\n id: number;\n\n /**\n * 包含的标记点数量\n */\n count: number;\n\n /**\n * 聚合点坐标\n */\n position: LatLng;\n}\n\n/**\n * 聚合点项\n */\nexport interface ClusterPoint {\n /**\n * 坐标\n */\n position: LatLng;\n\n /**\n * 自定义数据\n */\n properties?: any;\n}\n\n/**\n * 聚合图层属性\n */\nexport interface ClusterProps {\n /**\n * 聚合半径\n */\n radius?: number;\n\n /**\n * 聚合点样式\n */\n clusterStyle?: ViewStyle;\n\n /**\n * 聚合点文本样式\n */\n clusterTextStyle?: ViewStyle;\n\n /**\n * 坐标点列表\n */\n points: ClusterPoint[];\n\n /**\n * 渲染标记点\n */\n renderMarker: (item: ClusterPoint) => React.ReactNode;\n\n /**\n * 渲染聚合点\n */\n renderCluster?: (params: ClusterParams) => React.ReactNode;\n\n /**\n * 聚合点点击事件\n */\n onPress?: (params: ClusterParams) => void;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"overlays.types.js","sourceRoot":"","sources":["../../src/types/overlays.types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * 高德地图覆盖物相关类型定义\n * 基于 Expo Modules API\n */\n\nimport type { ImageSourcePropType, ViewStyle } from 'react-native';\nimport type { ColorValue, LatLng, Point } from './common.types';\n\n/**\n * 标记点属性\n */\nexport interface MarkerProps {\n /**\n * 坐标\n */\n position: LatLng;\n\n /**\n * 图标\n */\n icon?: ImageSourcePropType;\n\n /**\n * 标题\n */\n title?: string;\n\n /**\n * 描述\n */\n snippet?: string;\n\n /**\n * 透明度 [0, 1]\n * @platform android\n */\n opacity?: number;\n\n /**\n * 是否可拖拽\n */\n draggable?: boolean;\n\n /**\n * 是否平贴地图\n * @platform android\n */\n flat?: boolean;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 覆盖物锚点比例\n * @platform android\n */\n anchor?: Point;\n\n /**\n * 覆盖物偏移位置\n * @platform ios\n */\n centerOffset?: Point;\n\n /**\n * 自定义视图\n */\n children?: React.ReactNode;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n\n /**\n * 拖拽开始事件\n */\n onDragStart?: () => void;\n\n /**\n * 拖拽中事件\n */\n onDrag?: () => void;\n\n /**\n * 拖拽结束事件\n */\n onDragEnd?: (event: { nativeEvent: LatLng }) => void;\n}\n\n/**\n * 折线属性\n */\nexport interface PolylineProps {\n /**\n * 节点坐标数组\n */\n points: LatLng[];\n\n /**\n * 线宽\n */\n width?: number;\n\n /**\n * 线条颜色\n */\n color?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 分段颜色\n */\n colors?: ColorValue[];\n\n /**\n * 是否使用渐变色\n */\n gradient?: boolean;\n\n /**\n * 是否绘制大地线\n */\n geodesic?: boolean;\n\n /**\n * 是否绘制虚线\n */\n dotted?: boolean;\n\n /**\n * 纹理图片\n * 支持网络图片(http/https)、本地文件(file://)或资源名称\n */\n texture?: string;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n}\n\n/**\n * 多边形属性\n */\nexport interface PolygonProps {\n /**\n * 节点坐标数组\n */\n points: LatLng[];\n\n /**\n * 边线宽度\n */\n strokeWidth?: number;\n\n /**\n * 边线颜色\n */\n strokeColor?: ColorValue;\n\n /**\n * 填充颜色\n */\n fillColor?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n}\n\n/**\n * 圆形属性\n */\nexport interface CircleProps {\n /**\n * 圆心坐标\n */\n center: LatLng;\n\n /**\n * 半径(米)\n */\n radius: number;\n\n /**\n * 边线宽度\n */\n strokeWidth?: number;\n\n /**\n * 边线颜色\n */\n strokeColor?: ColorValue;\n\n /**\n * 填充颜色\n */\n fillColor?: ColorValue;\n\n /**\n * 层级\n */\n zIndex?: number;\n\n /**\n * 点击事件\n */\n onPress?: () => void;\n}\n\n/**\n * 热力图属性\n */\nexport interface HeatMapProps {\n /**\n * 热力点数据\n */\n data: LatLng[];\n\n /**\n * 热力半径(米)\n */\n radius?: number;\n\n /**\n * 透明度 [0, 1]\n */\n opacity?: number;\n}\n\n/**\n * 海量点标记项\n */\nexport interface MultiPointItem extends LatLng {\n /**\n * 唯一标识\n */\n id?: string | number;\n\n /**\n * 自定义数据\n */\n data?: any;\n}\n\n/**\n * 海量点属性\n */\nexport interface MultiPointProps {\n /**\n * 点集合\n */\n items: MultiPointItem[];\n\n /**\n * 图标\n */\n icon?: ImageSourcePropType;\n\n /**\n * 点击事件\n */\n onPress?: (event: { nativeEvent: { index: number; item: MultiPointItem } }) => void;\n}\n\n/**\n * 聚合点参数\n */\nexport interface ClusterParams {\n /**\n * 唯一标识\n */\n id: number;\n\n /**\n * 包含的标记点数量\n */\n count: number;\n\n /**\n * 聚合点坐标\n */\n position: LatLng;\n}\n\n/**\n * 聚合点项\n */\nexport interface ClusterPoint {\n /**\n * 坐标\n */\n position: LatLng;\n\n /**\n * 自定义数据\n */\n properties?: any;\n}\n\n/**\n * 聚合图层属性\n */\nexport interface ClusterProps {\n /**\n * 聚合半径\n */\n radius?: number;\n\n /**\n * 聚合点样式\n */\n clusterStyle?: ViewStyle;\n\n /**\n * 聚合点文本样式\n */\n clusterTextStyle?: ViewStyle;\n\n /**\n * 坐标点列表\n */\n points: ClusterPoint[];\n\n /**\n * 渲染标记点\n */\n renderMarker: (item: ClusterPoint) => React.ReactNode;\n\n /**\n * 渲染聚合点\n */\n renderCluster?: (params: ClusterParams) => React.ReactNode;\n\n /**\n * 聚合点点击事件\n */\n onPress?: (params: ClusterParams) => void;\n}\n"]}
|
package/docs/EXAMPLES.md
CHANGED
|
@@ -339,7 +339,7 @@ await mapRef.current?.removeMarker('marker1');
|
|
|
339
339
|
|
|
340
340
|
### Polyline (折线)
|
|
341
341
|
|
|
342
|
-
|
|
342
|
+
**声明式用法 - 普通折线:**
|
|
343
343
|
```tsx
|
|
344
344
|
<MapView style={{ flex: 1 }}>
|
|
345
345
|
<Polyline
|
|
@@ -348,25 +348,86 @@ await mapRef.current?.removeMarker('marker1');
|
|
|
348
348
|
{ latitude: 39.95, longitude: 116.45 },
|
|
349
349
|
{ latitude: 40.0, longitude: 116.5 },
|
|
350
350
|
]}
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
width={5}
|
|
352
|
+
color="#FFFF0000"
|
|
353
353
|
onPress={() => console.log('点击折线')}
|
|
354
354
|
/>
|
|
355
355
|
</MapView>
|
|
356
356
|
```
|
|
357
357
|
|
|
358
|
+
**声明式用法 - 纹理折线:**
|
|
359
|
+
```tsx
|
|
360
|
+
import { Image } from 'react-native';
|
|
361
|
+
|
|
362
|
+
const iconUri = Image.resolveAssetSource(require('./assets/arrow.png')).uri;
|
|
363
|
+
|
|
364
|
+
<MapView style={{ flex: 1 }}>
|
|
365
|
+
<Polyline
|
|
366
|
+
points={[
|
|
367
|
+
{ latitude: 39.9, longitude: 116.4 },
|
|
368
|
+
{ latitude: 39.95, longitude: 116.45 },
|
|
369
|
+
{ latitude: 40.0, longitude: 116.5 },
|
|
370
|
+
]}
|
|
371
|
+
width={20}
|
|
372
|
+
color="#FFFF0000"
|
|
373
|
+
texture={iconUri}
|
|
374
|
+
onPress={() => console.log('点击纹理折线')}
|
|
375
|
+
/>
|
|
376
|
+
</MapView>
|
|
377
|
+
```
|
|
378
|
+
|
|
358
379
|
**命令式用法:**
|
|
359
380
|
```tsx
|
|
381
|
+
// 普通折线
|
|
360
382
|
await mapRef.current?.addPolyline('polyline1', {
|
|
361
383
|
points: [
|
|
362
384
|
{ latitude: 39.9, longitude: 116.4 },
|
|
363
385
|
{ latitude: 40.0, longitude: 116.5 },
|
|
364
386
|
],
|
|
365
|
-
|
|
366
|
-
|
|
387
|
+
width: 5,
|
|
388
|
+
color: '#FFFF0000',
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// 纹理折线
|
|
392
|
+
await mapRef.current?.addPolyline('polyline2', {
|
|
393
|
+
points: [
|
|
394
|
+
{ latitude: 39.9, longitude: 116.4 },
|
|
395
|
+
{ latitude: 40.0, longitude: 116.5 },
|
|
396
|
+
],
|
|
397
|
+
width: 20,
|
|
398
|
+
color: '#FFFF0000',
|
|
399
|
+
texture: iconUri,
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
// 分段纹理示例(使用多个 Polyline)
|
|
403
|
+
const point1 = { latitude: 39.9, longitude: 116.4 };
|
|
404
|
+
const point2 = { latitude: 39.95, longitude: 116.45 };
|
|
405
|
+
const point3 = { latitude: 40.0, longitude: 116.5 };
|
|
406
|
+
|
|
407
|
+
// 第一段:红色箭头
|
|
408
|
+
await mapRef.current?.addPolyline('segment1', {
|
|
409
|
+
points: [point1, point2],
|
|
410
|
+
width: 20,
|
|
411
|
+
color: '#FFFF0000',
|
|
412
|
+
texture: redArrowUri,
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// 第二段:蓝色箭头
|
|
416
|
+
await mapRef.current?.addPolyline('segment2', {
|
|
417
|
+
points: [point2, point3],
|
|
418
|
+
width: 20,
|
|
419
|
+
color: '#FF0000FF',
|
|
420
|
+
texture: blueArrowUri,
|
|
367
421
|
});
|
|
368
422
|
```
|
|
369
423
|
|
|
424
|
+
> **注意**:
|
|
425
|
+
> - 颜色格式使用 ARGB(`#AARRGGBB`),例如 `#FFFF0000` 表示不透明红色
|
|
426
|
+
> - `texture` 支持网络图片(http/https)和本地文件(file://)
|
|
427
|
+
> - 纹理图片会沿着折线方向平铺显示
|
|
428
|
+
> - 建议纹理折线使用较大的 `width` 值(如 20)以获得更好的显示效果
|
|
429
|
+
> - **分段纹理限制**:单个 Polyline 只能设置一个纹理。如需不同线段使用不同纹理,请创建多个 Polyline 组件
|
|
430
|
+
|
|
370
431
|
### Polygon (多边形)
|
|
371
432
|
|
|
372
433
|
**声明式用法:**
|
|
@@ -371,6 +371,10 @@ public class ExpoGaodeMapModule: Module {
|
|
|
371
371
|
Prop("strokeColor") { (view: PolylineView, color: Int) in
|
|
372
372
|
view.setStrokeColor(color)
|
|
373
373
|
}
|
|
374
|
+
|
|
375
|
+
Prop("texture") { (view: PolylineView, url: String?) in
|
|
376
|
+
view.setTexture(url)
|
|
377
|
+
}
|
|
374
378
|
}
|
|
375
379
|
|
|
376
380
|
// Polygon - 多边形
|
|
@@ -67,26 +67,33 @@ class OverlayManager {
|
|
|
67
67
|
// MARK: - Polyline
|
|
68
68
|
|
|
69
69
|
func addPolyline(id: String, props: [String: Any]) {
|
|
70
|
+
print("📏 OverlayManager.addPolyline - id: \(id), props: \(props)")
|
|
71
|
+
|
|
70
72
|
guard let mapView = mapView,
|
|
71
|
-
let points = props["points"] as? [[String: Double]] else {
|
|
73
|
+
let points = props["points"] as? [[String: Double]] else {
|
|
74
|
+
print("❌ OverlayManager.addPolyline - mapView 或 points 为空")
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
var coordinates: [CLLocationCoordinate2D] = []
|
|
73
79
|
for point in points {
|
|
74
80
|
guard let lat = point["latitude"], let lng = point["longitude"] else { continue }
|
|
75
81
|
coordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lng))
|
|
76
82
|
}
|
|
77
|
-
guard
|
|
83
|
+
guard coordinates.count >= 2 else {
|
|
84
|
+
print("❌ OverlayManager.addPolyline - 坐标点数量不足: \(coordinates.count)")
|
|
85
|
+
return
|
|
86
|
+
}
|
|
78
87
|
|
|
79
|
-
let polyline =
|
|
80
|
-
polyline.setPolylineWithCoordinates(&coordinates, count: coordinates.count)
|
|
88
|
+
let polyline = MAPolyline(coordinates: &coordinates, count: UInt(coordinates.count))!
|
|
81
89
|
|
|
90
|
+
// 先保存样式和 overlay,再添加到地图
|
|
82
91
|
overlayStyles[id] = props
|
|
83
92
|
overlays[id] = polyline
|
|
84
|
-
mapView.add(polyline)
|
|
85
93
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
94
|
+
print("✅ OverlayManager.addPolyline - 准备添加到地图,id: \(id)")
|
|
95
|
+
mapView.add(polyline)
|
|
96
|
+
print("✅ OverlayManager.addPolyline - 已添加到地图")
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
func removePolyline(id: String) {
|
|
@@ -154,26 +161,43 @@ class OverlayManager {
|
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
return renderer
|
|
157
|
-
} else if let polyline = overlay as?
|
|
158
|
-
let renderer =
|
|
164
|
+
} else if let polyline = overlay as? MAPolyline {
|
|
165
|
+
let renderer = MAPolylineRenderer(polyline: polyline)!
|
|
159
166
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
// 设置线宽
|
|
168
|
+
if let width = style?["width"] as? Double {
|
|
169
|
+
renderer.lineWidth = CGFloat(width)
|
|
170
|
+
} else if let strokeWidth = style?["strokeWidth"] as? Double {
|
|
171
|
+
renderer.lineWidth = CGFloat(strokeWidth)
|
|
164
172
|
} else {
|
|
165
|
-
renderer
|
|
173
|
+
renderer.lineWidth = 8
|
|
166
174
|
}
|
|
167
175
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
176
|
+
// 设置线条样式
|
|
177
|
+
renderer.lineJoinType = kMALineJoinRound
|
|
178
|
+
renderer.lineCapType = kMALineCapRound
|
|
179
|
+
|
|
180
|
+
// 设置纹理或颜色
|
|
181
|
+
if let textureUrl = style?["texture"] as? String, !textureUrl.isEmpty {
|
|
182
|
+
loadPolylineTexture(url: textureUrl, renderer: renderer)
|
|
172
183
|
} else {
|
|
173
|
-
|
|
184
|
+
if let color = style?["color"] {
|
|
185
|
+
print("🎨 color 原始值: \(color), 类型: \(type(of: color))")
|
|
186
|
+
let parsedColor = ColorParser.parseColor(color)
|
|
187
|
+
print("🎨 解析后的颜色: \(String(describing: parsedColor))")
|
|
188
|
+
renderer.strokeColor = parsedColor ?? .red
|
|
189
|
+
} else if let strokeColor = style?["strokeColor"] {
|
|
190
|
+
print("🎨 strokeColor 原始值: \(strokeColor), 类型: \(type(of: strokeColor))")
|
|
191
|
+
let parsedColor = ColorParser.parseColor(strokeColor)
|
|
192
|
+
print("🎨 解析后的颜色: \(String(describing: parsedColor))")
|
|
193
|
+
renderer.strokeColor = parsedColor ?? .red
|
|
194
|
+
} else {
|
|
195
|
+
print("⚠️ 没有找到 color 或 strokeColor,使用默认红色")
|
|
196
|
+
renderer.strokeColor = .red
|
|
197
|
+
}
|
|
174
198
|
}
|
|
175
199
|
|
|
176
|
-
return renderer
|
|
200
|
+
return renderer
|
|
177
201
|
} else if let polygon = overlay as? MAPolygon {
|
|
178
202
|
guard let renderer = MAPolygonRenderer(polygon: polygon) else {
|
|
179
203
|
return nil
|
|
@@ -195,6 +219,48 @@ class OverlayManager {
|
|
|
195
219
|
return nil
|
|
196
220
|
}
|
|
197
221
|
|
|
222
|
+
private func loadPolylineTexture(url: String, renderer: MAPolylineRenderer) {
|
|
223
|
+
if url.hasPrefix("http://") || url.hasPrefix("https://") {
|
|
224
|
+
guard let imageUrl = URL(string: url) else {
|
|
225
|
+
print("❌ OverlayManager: 无效的 URL: \(url)")
|
|
226
|
+
return
|
|
227
|
+
}
|
|
228
|
+
URLSession.shared.dataTask(with: imageUrl) { [weak self] data, _, error in
|
|
229
|
+
if let error = error {
|
|
230
|
+
print("❌ OverlayManager: 下载图片失败: \(error)")
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
guard let data = data, let image = UIImage(data: data) else {
|
|
234
|
+
print("❌ OverlayManager: 无法创建图片")
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
print("✅ OverlayManager: 图片下载成功,大小: \(image.size)")
|
|
238
|
+
DispatchQueue.main.async {
|
|
239
|
+
self?.applyPolylineTexture(image: image, to: renderer)
|
|
240
|
+
}
|
|
241
|
+
}.resume()
|
|
242
|
+
} else if url.hasPrefix("file://") {
|
|
243
|
+
let path = String(url.dropFirst(7))
|
|
244
|
+
if let image = UIImage(contentsOfFile: path) {
|
|
245
|
+
print("✅ OverlayManager: 本地图片加载成功")
|
|
246
|
+
applyPolylineTexture(image: image, to: renderer)
|
|
247
|
+
} else {
|
|
248
|
+
print("❌ OverlayManager: 本地图片加载失败: \(path)")
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
if let image = UIImage(named: url) {
|
|
252
|
+
print("✅ OverlayManager: 资源图片加载成功")
|
|
253
|
+
applyPolylineTexture(image: image, to: renderer)
|
|
254
|
+
} else {
|
|
255
|
+
print("❌ OverlayManager: 资源图片加载失败: \(url)")
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
private func applyPolylineTexture(image: UIImage, to renderer: MAPolylineRenderer) {
|
|
261
|
+
renderer.strokeImage = image
|
|
262
|
+
}
|
|
263
|
+
|
|
198
264
|
func clear() {
|
|
199
265
|
guard let mapView = mapView else { return }
|
|
200
266
|
for overlay in overlays.values {
|
|
@@ -207,4 +273,4 @@ class OverlayManager {
|
|
|
207
273
|
overlayStyles.removeAll()
|
|
208
274
|
annotations.removeAll()
|
|
209
275
|
}
|
|
210
|
-
}
|
|
276
|
+
}
|
|
@@ -5,6 +5,7 @@ class PolylineView: ExpoView {
|
|
|
5
5
|
var points: [[String: Double]] = []
|
|
6
6
|
var strokeWidth: Float = 0
|
|
7
7
|
var strokeColor: Any?
|
|
8
|
+
var textureUrl: String?
|
|
8
9
|
|
|
9
10
|
private var mapView: MAMapView?
|
|
10
11
|
var polyline: MAPolyline?
|
|
@@ -36,12 +37,67 @@ class PolylineView: ExpoView {
|
|
|
36
37
|
func getRenderer() -> MAOverlayRenderer {
|
|
37
38
|
if renderer == nil, let polyline = polyline {
|
|
38
39
|
renderer = MAPolylineRenderer(polyline: polyline)
|
|
39
|
-
renderer?.strokeColor = ColorParser.parseColor(strokeColor) ?? UIColor.clear
|
|
40
40
|
renderer?.lineWidth = CGFloat(strokeWidth)
|
|
41
|
+
|
|
42
|
+
if let url = textureUrl {
|
|
43
|
+
print("🎨 PolylineView: 加载纹理 URL: \(url)")
|
|
44
|
+
loadTexture(url: url, renderer: renderer!)
|
|
45
|
+
} else {
|
|
46
|
+
renderer?.strokeColor = ColorParser.parseColor(strokeColor) ?? UIColor.clear
|
|
47
|
+
}
|
|
41
48
|
}
|
|
42
49
|
return renderer!
|
|
43
50
|
}
|
|
44
51
|
|
|
52
|
+
private func loadTexture(url: String, renderer: MAPolylineRenderer) {
|
|
53
|
+
if url.hasPrefix("http://") || url.hasPrefix("https://") {
|
|
54
|
+
guard let imageUrl = URL(string: url) else {
|
|
55
|
+
print("❌ PolylineView: 无效的 URL: \(url)")
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
URLSession.shared.dataTask(with: imageUrl) { [weak self] data, _, error in
|
|
59
|
+
if let error = error {
|
|
60
|
+
print("❌ PolylineView: 下载图片失败: \(error)")
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
guard let data = data, let image = UIImage(data: data) else {
|
|
64
|
+
print("❌ PolylineView: 无法创建图片")
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
print("✅ PolylineView: 图片下载成功,大小: \(image.size)")
|
|
68
|
+
DispatchQueue.main.async {
|
|
69
|
+
self?.applyTexture(image: image, to: renderer)
|
|
70
|
+
}
|
|
71
|
+
}.resume()
|
|
72
|
+
} else if url.hasPrefix("file://") {
|
|
73
|
+
let path = String(url.dropFirst(7))
|
|
74
|
+
if let image = UIImage(contentsOfFile: path) {
|
|
75
|
+
print("✅ PolylineView: 本地图片加载成功")
|
|
76
|
+
applyTexture(image: image, to: renderer)
|
|
77
|
+
} else {
|
|
78
|
+
print("❌ PolylineView: 本地图片加载失败: \(path)")
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
if let image = UIImage(named: url) {
|
|
82
|
+
print("✅ PolylineView: 资源图片加载成功")
|
|
83
|
+
applyTexture(image: image, to: renderer)
|
|
84
|
+
} else {
|
|
85
|
+
print("❌ PolylineView: 资源图片加载失败: \(url)")
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private func applyTexture(image: UIImage, to renderer: MAPolylineRenderer) {
|
|
91
|
+
let selector = NSSelectorFromString("loadStrokeTextureImage:")
|
|
92
|
+
if renderer.responds(to: selector) {
|
|
93
|
+
renderer.perform(selector, with: image)
|
|
94
|
+
print("✅ PolylineView: 纹理已应用")
|
|
95
|
+
mapView?.setNeedsDisplay()
|
|
96
|
+
} else {
|
|
97
|
+
print("❌ PolylineView: renderer 不支持 loadStrokeTextureImage 方法")
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
45
101
|
func setPoints(_ points: [[String: Double]]) {
|
|
46
102
|
self.points = points
|
|
47
103
|
renderer = nil
|
|
@@ -59,4 +115,10 @@ class PolylineView: ExpoView {
|
|
|
59
115
|
renderer = nil
|
|
60
116
|
updatePolyline()
|
|
61
117
|
}
|
|
118
|
+
|
|
119
|
+
func setTexture(_ url: String?) {
|
|
120
|
+
textureUrl = url
|
|
121
|
+
renderer = nil
|
|
122
|
+
updatePolyline()
|
|
123
|
+
}
|
|
62
124
|
}
|
|
@@ -73,18 +73,19 @@ class ColorParser {
|
|
|
73
73
|
hex = r + g + b + a
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
// 处理 #RRGGBBAA 格式
|
|
76
|
+
// 处理 #AARRGGBB 或 #RRGGBBAA 格式
|
|
77
77
|
if hex.count == 8 {
|
|
78
78
|
let scanner = Scanner(string: hex)
|
|
79
79
|
var hexNumber: UInt64 = 0
|
|
80
80
|
|
|
81
81
|
if scanner.scanHexInt64(&hexNumber) {
|
|
82
|
-
|
|
83
|
-
let
|
|
84
|
-
let
|
|
85
|
-
|
|
82
|
+
// 尝试 ARGB 格式(Android 风格)
|
|
83
|
+
let alphaARGB = CGFloat((hexNumber & 0xff000000) >> 24) / 255
|
|
84
|
+
let redARGB = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
|
|
85
|
+
let greenARGB = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
|
|
86
|
+
let blueARGB = CGFloat(hexNumber & 0x000000ff) / 255
|
|
86
87
|
|
|
87
|
-
return UIColor(red:
|
|
88
|
+
return UIColor(red: redARGB, green: greenARGB, blue: blueARGB, alpha: alphaARGB)
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
@@ -146,7 +147,7 @@ class ColorParser {
|
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
// UIColor
|
|
150
|
+
// UIColor 扩展,支持从数字创建(ARGB 格式)
|
|
150
151
|
extension UIColor {
|
|
151
152
|
convenience init(hex: Int) {
|
|
152
153
|
let alpha = CGFloat((hex >> 24) & 0xFF) / 255.0
|
|
@@ -155,4 +156,9 @@ extension UIColor {
|
|
|
155
156
|
let blue = CGFloat(hex & 0xFF) / 255.0
|
|
156
157
|
self.init(red: red, green: green, blue: blue, alpha: alpha)
|
|
157
158
|
}
|
|
159
|
+
|
|
160
|
+
// 别名方法,与 hex 功能相同
|
|
161
|
+
convenience init(argb: Int) {
|
|
162
|
+
self.init(hex: argb)
|
|
163
|
+
}
|
|
158
164
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
3
3
|
* @Date : 2025-11-13 15:01:30
|
|
4
4
|
* @LastEditors : 尚博信_王强 wangqiang03@sunboxsoft.com
|
|
5
|
-
* @LastEditTime : 2025-11-
|
|
5
|
+
* @LastEditTime : 2025-11-15 01:08:27
|
|
6
6
|
* @FilePath : /expo-gaode-map/src/components/overlays/Polyline.tsx
|
|
7
7
|
* @Description : 地图折线组件 - 使用命令式 API
|
|
8
8
|
*
|
|
@@ -32,30 +32,27 @@ import type { PolylineProps } from '../../types';
|
|
|
32
32
|
*/
|
|
33
33
|
export default function Polyline(props: PolylineProps) {
|
|
34
34
|
const mapRef = React.useContext(MapContext);
|
|
35
|
-
const polylineIdRef = React.useRef<string>(
|
|
36
|
-
const isInitialMount = React.useRef(true);
|
|
35
|
+
const polylineIdRef = React.useRef<string | null>(null);
|
|
37
36
|
|
|
38
37
|
// 添加折线
|
|
39
38
|
React.useEffect(() => {
|
|
40
|
-
const polylineId =
|
|
39
|
+
const polylineId = `polyline_${Date.now()}_${Math.random()}`;
|
|
40
|
+
polylineIdRef.current = polylineId;
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
// 只传递必要的属性
|
|
43
|
+
const polylineProps = {
|
|
44
|
+
points: props.points,
|
|
45
|
+
width: props.width,
|
|
46
|
+
color: props.color,
|
|
47
|
+
...(props.texture && { texture: props.texture }),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
mapRef?.current?.addPolyline?.(polylineId, polylineProps);
|
|
43
51
|
|
|
44
52
|
return () => {
|
|
45
53
|
mapRef?.current?.removePolyline?.(polylineId);
|
|
46
54
|
};
|
|
47
55
|
}, []);
|
|
48
56
|
|
|
49
|
-
// 监听 Props 变化,更新折线(跳过初始渲染)
|
|
50
|
-
React.useEffect(() => {
|
|
51
|
-
if (isInitialMount.current) {
|
|
52
|
-
isInitialMount.current = false;
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const polylineId = polylineIdRef.current;
|
|
57
|
-
mapRef?.current?.updatePolyline?.(polylineId, props);
|
|
58
|
-
}, [props.points, props.width, props.color]);
|
|
59
|
-
|
|
60
57
|
return null;
|
|
61
58
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import UIKit
|
|
2
|
-
|
|
3
|
-
extension UIColor {
|
|
4
|
-
convenience init(argb: Int) {
|
|
5
|
-
let alpha = CGFloat((argb >> 24) & 0xFF) / 255.0
|
|
6
|
-
let red = CGFloat((argb >> 16) & 0xFF) / 255.0
|
|
7
|
-
let green = CGFloat((argb >> 8) & 0xFF) / 255.0
|
|
8
|
-
let blue = CGFloat(argb & 0xFF) / 255.0
|
|
9
|
-
self.init(red: red, green: green, blue: blue, alpha: alpha)
|
|
10
|
-
}
|
|
11
|
-
}
|