Commit f33024a4cd6ca3fe50e32220f54cd6b9fa3f4619
1 parent
2e5e1e1b
封装地图路线规划
Showing
19 changed files
with
1027 additions
and
58 deletions
lib/android/src/main/java/cn/feewee/amap3d/AMap3DPackage.kt
@@ -5,6 +5,7 @@ import com.facebook.react.bridge.NativeModule | @@ -5,6 +5,7 @@ import com.facebook.react.bridge.NativeModule | ||
5 | import com.facebook.react.bridge.ReactApplicationContext | 5 | import com.facebook.react.bridge.ReactApplicationContext |
6 | import com.facebook.react.uimanager.ViewManager | 6 | import com.facebook.react.uimanager.ViewManager |
7 | import cn.feewee.amap3d.map_view.* | 7 | import cn.feewee.amap3d.map_view.* |
8 | +import cn.feewee.amap3d.map_view.route.DrivingRouteManager | ||
8 | import cn.feewee.amap3d.modules.SdkModule | 9 | import cn.feewee.amap3d.modules.SdkModule |
9 | import cn.feewee.amap3d.modules.AMapGeolocationModule | 10 | import cn.feewee.amap3d.modules.AMapGeolocationModule |
10 | 11 | ||
@@ -24,7 +25,8 @@ class AMap3DPackage : ReactPackage { | @@ -24,7 +25,8 @@ class AMap3DPackage : ReactPackage { | ||
24 | PolygonManager(), | 25 | PolygonManager(), |
25 | CircleManager(), | 26 | CircleManager(), |
26 | HeatMapManager(), | 27 | HeatMapManager(), |
27 | - MultiPointManager() | 28 | + MultiPointManager(), |
29 | + DrivingRouteManager() | ||
28 | ) | 30 | ) |
29 | } | 31 | } |
30 | } | 32 | } |
lib/android/src/main/java/cn/feewee/amap3d/Utils.kt
1 | package cn.feewee.amap3d | 1 | package cn.feewee.amap3d |
2 | 2 | ||
3 | +import android.content.Context | ||
3 | import android.content.res.Resources | 4 | import android.content.res.Resources |
4 | import android.graphics.Bitmap | 5 | import android.graphics.Bitmap |
5 | import android.graphics.Point | 6 | import android.graphics.Point |
6 | import android.location.Location | 7 | import android.location.Location |
7 | import android.view.View | 8 | import android.view.View |
9 | +import android.widget.Toast | ||
8 | import com.amap.api.maps.model.* | 10 | import com.amap.api.maps.model.* |
11 | +import com.amap.api.services.core.AMapException | ||
12 | +import com.amap.api.services.core.LatLonPoint | ||
9 | import com.facebook.drawee.backends.pipeline.Fresco | 13 | import com.facebook.drawee.backends.pipeline.Fresco |
10 | import com.facebook.imagepipeline.common.ResizeOptions | 14 | import com.facebook.imagepipeline.common.ResizeOptions |
11 | import com.facebook.imagepipeline.request.BasePostprocessor | 15 | import com.facebook.imagepipeline.request.BasePostprocessor |
@@ -15,100 +19,236 @@ import com.facebook.react.bridge.ReadableArray | @@ -15,100 +19,236 @@ import com.facebook.react.bridge.ReadableArray | ||
15 | import com.facebook.react.bridge.ReadableMap | 19 | import com.facebook.react.bridge.ReadableMap |
16 | import com.facebook.react.bridge.WritableMap | 20 | import com.facebook.react.bridge.WritableMap |
17 | import com.facebook.react.views.imagehelper.ImageSource | 21 | import com.facebook.react.views.imagehelper.ImageSource |
22 | +import kotlin.math.asin | ||
23 | +import kotlin.math.cos | ||
24 | +import kotlin.math.sin | ||
25 | +import kotlin.math.sqrt | ||
18 | 26 | ||
19 | fun Float.toPx(): Int { | 27 | fun Float.toPx(): Int { |
20 | - return (this * Resources.getSystem().displayMetrics.density).toInt() | 28 | + return (this * Resources.getSystem().displayMetrics.density).toInt() |
21 | } | 29 | } |
22 | 30 | ||
23 | fun Int.toPx(): Int { | 31 | fun Int.toPx(): Int { |
24 | - return (this * Resources.getSystem().displayMetrics.density).toInt() | 32 | + return (this * Resources.getSystem().displayMetrics.density).toInt() |
25 | } | 33 | } |
26 | 34 | ||
27 | fun ReadableMap.toPoint(): Point { | 35 | fun ReadableMap.toPoint(): Point { |
28 | - return Point(getDouble("x").toFloat().toPx(), getDouble("y").toFloat().toPx()) | 36 | + return Point(getDouble("x").toFloat().toPx(), getDouble("y").toFloat().toPx()) |
29 | } | 37 | } |
30 | 38 | ||
31 | fun ReadableMap.toLatLng(): LatLng { | 39 | fun ReadableMap.toLatLng(): LatLng { |
32 | - return LatLng(getDouble("latitude"), getDouble("longitude")) | 40 | + return LatLng(getDouble("latitude"), getDouble("longitude")) |
41 | +} | ||
42 | + | ||
43 | +fun ReadableMap.toLatLonPoint(): LatLonPoint { | ||
44 | + return LatLonPoint(getDouble("latitude"), getDouble("longitude")) | ||
33 | } | 45 | } |
34 | 46 | ||
35 | fun ReadableArray.toLatLngList(): List<LatLng> { | 47 | fun ReadableArray.toLatLngList(): List<LatLng> { |
36 | - return (0 until size()).map { | ||
37 | - // @todo 暂时兼容 0.63 | ||
38 | - @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") | ||
39 | - getMap(it)!!.toLatLng() | ||
40 | - } | 48 | + return (0 until size()).map { |
49 | + getMap(it)!!.toLatLng() | ||
50 | + } | ||
41 | } | 51 | } |
42 | 52 | ||
43 | fun LatLng.toJson(): WritableMap { | 53 | fun LatLng.toJson(): WritableMap { |
44 | - return Arguments.createMap().apply { | ||
45 | - putDouble("latitude", latitude) | ||
46 | - putDouble("longitude", longitude) | ||
47 | - } | 54 | + return Arguments.createMap().apply { |
55 | + putDouble("latitude", latitude) | ||
56 | + putDouble("longitude", longitude) | ||
57 | + } | ||
48 | } | 58 | } |
49 | 59 | ||
50 | fun Poi.toJson(): WritableMap { | 60 | fun Poi.toJson(): WritableMap { |
51 | - return Arguments.createMap().apply { | ||
52 | - putMap("position", coordinate.toJson()) | ||
53 | - putString("id", poiId) | ||
54 | - putString("name", name) | ||
55 | - } | 61 | + return Arguments.createMap().apply { |
62 | + putMap("position", coordinate.toJson()) | ||
63 | + putString("id", poiId) | ||
64 | + putString("name", name) | ||
65 | + } | ||
56 | } | 66 | } |
57 | 67 | ||
58 | fun CameraPosition.toJson(): WritableMap { | 68 | fun CameraPosition.toJson(): WritableMap { |
59 | - return Arguments.createMap().apply { | ||
60 | - putMap("target", target.toJson()) | ||
61 | - putDouble("zoom", zoom.toDouble()) | ||
62 | - putDouble("tilt", tilt.toDouble()) | ||
63 | - putDouble("bearing", bearing.toDouble()) | ||
64 | - } | 69 | + return Arguments.createMap().apply { |
70 | + putMap("target", target.toJson()) | ||
71 | + putDouble("zoom", zoom.toDouble()) | ||
72 | + putDouble("tilt", tilt.toDouble()) | ||
73 | + putDouble("bearing", bearing.toDouble()) | ||
74 | + } | ||
65 | } | 75 | } |
66 | 76 | ||
67 | fun Location.toJson(): WritableMap { | 77 | fun Location.toJson(): WritableMap { |
68 | - return Arguments.createMap().apply { | ||
69 | - putDouble("timestamp", time.toDouble()) | ||
70 | - putMap("coords", Arguments.createMap().apply { | ||
71 | - putDouble("latitude", latitude) | ||
72 | - putDouble("longitude", longitude) | ||
73 | - putDouble("latitude", latitude) | ||
74 | - putDouble("accuracy", accuracy.toDouble()) | ||
75 | - putDouble("heading", bearing.toDouble()) | ||
76 | - putDouble("speed", speed.toDouble()) | ||
77 | - }) | ||
78 | - } | 78 | + return Arguments.createMap().apply { |
79 | + putDouble("timestamp", time.toDouble()) | ||
80 | + putMap("coords", Arguments.createMap().apply { | ||
81 | + putDouble("latitude", latitude) | ||
82 | + putDouble("longitude", longitude) | ||
83 | + putDouble("latitude", latitude) | ||
84 | + putDouble("accuracy", accuracy.toDouble()) | ||
85 | + putDouble("heading", bearing.toDouble()) | ||
86 | + putDouble("speed", speed.toDouble()) | ||
87 | + }) | ||
88 | + } | ||
79 | } | 89 | } |
80 | 90 | ||
81 | fun LatLngBounds.toJson(): WritableMap { | 91 | fun LatLngBounds.toJson(): WritableMap { |
82 | - return Arguments.createMap().apply { | ||
83 | - putMap("southwest", southwest.toJson()) | ||
84 | - putMap("northeast", northeast.toJson()) | ||
85 | - } | 92 | + return Arguments.createMap().apply { |
93 | + putMap("southwest", southwest.toJson()) | ||
94 | + putMap("northeast", northeast.toJson()) | ||
95 | + } | ||
86 | } | 96 | } |
87 | 97 | ||
88 | fun ReadableMap.getFloat(key: String): Float? { | 98 | fun ReadableMap.getFloat(key: String): Float? { |
89 | - if (hasKey(key)) return getDouble(key).toFloat() | ||
90 | - return null | 99 | + if (hasKey(key)) return getDouble(key).toFloat() |
100 | + return null | ||
91 | } | 101 | } |
92 | 102 | ||
93 | fun getEventTypeConstants(vararg list: String): Map<String, Any> { | 103 | fun getEventTypeConstants(vararg list: String): Map<String, Any> { |
94 | - return list.associateWith { mapOf("phasedRegistrationNames" to mapOf("bubbled" to it)) } | 104 | + return list.associateWith { mapOf("phasedRegistrationNames" to mapOf("bubbled" to it)) } |
95 | } | 105 | } |
96 | 106 | ||
97 | fun View.fetchImage(source: ReadableMap, callback: (BitmapDescriptor) -> Unit) { | 107 | fun View.fetchImage(source: ReadableMap, callback: (BitmapDescriptor) -> Unit) { |
98 | - val uri = ImageSource(context, source.getString("uri")).uri | ||
99 | - val request = ImageRequestBuilder.newBuilderWithSource(uri).let { | ||
100 | - it.postprocessor = object : BasePostprocessor() { | ||
101 | - override fun process(bitmap: Bitmap) { | ||
102 | - callback(BitmapDescriptorFactory.fromBitmap(bitmap)) | ||
103 | - } | 108 | + val uri = ImageSource(context, source.getString("uri")).uri |
109 | + val request = ImageRequestBuilder.newBuilderWithSource(uri).let { | ||
110 | + it.postprocessor = object : BasePostprocessor() { | ||
111 | + override fun process(bitmap: Bitmap) { | ||
112 | + callback(BitmapDescriptorFactory.fromBitmap(bitmap)) | ||
113 | + } | ||
114 | + } | ||
115 | + if (source.hasKey("width") && source.hasKey("height")) { | ||
116 | + it.resizeOptions = ResizeOptions.forDimensions( | ||
117 | + source.getInt("width").toPx(), | ||
118 | + source.getInt("height").toPx() | ||
119 | + ) | ||
120 | + } | ||
121 | + it.build() | ||
122 | + } | ||
123 | + Fresco.getImagePipeline().fetchDecodedImage(request, this) | ||
124 | +} | ||
125 | + | ||
126 | +/** | ||
127 | + * 把LatLonPoint对象转化为LatLon对象 | ||
128 | + */ | ||
129 | +fun LatLonPoint.convertToLatLng(): LatLng { | ||
130 | + return LatLng(latitude, longitude) | ||
131 | +} | ||
132 | + | ||
133 | +/** | ||
134 | + * 把LatLng对象转化为LatLonPoint对象 | ||
135 | + */ | ||
136 | +fun LatLng.convertToLatLonPoint(): LatLonPoint { | ||
137 | + return LatLonPoint(latitude, longitude) | ||
138 | +} | ||
139 | + | ||
140 | +/** | ||
141 | + * 计算两点之间的距离 | ||
142 | + */ | ||
143 | +fun calculateDistance(start: LatLng, end: LatLng): Int { | ||
144 | + var x1 = start.longitude | ||
145 | + var y1 = start.latitude | ||
146 | + var x2 = end.longitude | ||
147 | + var y2 = end.latitude | ||
148 | + val NF_pi = 0.01745329251994329 // 弧度 PI/180 | ||
149 | + x1 *= NF_pi | ||
150 | + y1 *= NF_pi | ||
151 | + x2 *= NF_pi | ||
152 | + y2 *= NF_pi | ||
153 | + val sinx1 = sin(x1) | ||
154 | + val siny1 = sin(y1) | ||
155 | + val cosx1 = cos(x1) | ||
156 | + val cosy1 = cos(y1) | ||
157 | + val sinx2 = sin(x2) | ||
158 | + val siny2 = sin(y2) | ||
159 | + val cosx2 = cos(x2) | ||
160 | + val cosy2 = cos(y2) | ||
161 | + val v1 = DoubleArray(3) | ||
162 | + v1[0] = cosy1 * cosx1 - cosy2 * cosx2 | ||
163 | + v1[1] = cosy1 * sinx1 - cosy2 * sinx2 | ||
164 | + v1[2] = siny1 - siny2 | ||
165 | + val dist = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]) | ||
166 | + return (asin(dist / 2) * 12742001.5798544).toInt() | ||
167 | +} | ||
168 | + | ||
169 | +fun show(context: Context, info: String) { | ||
170 | + Toast.makeText(context.applicationContext, info, Toast.LENGTH_LONG).show() | ||
171 | +} | ||
172 | + | ||
173 | +fun show(context: Context, info: Int) { | ||
174 | + Toast.makeText(context.applicationContext, info, Toast.LENGTH_LONG).show() | ||
175 | +} | ||
176 | + | ||
177 | +fun showerror(context: Context, rCode: Int) { | ||
178 | + fun logError(info: String, errorCode: Int) { | ||
179 | + val sb = StringBuilder() | ||
180 | + for (i in 0 until 80) { | ||
181 | + sb.append("=") | ||
182 | + } | ||
183 | + print(sb.toString()) | ||
184 | + print(" 错误信息 ") | ||
185 | + print(sb.toString()) | ||
186 | + print(info) | ||
187 | + print("错误码: $errorCode") | ||
188 | + print(" ") | ||
189 | + print("如果需要更多信息,请根据错误码到以下地址进行查询") | ||
190 | + print(" http://lbs.amap.com/api/android-sdk/guide/map-tools/error-code/") | ||
191 | + print("如若仍无法解决问题,请将全部log信息提交到工单系统,多谢合作") | ||
192 | + print(sb.toString()) | ||
104 | } | 193 | } |
105 | - if (source.hasKey("width") && source.hasKey("height")) { | ||
106 | - it.resizeOptions = ResizeOptions.forDimensions( | ||
107 | - source.getInt("width").toPx(), | ||
108 | - source.getInt("height").toPx() | ||
109 | - ) | 194 | + |
195 | + try { | ||
196 | + when (rCode) { | ||
197 | + 1001 -> throw AMapException(AMapException.AMAP_SIGNATURE_ERROR) | ||
198 | + 1002 -> throw AMapException(AMapException.AMAP_INVALID_USER_KEY) | ||
199 | + 1003 -> throw AMapException(AMapException.AMAP_SERVICE_NOT_AVAILBALE) | ||
200 | + 1004 -> throw AMapException(AMapException.AMAP_DAILY_QUERY_OVER_LIMIT) | ||
201 | + 1005 -> throw AMapException(AMapException.AMAP_ACCESS_TOO_FREQUENT) | ||
202 | + 1006 -> throw AMapException(AMapException.AMAP_INVALID_USER_IP) | ||
203 | + 1007 -> throw AMapException(AMapException.AMAP_INVALID_USER_DOMAIN) | ||
204 | + 1008 -> throw AMapException(AMapException.AMAP_INVALID_USER_SCODE) | ||
205 | + 1009 -> throw AMapException(AMapException.AMAP_USERKEY_PLAT_NOMATCH) | ||
206 | + 1010 -> throw AMapException(AMapException.AMAP_IP_QUERY_OVER_LIMIT) | ||
207 | + 1011 -> throw AMapException(AMapException.AMAP_NOT_SUPPORT_HTTPS) | ||
208 | + 1012 -> throw AMapException(AMapException.AMAP_INSUFFICIENT_PRIVILEGES) | ||
209 | + 1013 -> throw AMapException(AMapException.AMAP_USER_KEY_RECYCLED) | ||
210 | + 1100 -> throw AMapException(AMapException.AMAP_ENGINE_RESPONSE_ERROR) | ||
211 | + 1101 -> throw AMapException(AMapException.AMAP_ENGINE_RESPONSE_DATA_ERROR) | ||
212 | + 1102 -> throw AMapException(AMapException.AMAP_ENGINE_CONNECT_TIMEOUT) | ||
213 | + 1103 -> throw AMapException(AMapException.AMAP_ENGINE_RETURN_TIMEOUT) | ||
214 | + 1200 -> throw AMapException(AMapException.AMAP_SERVICE_INVALID_PARAMS) | ||
215 | + 1201 -> throw AMapException(AMapException.AMAP_SERVICE_MISSING_REQUIRED_PARAMS) | ||
216 | + 1202 -> throw AMapException(AMapException.AMAP_SERVICE_ILLEGAL_REQUEST) | ||
217 | + 1203 -> throw AMapException(AMapException.AMAP_SERVICE_UNKNOWN_ERROR) | ||
218 | + 1800 -> throw AMapException(AMapException.AMAP_CLIENT_ERRORCODE_MISSSING) | ||
219 | + 1801 -> throw AMapException(AMapException.AMAP_CLIENT_ERROR_PROTOCOL) | ||
220 | + 1802 -> throw AMapException(AMapException.AMAP_CLIENT_SOCKET_TIMEOUT_EXCEPTION) | ||
221 | + 1803 -> throw AMapException(AMapException.AMAP_CLIENT_URL_EXCEPTION) | ||
222 | + 1804 -> throw AMapException(AMapException.AMAP_CLIENT_UNKNOWHOST_EXCEPTION) | ||
223 | + 1806 -> throw AMapException(AMapException.AMAP_CLIENT_NETWORK_EXCEPTION) | ||
224 | + 1900 -> throw AMapException(AMapException.AMAP_CLIENT_UNKNOWN_ERROR) | ||
225 | + 1901 -> throw AMapException(AMapException.AMAP_CLIENT_INVALID_PARAMETER) | ||
226 | + 1902 -> throw AMapException(AMapException.AMAP_CLIENT_IO_EXCEPTION) | ||
227 | + 1903 -> throw AMapException(AMapException.AMAP_CLIENT_NULLPOINT_EXCEPTION) | ||
228 | + 2000 -> throw AMapException(AMapException.AMAP_SERVICE_TABLEID_NOT_EXIST) | ||
229 | + 2001 -> throw AMapException(AMapException.AMAP_ID_NOT_EXIST) | ||
230 | + 2002 -> throw AMapException(AMapException.AMAP_SERVICE_MAINTENANCE) | ||
231 | + 2003 -> throw AMapException(AMapException.AMAP_ENGINE_TABLEID_NOT_EXIST) | ||
232 | + 2100 -> throw AMapException(AMapException.AMAP_NEARBY_INVALID_USERID) | ||
233 | + 2101 -> throw AMapException(AMapException.AMAP_NEARBY_KEY_NOT_BIND) | ||
234 | + 2200 -> throw AMapException(AMapException.AMAP_CLIENT_UPLOADAUTO_STARTED_ERROR) | ||
235 | + 2201 -> throw AMapException(AMapException.AMAP_CLIENT_USERID_ILLEGAL) | ||
236 | + 2202 -> throw AMapException(AMapException.AMAP_CLIENT_NEARBY_NULL_RESULT) | ||
237 | + 2203 -> throw AMapException(AMapException.AMAP_CLIENT_UPLOAD_TOO_FREQUENT) | ||
238 | + 2204 -> throw AMapException(AMapException.AMAP_CLIENT_UPLOAD_LOCATION_ERROR) | ||
239 | + 3000 -> throw AMapException(AMapException.AMAP_ROUTE_OUT_OF_SERVICE) | ||
240 | + 3001 -> throw AMapException(AMapException.AMAP_ROUTE_NO_ROADS_NEARBY) | ||
241 | + 3002 -> throw AMapException(AMapException.AMAP_ROUTE_FAIL) | ||
242 | + 3003 -> throw AMapException(AMapException.AMAP_OVER_DIRECTION_RANGE) | ||
243 | + 4000 -> throw AMapException(AMapException.AMAP_SHARE_LICENSE_IS_EXPIRED) | ||
244 | + 4001 -> throw AMapException(AMapException.AMAP_SHARE_FAILURE) | ||
245 | + else -> { | ||
246 | + Toast.makeText(context, "查询失败:$rCode", Toast.LENGTH_LONG).show() | ||
247 | + logError("查询失败", rCode) | ||
248 | + } | ||
249 | + } | ||
250 | + } catch (e: Exception) { | ||
251 | + Toast.makeText(context.applicationContext, e.message, Toast.LENGTH_LONG).show() | ||
252 | + e.message?.let { logError(it, rCode) } | ||
110 | } | 253 | } |
111 | - it.build() | ||
112 | - } | ||
113 | - Fresco.getImagePipeline().fetchDecodedImage(request, this) | ||
114 | } | 254 | } |
115 | \ No newline at end of file | 255 | \ No newline at end of file |
lib/android/src/main/java/cn/feewee/amap3d/map_view/route/DrivingRoute.kt
0 → 100644
1 | +package cn.feewee.amap3d.map_view.route | ||
2 | + | ||
3 | +import android.content.Context | ||
4 | +import android.graphics.Color | ||
5 | +import android.widget.Toast | ||
6 | +import cn.feewee.amap3d.* | ||
7 | +import cn.feewee.amap3d.R | ||
8 | +import com.amap.api.maps.AMap | ||
9 | +import com.amap.api.maps.model.* | ||
10 | +import com.amap.api.services.core.AMapException | ||
11 | +import com.amap.api.services.route.* | ||
12 | +import com.facebook.react.bridge.ReadableArray | ||
13 | + | ||
14 | +class DrivingRoute(context: Context) : RouteOverlay(context) { | ||
15 | + private var drivePath: DrivePathV2? = null | ||
16 | + private var throughPointList: List<LatLng> = emptyList() | ||
17 | + private var isColorfulline = true | ||
18 | + private var throughPointMarkerList: ArrayList<Marker> = ArrayList() | ||
19 | + private var throughPointMarkerVisible = true | ||
20 | + private var mPolylineOptions: PolylineOptions? = null | ||
21 | + private var mPolylineOptionsColor: PolylineOptions? = null | ||
22 | + | ||
23 | + init { | ||
24 | + try { | ||
25 | + mRouteSearch = RouteSearchV2(context) | ||
26 | + } catch (e: AMapException) { | ||
27 | + e.printStackTrace() | ||
28 | + } | ||
29 | + } | ||
30 | + | ||
31 | + fun setThroughPointList(throughPoints: List<LatLng>) { | ||
32 | + if (throughPoints.size > 6) { | ||
33 | + throughPointList = throughPoints.take(6) | ||
34 | + return | ||
35 | + } | ||
36 | + throughPointList = throughPoints | ||
37 | + } | ||
38 | + | ||
39 | + fun setIsColorfulline(iscolorfulline: Boolean) { | ||
40 | + isColorfulline = iscolorfulline | ||
41 | + } | ||
42 | + | ||
43 | + fun setThroughPointMarkerVisible(visible: Boolean) { | ||
44 | + try { | ||
45 | + throughPointMarkerVisible = visible | ||
46 | + if (this.throughPointMarkerList.isNotEmpty()) { | ||
47 | + for (i in this.throughPointMarkerList.indices) { | ||
48 | + this.throughPointMarkerList[i].isVisible = visible | ||
49 | + } | ||
50 | + } | ||
51 | + } catch (e: Throwable) { | ||
52 | + e.printStackTrace() | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + override fun add(map: AMap) { | ||
57 | + this.map = map | ||
58 | + searchRouteResult() | ||
59 | + } | ||
60 | + | ||
61 | + override fun remove() { | ||
62 | + removeMarkerFromMap() | ||
63 | + removeLineFromMap() | ||
64 | + try { | ||
65 | + if (throughPointMarkerList.size > 0) { | ||
66 | + for (i in throughPointMarkerList.indices) { | ||
67 | + throughPointMarkerList[i].remove() | ||
68 | + } | ||
69 | + throughPointMarkerList.clear() | ||
70 | + } | ||
71 | + } catch (e: Throwable) { | ||
72 | + e.printStackTrace() | ||
73 | + } | ||
74 | + } | ||
75 | + | ||
76 | + private fun addToMap() { | ||
77 | + initPolylineOptions() | ||
78 | + if (getRouteWidth() == 0f || drivePath == null) { | ||
79 | + return | ||
80 | + } | ||
81 | + | ||
82 | + val mLatLngsOfPath = ArrayList<LatLng>() | ||
83 | + val tmcs = ArrayList<TMC>() | ||
84 | + val drivePaths = drivePath?.steps | ||
85 | + | ||
86 | + for (step in drivePaths!!) { | ||
87 | + val latlonPoints = step.polyline | ||
88 | + val tmclist = step.tmCs | ||
89 | + tmcs.addAll(tmclist) | ||
90 | + addDrivingStationMarkers(step, latlonPoints[0].convertToLatLng()) | ||
91 | + for (latlonpoint in latlonPoints) { | ||
92 | + mPolylineOptions?.add(latlonpoint.convertToLatLng()) | ||
93 | + mLatLngsOfPath.add(latlonpoint.convertToLatLng()) | ||
94 | + } | ||
95 | + } | ||
96 | + addStartAndEndMarker() | ||
97 | + addThroughPointMarker() | ||
98 | + if (isColorfulline && tmcs.size > 0) { | ||
99 | + colorWayUpdate(tmcs) | ||
100 | + addPolyLine(mPolylineOptionsColor) | ||
101 | + } else { | ||
102 | + addPolyLine(mPolylineOptions) | ||
103 | + } | ||
104 | + } | ||
105 | + | ||
106 | + /** | ||
107 | + * 初始化线段属性 | ||
108 | + */ | ||
109 | + private fun initPolylineOptions() { | ||
110 | + mPolylineOptions = PolylineOptions() | ||
111 | + .color(getRoadColor()) | ||
112 | + .setCustomTexture(getRoadLine()) | ||
113 | + .width(getRouteWidth()) | ||
114 | + } | ||
115 | + | ||
116 | + /** | ||
117 | + * 根据不同的路段拥堵情况展示不同的颜色 | ||
118 | + * | ||
119 | + * @param tmcSection | ||
120 | + */ | ||
121 | + private fun colorWayUpdate(tmcSection: List<TMC>) { | ||
122 | + var segmentTrafficStatus: TMC | ||
123 | + mPolylineOptionsColor = PolylineOptions().width(getRouteWidth()) | ||
124 | + mPolylineOptionsColor?.add(tmcSection[0].polyline[0].convertToLatLng()) | ||
125 | + | ||
126 | + val colorList: MutableList<Int> = ArrayList() | ||
127 | + colorList.add(getRoadColor()) | ||
128 | + for (i in tmcSection.indices) { | ||
129 | + segmentTrafficStatus = tmcSection[i] | ||
130 | + val color: Int = getColor(segmentTrafficStatus.status) | ||
131 | + val mployline = segmentTrafficStatus.polyline | ||
132 | + for (j in 1 until mployline.size) { | ||
133 | + mPolylineOptionsColor?.add(mployline[j].convertToLatLng()) | ||
134 | + colorList.add(color) | ||
135 | + } | ||
136 | + } | ||
137 | + colorList.add(getRoadColor()) | ||
138 | + mPolylineOptionsColor?.colorValues(colorList) | ||
139 | + } | ||
140 | + | ||
141 | + private fun getColor(status: String): Int { | ||
142 | + return when (status) { | ||
143 | + "畅通" -> { | ||
144 | + Color.GREEN | ||
145 | + } | ||
146 | + "缓行" -> { | ||
147 | + Color.YELLOW | ||
148 | + } | ||
149 | + "拥堵" -> { | ||
150 | + Color.RED | ||
151 | + } | ||
152 | + "严重拥堵" -> { | ||
153 | + Color.parseColor("#990033") | ||
154 | + } | ||
155 | + else -> { | ||
156 | + Color.parseColor("#537edc") | ||
157 | + } | ||
158 | + } | ||
159 | + } | ||
160 | + | ||
161 | + /** | ||
162 | + * @param driveStep | ||
163 | + * @param latLng | ||
164 | + */ | ||
165 | + private fun addDrivingStationMarkers(driveStep: DriveStepV2, latLng: LatLng) { | ||
166 | + addStationMarker( | ||
167 | + MarkerOptions() | ||
168 | + .position(latLng) | ||
169 | + .title("\u65B9\u5411:" + driveStep.instruction + "\n\u9053\u8DEF:" + driveStep.road) | ||
170 | + .snippet(driveStep.instruction).visible(nodeIconVisible) | ||
171 | + .anchor(0.5f, 0.5f).icon(getDriveBit()) | ||
172 | + ) | ||
173 | + } | ||
174 | + | ||
175 | + /** | ||
176 | + * 添加途经点marker | ||
177 | + */ | ||
178 | + private fun addThroughPointMarker() { | ||
179 | + if (throughPointList.isNotEmpty()) { | ||
180 | + for (i in throughPointList.indices) { | ||
181 | + val latLonPoint = throughPointList[i] | ||
182 | + throughPointMarkerList.add( | ||
183 | + map.addMarker( | ||
184 | + MarkerOptions() | ||
185 | + .position(latLonPoint) | ||
186 | + .visible(throughPointMarkerVisible) | ||
187 | + .icon(getThroughBit()) | ||
188 | + .title("\u9014\u7ECF\u70B9") | ||
189 | + ) | ||
190 | + ) | ||
191 | + } | ||
192 | + } | ||
193 | + } | ||
194 | + | ||
195 | + override fun searchRouteResult() { | ||
196 | + if (mRouteSearch == null) { | ||
197 | + return | ||
198 | + } | ||
199 | + val fromAndTo = createFromAndTo() ?: return | ||
200 | + try { | ||
201 | + showProgressDialog() | ||
202 | + val driveRouteResult = mRouteSearch!!.calculateDriveRoute( | ||
203 | + RouteSearchV2.DriveRouteQuery( | ||
204 | + fromAndTo, | ||
205 | + RouteSearchV2.DrivingStrategy.DEFAULT, | ||
206 | + throughPointList.map { r -> r.convertToLatLonPoint() }, | ||
207 | + null, | ||
208 | + null | ||
209 | + ) | ||
210 | + ) | ||
211 | + onDriveRouteSearched(driveRouteResult) | ||
212 | + } catch (e: AMapException) { | ||
213 | + dissmissProgressDialog() | ||
214 | + showerror(context, e.errorCode) | ||
215 | + } | ||
216 | + | ||
217 | + } | ||
218 | + | ||
219 | + private fun onDriveRouteSearched(result: DriveRouteResultV2) { | ||
220 | + dissmissProgressDialog() | ||
221 | + map.clear() | ||
222 | + if (result.paths != null) { | ||
223 | + if (result.paths.size > 0) { | ||
224 | + drivePath = result.paths[0] ?: return | ||
225 | + remove() | ||
226 | + addToMap() | ||
227 | + zoomToSpan() | ||
228 | + | ||
229 | + } else if (result.paths == null) { | ||
230 | + show(context, R.string.no_result) | ||
231 | + } | ||
232 | + } else { | ||
233 | + show(context, R.string.no_result) | ||
234 | + } | ||
235 | + } | ||
236 | + | ||
237 | + | ||
238 | + fun searchRoute(args: ReadableArray?) { | ||
239 | + val start = args?.getMap(0)?.toLatLonPoint() | ||
240 | + val end = args?.getMap(1)?.toLatLonPoint() | ||
241 | + val through = args?.getArray(2)?.toLatLngList() | ||
242 | + if (start == null) { | ||
243 | + Toast.makeText(context, "起点不能为空", Toast.LENGTH_LONG).show() | ||
244 | + return | ||
245 | + } | ||
246 | + if (end == null) { | ||
247 | + Toast.makeText(context, "终点不能为空", Toast.LENGTH_LONG).show() | ||
248 | + return | ||
249 | + } | ||
250 | + setStartPoint(start) | ||
251 | + setEndPoint(end) | ||
252 | + if (through?.isNotEmpty() == true) { | ||
253 | + setThroughPointList(through) | ||
254 | + } | ||
255 | + searchRouteResult() | ||
256 | + } | ||
257 | + | ||
258 | +} | ||
0 | \ No newline at end of file | 259 | \ No newline at end of file |
lib/android/src/main/java/cn/feewee/amap3d/map_view/route/DrivingRouteManager.kt
0 → 100644
1 | +package cn.feewee.amap3d.map_view.route | ||
2 | + | ||
3 | +import cn.feewee.amap3d.toLatLngList | ||
4 | +import cn.feewee.amap3d.toLatLonPoint | ||
5 | +import cn.feewee.amap3d.toPx | ||
6 | +import com.facebook.react.bridge.ReadableArray | ||
7 | +import com.facebook.react.bridge.ReadableMap | ||
8 | +import com.facebook.react.uimanager.SimpleViewManager | ||
9 | +import com.facebook.react.uimanager.ThemedReactContext | ||
10 | +import com.facebook.react.uimanager.annotations.ReactProp | ||
11 | + | ||
12 | +@Suppress("unused") | ||
13 | +class DrivingRouteManager : SimpleViewManager<DrivingRoute>() { | ||
14 | + override fun getName(): String { | ||
15 | + return "DrivingRoute" | ||
16 | + } | ||
17 | + | ||
18 | + override fun createViewInstance(reactContext: ThemedReactContext): DrivingRoute { | ||
19 | + return DrivingRoute(reactContext) | ||
20 | + } | ||
21 | + | ||
22 | + companion object { | ||
23 | + const val searchRoute = 1 | ||
24 | + } | ||
25 | + | ||
26 | + override fun getCommandsMap(): Map<String, Int> { | ||
27 | + return mapOf("searchRoute" to searchRoute) | ||
28 | + } | ||
29 | + | ||
30 | + override fun receiveCommand(route: DrivingRoute, commandId: Int, args: ReadableArray?) { | ||
31 | + when (commandId) { | ||
32 | + searchRoute -> route.searchRoute(args) | ||
33 | + } | ||
34 | + } | ||
35 | + | ||
36 | + @ReactProp(name = "startPoint") | ||
37 | + fun setStart(route: DrivingRoute, startPoint: ReadableMap) { | ||
38 | + route.setStartPoint(startPoint.toLatLonPoint()) | ||
39 | + } | ||
40 | + | ||
41 | + @ReactProp(name = "endPoint") | ||
42 | + fun setEnd(route: DrivingRoute, endPoint: ReadableMap) { | ||
43 | + route.setEndPoint(endPoint.toLatLonPoint()) | ||
44 | + } | ||
45 | + | ||
46 | + @ReactProp(name = "width") | ||
47 | + fun setWidth(route: DrivingRoute, width: Float) { | ||
48 | + route.setRouteWidth(width.toPx().toFloat()) | ||
49 | + } | ||
50 | + | ||
51 | + @ReactProp(name = "lineColor", customType = "Color") | ||
52 | + fun setColor(route: DrivingRoute, lineColor: Int) { | ||
53 | + route.setRoadColor(lineColor) | ||
54 | + } | ||
55 | + | ||
56 | + @ReactProp(name = "throughPointVisible") | ||
57 | + fun setThroughPointVisible(route: DrivingRoute, throughPointVisible: Boolean) { | ||
58 | + route.setThroughPointMarkerVisible(throughPointVisible) | ||
59 | + } | ||
60 | + | ||
61 | + @ReactProp(name = "colorFulLine") | ||
62 | + fun setColorFulLine(route: DrivingRoute, colorFulLine: Boolean) { | ||
63 | + route.setIsColorfulline(colorFulLine) | ||
64 | + } | ||
65 | + | ||
66 | + @ReactProp(name = "throughPointList") | ||
67 | + fun setThroughPointList(route: DrivingRoute, position: ReadableArray) { | ||
68 | + route.setThroughPointList(position.toLatLngList()) | ||
69 | + } | ||
70 | + | ||
71 | + @ReactProp(name = "driveIcon") | ||
72 | + fun setDriveIcon(route: DrivingRoute, driveIcon: ReadableMap?) { | ||
73 | + driveIcon?.let { route.setDriveBit(it) } | ||
74 | + } | ||
75 | + | ||
76 | + @ReactProp(name = "startIcon") | ||
77 | + fun setStartIcon(route: DrivingRoute, startIcon: ReadableMap?) { | ||
78 | + startIcon?.let { route.setStartBit(it) } | ||
79 | + } | ||
80 | + | ||
81 | + @ReactProp(name = "endIcon") | ||
82 | + fun setEndIcon(route: DrivingRoute, endIcon: ReadableMap?) { | ||
83 | + endIcon?.let { route.setEndBit(it) } | ||
84 | + } | ||
85 | + | ||
86 | + @ReactProp(name = "throughPointIcon") | ||
87 | + fun setThroughPointIcon(route: DrivingRoute, throughPoint: ReadableMap?) { | ||
88 | + throughPoint?.let { route.setThroughPointBitDes(it) } | ||
89 | + } | ||
90 | + | ||
91 | + @ReactProp(name = "roadLine") | ||
92 | + fun setRoadLine(route: DrivingRoute, roadLine: ReadableMap?) { | ||
93 | + roadLine?.let { route.setRoadLine(it) } | ||
94 | + } | ||
95 | +} | ||
0 | \ No newline at end of file | 96 | \ No newline at end of file |
lib/android/src/main/java/cn/feewee/amap3d/map_view/route/RouteOverlay.kt
0 → 100644
1 | +package cn.feewee.amap3d.map_view.route | ||
2 | + | ||
3 | +import android.annotation.SuppressLint | ||
4 | +import android.app.AlertDialog | ||
5 | +import android.content.Context | ||
6 | +import android.graphics.Color | ||
7 | +import android.view.LayoutInflater | ||
8 | +import android.view.View | ||
9 | +import android.widget.TextView | ||
10 | +import cn.feewee.amap3d.* | ||
11 | +import cn.feewee.amap3d.map_view.Overlay | ||
12 | +import com.amap.api.maps.AMap | ||
13 | +import com.amap.api.maps.CameraUpdateFactory | ||
14 | +import com.amap.api.maps.model.* | ||
15 | +import com.amap.api.services.core.LatLonPoint | ||
16 | +import com.amap.api.services.route.* | ||
17 | +import com.facebook.react.bridge.ReadableMap | ||
18 | +import com.facebook.react.views.view.ReactViewGroup | ||
19 | + | ||
20 | +abstract class RouteOverlay(context: Context) : ReactViewGroup(context), Overlay { | ||
21 | + lateinit var map: AMap | ||
22 | + private var stationMarkers: MutableList<Marker> = ArrayList() | ||
23 | + private var allPolyLines: MutableList<Polyline> = ArrayList() | ||
24 | + private var startPoint: LatLng? = null | ||
25 | + private var endPoint: LatLng? = null | ||
26 | + private var startMarker: Marker? = null | ||
27 | + private var endMarker: Marker? = null | ||
28 | + private var roadColor: Int = Color.parseColor("#537edc") | ||
29 | + private var progDialog: AlertDialog? = null | ||
30 | + | ||
31 | + protected var mRouteSearch: RouteSearchV2? = null | ||
32 | + | ||
33 | + abstract fun searchRouteResult() | ||
34 | + | ||
35 | + /** | ||
36 | + * 路段节点图标控制显示接口。 | ||
37 | + * @param visible true为显示节点图标,false为不显示。 | ||
38 | + * @since V2.3.1 | ||
39 | + */ | ||
40 | + protected var nodeIconVisible = true | ||
41 | + fun setNodeIconVisibility(visible: Boolean) { | ||
42 | + try { | ||
43 | + nodeIconVisible = visible | ||
44 | + if (stationMarkers.size > 0) { | ||
45 | + for (i in stationMarkers.indices) { | ||
46 | + stationMarkers[i].isVisible = visible | ||
47 | + } | ||
48 | + } | ||
49 | + } catch (e: Throwable) { | ||
50 | + e.printStackTrace() | ||
51 | + } | ||
52 | + } | ||
53 | + | ||
54 | + | ||
55 | + fun setStartPoint(start: LatLonPoint?) { | ||
56 | + start?.let { | ||
57 | + startPoint = start.convertToLatLng() | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
61 | + fun getStartPoint(): LatLng? { | ||
62 | + return startPoint | ||
63 | + } | ||
64 | + | ||
65 | + fun setEndPoint(end: LatLonPoint?) { | ||
66 | + end?.let { | ||
67 | + endPoint = end.convertToLatLng() | ||
68 | + } | ||
69 | + } | ||
70 | + | ||
71 | + fun getEndPoint(): LatLng? { | ||
72 | + return endPoint | ||
73 | + } | ||
74 | + | ||
75 | + /** | ||
76 | + * 起点Marker图标。 | ||
77 | + */ | ||
78 | + private var startBit: BitmapDescriptor? = null | ||
79 | + | ||
80 | + fun setStartBit(source: ReadableMap) { | ||
81 | + fetchImage(source) { | ||
82 | + startBit = it | ||
83 | + } | ||
84 | + } | ||
85 | + | ||
86 | + fun getStartBit(): BitmapDescriptor { | ||
87 | + return startBit ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_amap_start) | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
91 | + * 终点Marker图标。 | ||
92 | + */ | ||
93 | + private var endBit: BitmapDescriptor? = null | ||
94 | + | ||
95 | + fun setEndBit(source: ReadableMap) { | ||
96 | + fetchImage(source) { | ||
97 | + endBit = it | ||
98 | + } | ||
99 | + } | ||
100 | + | ||
101 | + fun getEndBit(): BitmapDescriptor { | ||
102 | + return endBit ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_amap_end) | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
106 | + * 途经点图标 | ||
107 | + */ | ||
108 | + private var throughBit: BitmapDescriptor? = null | ||
109 | + | ||
110 | + fun setThroughBit(source: ReadableMap) { | ||
111 | + fetchImage(source) { | ||
112 | + throughBit = it | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
116 | + fun getThroughBit(): BitmapDescriptor { | ||
117 | + return throughBit ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_amap_through) | ||
118 | + } | ||
119 | + | ||
120 | + /** | ||
121 | + * 驾车Marker图标 | ||
122 | + */ | ||
123 | + private var driveBit: BitmapDescriptor? = null | ||
124 | + | ||
125 | + fun setDriveBit(source: ReadableMap) { | ||
126 | + fetchImage(source) { | ||
127 | + driveBit = it | ||
128 | + } | ||
129 | + } | ||
130 | + | ||
131 | + fun getDriveBit(): BitmapDescriptor { | ||
132 | + return driveBit ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_amap_car) | ||
133 | + } | ||
134 | + | ||
135 | + /** | ||
136 | + * 骑行Marker图标 | ||
137 | + */ | ||
138 | + private var rideBit: BitmapDescriptor? = null | ||
139 | + | ||
140 | + fun setRideBit(source: ReadableMap) { | ||
141 | + fetchImage(source) { | ||
142 | + rideBit = it | ||
143 | + } | ||
144 | + } | ||
145 | + | ||
146 | + fun getRideBit(): BitmapDescriptor { | ||
147 | + return rideBit ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_amap_ride) | ||
148 | + } | ||
149 | + | ||
150 | + /** | ||
151 | + * 公交Marker图标 | ||
152 | + */ | ||
153 | + private var busBit: BitmapDescriptor? = null | ||
154 | + | ||
155 | + fun setBusBit(source: ReadableMap) { | ||
156 | + fetchImage(source) { | ||
157 | + busBit = it | ||
158 | + } | ||
159 | + } | ||
160 | + | ||
161 | + fun getBusBit(): BitmapDescriptor { | ||
162 | + return busBit ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_amap_bus) | ||
163 | + } | ||
164 | + | ||
165 | + /** | ||
166 | + * 步行Marker图标 | ||
167 | + */ | ||
168 | + private var walkBit: BitmapDescriptor? = null | ||
169 | + | ||
170 | + fun setWalkBit(source: ReadableMap) { | ||
171 | + fetchImage(source) { | ||
172 | + walkBit = it | ||
173 | + } | ||
174 | + } | ||
175 | + | ||
176 | + fun getWalkBit(): BitmapDescriptor { | ||
177 | + return walkBit ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_amap_man) | ||
178 | + } | ||
179 | + | ||
180 | + private var roadLine: BitmapDescriptor? = null | ||
181 | + | ||
182 | + fun setRoadLine(source: ReadableMap) { | ||
183 | + fetchImage(source) { | ||
184 | + roadLine = it | ||
185 | + } | ||
186 | + } | ||
187 | + | ||
188 | + fun getRoadLine(): BitmapDescriptor { | ||
189 | + return roadLine ?: BitmapDescriptorFactory.fromResource(R.drawable.cqfw_custtexture) | ||
190 | + } | ||
191 | + | ||
192 | + private var routeWidth: Float = 18F | ||
193 | + | ||
194 | + /** | ||
195 | + * 自定义路线宽度 | ||
196 | + * @param width | ||
197 | + */ | ||
198 | + | ||
199 | + fun setRouteWidth(width: Float?) { | ||
200 | + width?.let { | ||
201 | + routeWidth = width | ||
202 | + } | ||
203 | + } | ||
204 | + | ||
205 | + fun getRouteWidth(): Float { | ||
206 | + return routeWidth | ||
207 | + } | ||
208 | + | ||
209 | + /** | ||
210 | + * 自定义路线颜色 | ||
211 | + * | ||
212 | + * @param color | ||
213 | + */ | ||
214 | + fun setRoadColor(color: Int) { | ||
215 | + roadColor = color | ||
216 | + } | ||
217 | + | ||
218 | + fun getRoadColor(): Int { | ||
219 | + return roadColor | ||
220 | + } | ||
221 | + | ||
222 | + protected fun addStartAndEndMarker() { | ||
223 | + removeMarkerFromMap() | ||
224 | + startMarker = map.addMarker( | ||
225 | + MarkerOptions() | ||
226 | + .position(startPoint) | ||
227 | + .icon(getStartBit()) | ||
228 | + .title("\u8D77\u70B9") | ||
229 | + ) | ||
230 | + endMarker = map.addMarker( | ||
231 | + MarkerOptions() | ||
232 | + .position(endPoint) | ||
233 | + .icon(getEndBit()) | ||
234 | + .title("\u7EC8\u70B9") | ||
235 | + ) | ||
236 | + } | ||
237 | + | ||
238 | + protected fun addStationMarker(options: MarkerOptions?) { | ||
239 | + if (options == null) { | ||
240 | + return | ||
241 | + } | ||
242 | + val marker = map.addMarker(options) | ||
243 | + if (marker != null) { | ||
244 | + stationMarkers.add(marker) | ||
245 | + } | ||
246 | + } | ||
247 | + | ||
248 | + protected fun addPolyLine(options: PolylineOptions?) { | ||
249 | + if (options == null) { | ||
250 | + return | ||
251 | + } | ||
252 | + val polyline = map.addPolyline(options) | ||
253 | + if (polyline != null) { | ||
254 | + allPolyLines.add(polyline) | ||
255 | + } | ||
256 | + } | ||
257 | + | ||
258 | + /** | ||
259 | + * 移动镜头到当前的视角。 | ||
260 | + * @since V2.1.0 | ||
261 | + */ | ||
262 | + protected fun zoomToSpan() { | ||
263 | + if (startPoint != null) { | ||
264 | + try { | ||
265 | + val bounds = getLatLngBounds() | ||
266 | + map.animateCamera( | ||
267 | + CameraUpdateFactory | ||
268 | + .newLatLngBounds(bounds, 100) | ||
269 | + ) | ||
270 | + } catch (e: Throwable) { | ||
271 | + e.printStackTrace() | ||
272 | + } | ||
273 | + } | ||
274 | + } | ||
275 | + | ||
276 | + protected open fun getLatLngBounds(): LatLngBounds { | ||
277 | + return LatLngBounds.builder() | ||
278 | + .include(LatLng(startPoint!!.latitude, startPoint!!.longitude)) | ||
279 | + .include(LatLng(endPoint!!.latitude, endPoint!!.longitude)) | ||
280 | + .build() | ||
281 | + } | ||
282 | + | ||
283 | + /** | ||
284 | + * 移除所有的Marker。 | ||
285 | + */ | ||
286 | + protected fun removeMarkerFromMap() { | ||
287 | + startMarker?.destroy() | ||
288 | + endMarker?.destroy() | ||
289 | + | ||
290 | + } | ||
291 | + | ||
292 | + /** | ||
293 | + * 移除所有的路线。 | ||
294 | + */ | ||
295 | + protected fun removeLineFromMap() { | ||
296 | + for (marker in stationMarkers) { | ||
297 | + marker.destroy() | ||
298 | + } | ||
299 | + for (line in allPolyLines) { | ||
300 | + line.remove() | ||
301 | + } | ||
302 | + } | ||
303 | + | ||
304 | + /** | ||
305 | + * 开始搜索路径规划方案 | ||
306 | + */ | ||
307 | + protected fun createFromAndTo(): RouteSearchV2.FromAndTo? { | ||
308 | + if (startPoint == null) { | ||
309 | + show(context, "起点未设置") | ||
310 | + return null | ||
311 | + } | ||
312 | + if (endPoint == null) { | ||
313 | + show(context, "终点未设置") | ||
314 | + return null | ||
315 | + } | ||
316 | + return RouteSearchV2.FromAndTo( | ||
317 | + startPoint!!.convertToLatLonPoint(), | ||
318 | + endPoint!!.convertToLatLonPoint() | ||
319 | + ) | ||
320 | + } | ||
321 | + | ||
322 | + /** | ||
323 | + * 隐藏进度框 | ||
324 | + */ | ||
325 | + protected fun dissmissProgressDialog() { | ||
326 | + progDialog?.dismiss() | ||
327 | + } | ||
328 | + | ||
329 | + /** | ||
330 | + * 显示进度框 | ||
331 | + */ | ||
332 | + protected fun showProgressDialog() { | ||
333 | + if (progDialog == null) { | ||
334 | + progressBarCircleDialog() | ||
335 | + } | ||
336 | + progDialog?.setCanceledOnTouchOutside(false); | ||
337 | + progDialog?.setCancelable(false); | ||
338 | + progDialog?.show(); | ||
339 | + } | ||
340 | + | ||
341 | + | ||
342 | + private fun progressBarCircleDialog() { | ||
343 | + val builder = AlertDialog.Builder( | ||
344 | + context, | ||
345 | + AlertDialog.THEME_HOLO_LIGHT | ||
346 | + ) | ||
347 | + val inflater = LayoutInflater.from(context); | ||
348 | + @SuppressLint("InflateParams") | ||
349 | + val view: View = inflater.inflate(R.layout.dialog_progressbar_circle, null); | ||
350 | + val tv: TextView = view.findViewById(R.id.tv); | ||
351 | + tv.text = "正在搜索..."; | ||
352 | + builder.setView(view); | ||
353 | + progDialog = builder.create(); | ||
354 | + } | ||
355 | +} | ||
0 | \ No newline at end of file | 356 | \ No newline at end of file |
lib/android/src/main/res/drawable-hdpi/cqfw_amap_bus.png
0 → 100644
1.05 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_car.png
0 → 100644
1.14 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_end.png
0 → 100644
10.9 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_man.png
0 → 100644
1.26 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_ride.png
0 → 100644
1.3 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_start.png
0 → 100644
10.2 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_through.png
0 → 100644
4.4 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_train.png
0 → 100644
1.08 KB
lib/android/src/main/res/drawable-hdpi/cqfw_amap_truck.png
0 → 100644
1.14 KB
lib/android/src/main/res/drawable-hdpi/cqfw_custtexture.png
0 → 100644
1.46 KB
lib/android/src/main/res/layout/dialog_progressbar_circle.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | ||
2 | +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | + android:layout_width="match_parent" | ||
4 | + android:layout_height="match_parent" | ||
5 | + xmlns:tools="http://schemas.android.com/tools" | ||
6 | + android:gravity="center" | ||
7 | + android:orientation="horizontal" | ||
8 | + android:padding="10dp"> | ||
9 | + | ||
10 | + <ProgressBar | ||
11 | + android:id="@+id/pb" | ||
12 | + android:layout_width="50dp" | ||
13 | + android:layout_height="50dp" | ||
14 | + android:layout_gravity="center" | ||
15 | + android:layout_margin="5dp" | ||
16 | + android:indeterminateDuration="300" /> | ||
17 | + | ||
18 | + <!--android:indeterminateDrawable="@drawable/progress_bar"--> | ||
19 | + | ||
20 | + <TextView | ||
21 | + android:id="@+id/tv" | ||
22 | + android:layout_width="0dp" | ||
23 | + android:layout_height="wrap_content" | ||
24 | + android:layout_weight="1" | ||
25 | + android:gravity="left|center" | ||
26 | + android:textSize="22sp" | ||
27 | + tools:ignore="RtlHardcoded" /> | ||
28 | +</LinearLayout> |
lib/android/src/main/res/values/strings.xml
0 → 100644
lib/src/index.ts
1 | export { default as Circle } from "./circle"; | 1 | export { default as Circle } from "./circle"; |
2 | -export { default as Cluster } from "./cluster"; | 2 | +export { default as Cluster } from "./cluster/index"; |
3 | export { default as HeatMap } from "./heat-map"; | 3 | export { default as HeatMap } from "./heat-map"; |
4 | export { default as MapView } from "./map-view"; | 4 | export { default as MapView } from "./map-view"; |
5 | export { default as Marker } from "./marker"; | 5 | export { default as Marker } from "./marker"; |
6 | +export { default as DrivingRoute } from "./route/driving-route"; | ||
6 | export { default as MultiPoint } from "./multi-point"; | 7 | export { default as MultiPoint } from "./multi-point"; |
7 | export { default as Polygon } from "./polygon"; | 8 | export { default as Polygon } from "./polygon"; |
8 | export { default as Polyline } from "./polyline"; | 9 | export { default as Polyline } from "./polyline"; |
lib/src/route/driving-route.tsx
0 → 100644
1 | +import * as React from "react"; | ||
2 | +import { ColorValue, ImageSourcePropType, Platform, processColor, requireNativeComponent } from "react-native"; | ||
3 | +import Component from "../component"; | ||
4 | +// @ts-ignore | ||
5 | +import resolveAssetSource from "react-native/Libraries/Image/resolveAssetSource"; | ||
6 | +import { LatLng } from "../types"; | ||
7 | + | ||
8 | +export interface DrivingRouteProps { | ||
9 | + /** | ||
10 | + * 起点 | ||
11 | + */ | ||
12 | + startPoint: LatLng; | ||
13 | + /** | ||
14 | + * 终点 | ||
15 | + */ | ||
16 | + endPoint: LatLng; | ||
17 | + /** | ||
18 | + * 途经点 | ||
19 | + */ | ||
20 | + throughPointList?: LatLng[]; | ||
21 | + /** | ||
22 | + * 显示途经点 | ||
23 | + */ | ||
24 | + throughPointVisible?: boolean; | ||
25 | + /** | ||
26 | + * 根据不同的路段拥堵情况展示不同的颜色 | ||
27 | + */ | ||
28 | + colorFulLine?: boolean; | ||
29 | + /** | ||
30 | + * 线段宽度 | ||
31 | + */ | ||
32 | + width?: number; | ||
33 | + /** | ||
34 | + * 路线的纹理 | ||
35 | + */ | ||
36 | + roadLine?: ImageSourcePropType; | ||
37 | + /** | ||
38 | + * 驾车图标 | ||
39 | + */ | ||
40 | + driveIcon?: ImageSourcePropType; | ||
41 | + /** | ||
42 | + * 起点图标 | ||
43 | + */ | ||
44 | + startIcon?: ImageSourcePropType; | ||
45 | + /** | ||
46 | + * 终点图标 | ||
47 | + */ | ||
48 | + endIcon?: ImageSourcePropType; | ||
49 | + /** | ||
50 | + * 途经点图标 | ||
51 | + */ | ||
52 | + throughPointIcon?: ImageSourcePropType; | ||
53 | + /** | ||
54 | + * 线段颜色 | ||
55 | + */ | ||
56 | + lineColor?: ColorValue; | ||
57 | +} | ||
58 | + | ||
59 | +export default class extends Component<DrivingRouteProps> { | ||
60 | + static defaultProps = { with: 14, throughPointVisible: true }; | ||
61 | + | ||
62 | + /** | ||
63 | + * 路线规划 | ||
64 | + */ | ||
65 | + routePlan(start: LatLng, end: LatLng, throughPointList: LatLng[] = []) { | ||
66 | + this.invoke("searchRoute", [start, end, throughPointList]); | ||
67 | + } | ||
68 | + | ||
69 | + render() { | ||
70 | + const props = { | ||
71 | + ...this.props, | ||
72 | + }; | ||
73 | + return ( | ||
74 | + <NativeDrivingRoute | ||
75 | + {...props} | ||
76 | + driveIcon={resolveAssetSource(props.driveIcon)} | ||
77 | + startIcon={resolveAssetSource(props.startIcon)} | ||
78 | + endIcon={resolveAssetSource(props.endIcon)} | ||
79 | + throughPointIcon={resolveAssetSource(props.throughPointIcon)} | ||
80 | + roadLine={resolveAssetSource(props.roadLine)} | ||
81 | + /> | ||
82 | + ); | ||
83 | + } | ||
84 | +} | ||
85 | + | ||
86 | +const NativeDrivingRoute = requireNativeComponent<DrivingRouteProps>("DrivingRoute"); |