react-native-cn-maps 0.1.0

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 (42) hide show
  1. package/CnMaps.podspec +21 -0
  2. package/LICENSE +20 -0
  3. package/README.md +89 -0
  4. package/android/build.gradle +68 -0
  5. package/android/src/main/AndroidManifest.xml +7 -0
  6. package/android/src/main/java/com/cnmaps/MapView.kt +368 -0
  7. package/android/src/main/java/com/cnmaps/MapViewManager.kt +112 -0
  8. package/android/src/main/java/com/cnmaps/MapsPackage.kt +17 -0
  9. package/ios/RNMapsMapView.h +14 -0
  10. package/ios/RNMapsMapView.mm +291 -0
  11. package/lib/module/MapMarker.js +8 -0
  12. package/lib/module/MapMarker.js.map +1 -0
  13. package/lib/module/MapView.js +111 -0
  14. package/lib/module/MapView.js.map +1 -0
  15. package/lib/module/MapViewNativeComponent.ts +79 -0
  16. package/lib/module/coordinate.js +72 -0
  17. package/lib/module/coordinate.js.map +1 -0
  18. package/lib/module/index.js +5 -0
  19. package/lib/module/index.js.map +1 -0
  20. package/lib/module/package.json +1 -0
  21. package/lib/module/types.js +4 -0
  22. package/lib/module/types.js.map +1 -0
  23. package/lib/typescript/package.json +1 -0
  24. package/lib/typescript/src/MapMarker.d.ts +8 -0
  25. package/lib/typescript/src/MapMarker.d.ts.map +1 -0
  26. package/lib/typescript/src/MapView.d.ts +145 -0
  27. package/lib/typescript/src/MapView.d.ts.map +1 -0
  28. package/lib/typescript/src/MapViewNativeComponent.d.ts +55 -0
  29. package/lib/typescript/src/MapViewNativeComponent.d.ts.map +1 -0
  30. package/lib/typescript/src/coordinate.d.ts +8 -0
  31. package/lib/typescript/src/coordinate.d.ts.map +1 -0
  32. package/lib/typescript/src/index.d.ts +5 -0
  33. package/lib/typescript/src/index.d.ts.map +1 -0
  34. package/lib/typescript/src/types.d.ts +50 -0
  35. package/lib/typescript/src/types.d.ts.map +1 -0
  36. package/package.json +182 -0
  37. package/src/MapMarker.tsx +14 -0
  38. package/src/MapView.tsx +201 -0
  39. package/src/MapViewNativeComponent.ts +79 -0
  40. package/src/coordinate.ts +123 -0
  41. package/src/index.tsx +15 -0
  42. package/src/types.ts +59 -0
package/CnMaps.podspec ADDED
@@ -0,0 +1,21 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "CnMaps"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/popsiclelmlm/react-native-cn-maps.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+ install_modules_dependencies(s)
20
+ s.dependency "AMap3DMap"
21
+ end
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 popsiclelmlm
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # react-native-cn-maps
2
+
3
+ React Native Map components for China providers, with a `react-native-maps`-compatible API shape and a Fabric-only native implementation.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ npm install react-native-cn-maps
9
+ ```
10
+
11
+ This package currently targets React Native New Architecture/Fabric only. The first provider is AMap/Gaode (`provider="amap"`) on Android and iOS.
12
+
13
+ ## Native Setup
14
+
15
+ ### Android
16
+
17
+ Add your AMap Android key in the host app manifest:
18
+
19
+ ```xml
20
+ <application>
21
+ <meta-data
22
+ android:name="com.amap.api.v2.apikey"
23
+ android:value="YOUR_AMAP_ANDROID_KEY" />
24
+ </application>
25
+ ```
26
+
27
+ The Android SDK version can be overridden from the host Gradle project:
28
+
29
+ ```gradle
30
+ ext.amapSdkVersion = "latest.integration"
31
+ ```
32
+
33
+ ### iOS
34
+
35
+ Set the AMap iOS key before the React Native surface starts:
36
+
37
+ ```swift
38
+ import AMapFoundationKit
39
+
40
+ AMapServices.shared().apiKey = "YOUR_AMAP_IOS_KEY"
41
+ ```
42
+
43
+ The podspec depends on `AMap3DMap`, which pulls in `AMapFoundation`.
44
+
45
+ ## Usage
46
+
47
+ ```tsx
48
+ import MapView, { Marker } from 'react-native-cn-maps';
49
+
50
+ <MapView
51
+ provider="amap"
52
+ coordinateSystem="gcj02"
53
+ initialRegion={{
54
+ latitude: 31.2304,
55
+ longitude: 121.4737,
56
+ latitudeDelta: 0.05,
57
+ longitudeDelta: 0.05,
58
+ }}
59
+ >
60
+ <Marker
61
+ coordinate={{ latitude: 31.2304, longitude: 121.4737 }}
62
+ title="Shanghai"
63
+ />
64
+ </MapView>;
65
+ ```
66
+
67
+ ## MVP Scope
68
+
69
+ - `MapView`
70
+ - `Marker`
71
+ - `initialRegion`
72
+ - controlled `region`
73
+ - `onRegionChange`
74
+ - `onRegionChangeComplete`
75
+ - marker `onPress`
76
+ - `animateToRegion`
77
+ - `coordinateSystem="gcj02" | "wgs84"`
78
+
79
+ `Polyline`, `Polygon`, `Circle`, custom marker views, callouts, and extra providers are intentionally left for later milestones.
80
+
81
+ ## Contributing
82
+
83
+ - [Development workflow](CONTRIBUTING.md#development-workflow)
84
+ - [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
85
+ - [Code of conduct](CODE_OF_CONDUCT.md)
86
+
87
+ ## License
88
+
89
+ MIT
@@ -0,0 +1,68 @@
1
+ buildscript {
2
+ ext.CnMaps = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36,
6
+ targetSdkVersion: 36
7
+ ]
8
+
9
+ ext.getExtOrDefault = { prop ->
10
+ if (rootProject.ext.has(prop)) {
11
+ return rootProject.ext.get(prop)
12
+ }
13
+
14
+ return CnMaps[prop]
15
+ }
16
+
17
+ repositories {
18
+ google()
19
+ mavenCentral()
20
+ }
21
+
22
+ dependencies {
23
+ classpath "com.android.tools.build:gradle:8.7.2"
24
+ // noinspection DifferentKotlinGradleVersion
25
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
26
+ }
27
+ }
28
+
29
+
30
+ apply plugin: "com.android.library"
31
+ apply plugin: "kotlin-android"
32
+
33
+ apply plugin: "com.facebook.react"
34
+
35
+ android {
36
+ namespace "com.cnmaps"
37
+
38
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
39
+
40
+ defaultConfig {
41
+ minSdkVersion getExtOrDefault("minSdkVersion")
42
+ targetSdkVersion getExtOrDefault("targetSdkVersion")
43
+ }
44
+
45
+ buildFeatures {
46
+ buildConfig true
47
+ }
48
+
49
+ buildTypes {
50
+ release {
51
+ minifyEnabled false
52
+ }
53
+ }
54
+
55
+ lint {
56
+ disable "GradleCompatible"
57
+ }
58
+
59
+ compileOptions {
60
+ sourceCompatibility JavaVersion.VERSION_1_8
61
+ targetCompatibility JavaVersion.VERSION_1_8
62
+ }
63
+ }
64
+
65
+ dependencies {
66
+ implementation "com.facebook.react:react-android"
67
+ implementation "com.amap.api:3dmap-location-search:${rootProject.ext.has('amapSdkVersion') ? rootProject.ext.get('amapSdkVersion') : 'latest.integration'}"
68
+ }
@@ -0,0 +1,7 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <uses-permission android:name="android.permission.INTERNET" />
3
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
4
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
5
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
6
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
7
+ </manifest>
@@ -0,0 +1,368 @@
1
+ package com.cnmaps
2
+
3
+ import android.graphics.Color
4
+ import android.view.MotionEvent
5
+ import android.widget.FrameLayout
6
+ import com.amap.api.maps.AMap
7
+ import com.amap.api.maps.CameraUpdate
8
+ import com.amap.api.maps.CameraUpdateFactory
9
+ import com.amap.api.maps.MapView as AMapView
10
+ import com.amap.api.maps.model.BitmapDescriptorFactory
11
+ import com.amap.api.maps.model.CameraPosition
12
+ import com.amap.api.maps.model.LatLng
13
+ import com.amap.api.maps.model.LatLngBounds
14
+ import com.amap.api.maps.model.Marker
15
+ import com.amap.api.maps.model.MarkerOptions
16
+ import com.facebook.react.bridge.Arguments
17
+ import com.facebook.react.bridge.LifecycleEventListener
18
+ import com.facebook.react.bridge.ReadableArray
19
+ import com.facebook.react.bridge.ReadableMap
20
+ import com.facebook.react.bridge.WritableMap
21
+ import com.facebook.react.uimanager.ThemedReactContext
22
+ import com.facebook.react.uimanager.UIManagerHelper
23
+ import com.facebook.react.uimanager.events.Event
24
+ import kotlin.math.abs
25
+ import kotlin.math.ln
26
+ import kotlin.math.max
27
+ import kotlin.math.min
28
+
29
+ data class MapRegion(
30
+ val latitude: Double,
31
+ val longitude: Double,
32
+ val latitudeDelta: Double,
33
+ val longitudeDelta: Double
34
+ )
35
+
36
+ class MapView(private val reactContext: ThemedReactContext) :
37
+ FrameLayout(reactContext),
38
+ LifecycleEventListener {
39
+ private val mapView = AMapView(reactContext)
40
+ private val aMap: AMap
41
+ private val markerByIdentifier = LinkedHashMap<String, Marker>()
42
+ private var pendingInitialRegion: MapRegion? = null
43
+ private var didApplyInitialRegion = false
44
+ private var didDestroy = false
45
+ private var isGesture = false
46
+
47
+ init {
48
+ addView(mapView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
49
+ mapView.onCreate(null)
50
+ aMap = mapView.map
51
+ reactContext.addLifecycleEventListener(this)
52
+ configureMap()
53
+ }
54
+
55
+ fun setInitialRegion(region: MapRegion?) {
56
+ if (region == null || didApplyInitialRegion) {
57
+ return
58
+ }
59
+
60
+ pendingInitialRegion = region
61
+ applyPendingInitialRegion()
62
+ }
63
+
64
+ fun setRegion(region: MapRegion?) {
65
+ if (region != null) {
66
+ moveToRegion(region, animated = false)
67
+ }
68
+ }
69
+
70
+ fun animateToRegion(region: MapRegion, duration: Int) {
71
+ moveToRegion(region, animated = true, duration = duration)
72
+ }
73
+
74
+ fun setMarkers(markers: ReadableArray?) {
75
+ markerByIdentifier.values.forEach { it.remove() }
76
+ markerByIdentifier.clear()
77
+
78
+ if (markers == null) {
79
+ return
80
+ }
81
+
82
+ for (index in 0 until markers.size()) {
83
+ val markerMap = markers.getMap(index) ?: continue
84
+ val identifier = markerMap.getOptionalString("identifier") ?: index.toString()
85
+ val latitude = markerMap.getOptionalDouble("latitude") ?: continue
86
+ val longitude = markerMap.getOptionalDouble("longitude") ?: continue
87
+
88
+ val options = MarkerOptions()
89
+ .position(LatLng(latitude, longitude))
90
+ .draggable(markerMap.getOptionalBoolean("draggable") ?: false)
91
+
92
+ markerMap.getOptionalString("title")?.let { options.title(it) }
93
+ markerMap.getOptionalString("description")?.let { options.snippet(it) }
94
+ markerMap.getOptionalString("pinColor")?.let { pinColor ->
95
+ markerHue(pinColor)?.let { hue ->
96
+ options.icon(BitmapDescriptorFactory.defaultMarker(hue))
97
+ }
98
+ }
99
+
100
+ val marker = aMap.addMarker(options)
101
+ marker.`object` = identifier
102
+ markerByIdentifier[identifier] = marker
103
+ }
104
+ }
105
+
106
+ fun setShowsUserLocation(value: Boolean) {
107
+ aMap.isMyLocationEnabled = value
108
+ }
109
+
110
+ fun setZoomEnabled(value: Boolean) {
111
+ aMap.uiSettings.isZoomGesturesEnabled = value
112
+ }
113
+
114
+ fun setScrollEnabled(value: Boolean) {
115
+ aMap.uiSettings.isScrollGesturesEnabled = value
116
+ }
117
+
118
+ fun setRotateEnabled(value: Boolean) {
119
+ aMap.uiSettings.isRotateGesturesEnabled = value
120
+ }
121
+
122
+ fun setPitchEnabled(value: Boolean) {
123
+ aMap.uiSettings.isTiltGesturesEnabled = value
124
+ }
125
+
126
+ fun destroy() {
127
+ if (didDestroy) {
128
+ return
129
+ }
130
+
131
+ didDestroy = true
132
+ reactContext.removeLifecycleEventListener(this)
133
+ markerByIdentifier.values.forEach { it.remove() }
134
+ markerByIdentifier.clear()
135
+ mapView.onDestroy()
136
+ }
137
+
138
+ override fun onHostResume() {
139
+ if (!didDestroy) {
140
+ mapView.onResume()
141
+ }
142
+ }
143
+
144
+ override fun onHostPause() {
145
+ if (!didDestroy) {
146
+ mapView.onPause()
147
+ }
148
+ }
149
+
150
+ override fun onHostDestroy() {
151
+ destroy()
152
+ }
153
+
154
+ override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
155
+ super.onSizeChanged(width, height, oldWidth, oldHeight)
156
+ applyPendingInitialRegion()
157
+ }
158
+
159
+ private fun configureMap() {
160
+ aMap.uiSettings.isZoomControlsEnabled = false
161
+
162
+ aMap.setOnMapTouchListener { event ->
163
+ if (
164
+ event?.actionMasked == MotionEvent.ACTION_DOWN ||
165
+ event?.actionMasked == MotionEvent.ACTION_MOVE
166
+ ) {
167
+ isGesture = true
168
+ }
169
+ }
170
+
171
+ aMap.setOnCameraChangeListener(
172
+ object : AMap.OnCameraChangeListener {
173
+ override fun onCameraChange(position: CameraPosition?) {
174
+ sendRegionEvent("topRegionChange", isGesture)
175
+ }
176
+
177
+ override fun onCameraChangeFinish(position: CameraPosition?) {
178
+ sendRegionEvent("topRegionChangeComplete", isGesture)
179
+ isGesture = false
180
+ }
181
+ }
182
+ )
183
+
184
+ aMap.setOnMarkerClickListener { marker ->
185
+ val identifier = marker.`object` as? String ?: return@setOnMarkerClickListener false
186
+ sendMarkerPressEvent(identifier, marker.position)
187
+ false
188
+ }
189
+ }
190
+
191
+ private fun applyPendingInitialRegion() {
192
+ val region = pendingInitialRegion ?: return
193
+
194
+ if (width <= 0 || height <= 0) {
195
+ return
196
+ }
197
+
198
+ didApplyInitialRegion = true
199
+ pendingInitialRegion = null
200
+ moveToRegion(region, animated = false)
201
+ }
202
+
203
+ private fun moveToRegion(region: MapRegion, animated: Boolean, duration: Int = 0) {
204
+ val applyCamera = Runnable {
205
+ val boundsUpdate = CameraUpdateFactory.newLatLngBounds(region.toBounds(), 0)
206
+ runCatching {
207
+ applyCameraUpdate(boundsUpdate, animated, duration)
208
+ }.onFailure {
209
+ val fallbackUpdate = CameraUpdateFactory.newLatLngZoom(
210
+ LatLng(region.latitude, region.longitude),
211
+ region.toApproximateZoom()
212
+ )
213
+ applyCameraUpdate(fallbackUpdate, animated, duration)
214
+ }
215
+ }
216
+
217
+ if (width <= 0 || height <= 0) {
218
+ post(applyCamera)
219
+ } else {
220
+ applyCamera.run()
221
+ }
222
+ }
223
+
224
+ private fun applyCameraUpdate(update: CameraUpdate, animated: Boolean, duration: Int) {
225
+ if (animated) {
226
+ aMap.animateCamera(update, duration.toLong(), null)
227
+ } else {
228
+ aMap.moveCamera(update)
229
+ }
230
+ }
231
+
232
+ private fun sendRegionEvent(eventName: String, gesture: Boolean) {
233
+ if (id == NO_ID) {
234
+ return
235
+ }
236
+
237
+ currentRegion()?.let { region ->
238
+ UIManagerHelper.getEventDispatcher(reactContext)
239
+ ?.dispatchEvent(RegionEvent(UIManagerHelper.getSurfaceId(this), id, eventName, region, gesture))
240
+ }
241
+ }
242
+
243
+ private fun sendMarkerPressEvent(identifier: String, coordinate: LatLng) {
244
+ if (id == NO_ID) {
245
+ return
246
+ }
247
+
248
+ UIManagerHelper.getEventDispatcher(reactContext)
249
+ ?.dispatchEvent(
250
+ MarkerPressEvent(
251
+ UIManagerHelper.getSurfaceId(this),
252
+ id,
253
+ identifier,
254
+ coordinate.latitude,
255
+ coordinate.longitude
256
+ )
257
+ )
258
+ }
259
+
260
+ private fun currentRegion(): MapRegion? {
261
+ val bounds = runCatching {
262
+ aMap.projection.visibleRegion.latLngBounds
263
+ }.getOrNull() ?: return null
264
+ val target = aMap.cameraPosition.target ?: return null
265
+ val latitudeDelta = abs(bounds.northeast.latitude - bounds.southwest.latitude)
266
+ val longitudeDelta = abs(bounds.northeast.longitude - bounds.southwest.longitude)
267
+
268
+ return MapRegion(
269
+ latitude = target.latitude,
270
+ longitude = target.longitude,
271
+ latitudeDelta = latitudeDelta,
272
+ longitudeDelta = longitudeDelta
273
+ )
274
+ }
275
+
276
+ private fun MapRegion.toBounds(): LatLngBounds {
277
+ val halfLat = max(latitudeDelta, MIN_DELTA) / 2.0
278
+ val halfLon = max(longitudeDelta, MIN_DELTA) / 2.0
279
+ val southwest = LatLng(
280
+ max(-90.0, latitude - halfLat),
281
+ max(-180.0, longitude - halfLon)
282
+ )
283
+ val northeast = LatLng(
284
+ min(90.0, latitude + halfLat),
285
+ min(180.0, longitude + halfLon)
286
+ )
287
+
288
+ return LatLngBounds(southwest, northeast)
289
+ }
290
+
291
+ private fun MapRegion.toApproximateZoom(): Float {
292
+ val delta = max(max(latitudeDelta, longitudeDelta), MIN_DELTA)
293
+ val zoom = ln(360.0 / delta) / ln(2.0)
294
+ return zoom.toFloat().coerceIn(3f, 20f)
295
+ }
296
+
297
+ private fun markerHue(color: String): Float? {
298
+ return runCatching {
299
+ val hsv = FloatArray(3)
300
+ Color.colorToHSV(Color.parseColor(color), hsv)
301
+ hsv[0]
302
+ }.getOrNull()
303
+ }
304
+
305
+ private fun ReadableMap.getOptionalString(key: String): String? {
306
+ return if (hasKey(key) && !isNull(key)) getString(key) else null
307
+ }
308
+
309
+ private fun ReadableMap.getOptionalDouble(key: String): Double? {
310
+ return if (hasKey(key) && !isNull(key)) getDouble(key) else null
311
+ }
312
+
313
+ private fun ReadableMap.getOptionalBoolean(key: String): Boolean? {
314
+ return if (hasKey(key) && !isNull(key)) getBoolean(key) else null
315
+ }
316
+
317
+ private class RegionEvent(
318
+ surfaceId: Int,
319
+ viewId: Int,
320
+ private val rnEventName: String,
321
+ private val region: MapRegion,
322
+ private val isGesture: Boolean
323
+ ) : Event<RegionEvent>(surfaceId, viewId) {
324
+ override fun getEventName(): String = rnEventName
325
+
326
+ override fun getEventData(): WritableMap =
327
+ Arguments.createMap().apply {
328
+ putMap(
329
+ "region",
330
+ Arguments.createMap().apply {
331
+ putDouble("latitude", region.latitude)
332
+ putDouble("longitude", region.longitude)
333
+ putDouble("latitudeDelta", region.latitudeDelta)
334
+ putDouble("longitudeDelta", region.longitudeDelta)
335
+ }
336
+ )
337
+ putBoolean("isGesture", isGesture)
338
+ }
339
+ }
340
+
341
+ private class MarkerPressEvent(
342
+ surfaceId: Int,
343
+ viewId: Int,
344
+ private val identifier: String,
345
+ private val latitude: Double,
346
+ private val longitude: Double
347
+ ) : Event<MarkerPressEvent>(surfaceId, viewId) {
348
+ override fun getEventName(): String = "topMarkerPress"
349
+
350
+ override fun canCoalesce(): Boolean = false
351
+
352
+ override fun getEventData(): WritableMap =
353
+ Arguments.createMap().apply {
354
+ putString("identifier", identifier)
355
+ putMap(
356
+ "coordinate",
357
+ Arguments.createMap().apply {
358
+ putDouble("latitude", latitude)
359
+ putDouble("longitude", longitude)
360
+ }
361
+ )
362
+ }
363
+ }
364
+
365
+ private companion object {
366
+ private const val MIN_DELTA = 0.000001
367
+ }
368
+ }
@@ -0,0 +1,112 @@
1
+ package com.cnmaps
2
+
3
+ import com.facebook.react.bridge.ReadableArray
4
+ import com.facebook.react.bridge.ReadableMap
5
+ import com.facebook.react.module.annotations.ReactModule
6
+ import com.facebook.react.uimanager.SimpleViewManager
7
+ import com.facebook.react.uimanager.ThemedReactContext
8
+ import com.facebook.react.uimanager.ViewManagerDelegate
9
+ import com.facebook.react.uimanager.annotations.ReactProp
10
+ import com.facebook.react.viewmanagers.RNMapsMapViewManagerDelegate
11
+ import com.facebook.react.viewmanagers.RNMapsMapViewManagerInterface
12
+
13
+ @ReactModule(name = MapViewManager.REACT_CLASS)
14
+ class MapViewManager : SimpleViewManager<MapView>(),
15
+ RNMapsMapViewManagerInterface<MapView> {
16
+ private val delegate: ViewManagerDelegate<MapView> = RNMapsMapViewManagerDelegate(this)
17
+
18
+ override fun getDelegate(): ViewManagerDelegate<MapView> = delegate
19
+
20
+ override fun getName(): String = REACT_CLASS
21
+
22
+ public override fun createViewInstance(context: ThemedReactContext): MapView {
23
+ return MapView(context)
24
+ }
25
+
26
+ override fun onDropViewInstance(view: MapView) {
27
+ view.destroy()
28
+ super.onDropViewInstance(view)
29
+ }
30
+
31
+ @ReactProp(name = "provider")
32
+ override fun setProvider(view: MapView, value: String?) {
33
+ // Fabric schema reserves future providers; the current native implementation is AMap only.
34
+ }
35
+
36
+ @ReactProp(name = "coordinateSystem")
37
+ override fun setCoordinateSystem(view: MapView, value: String?) {
38
+ // JS normalizes coordinates before they cross the native boundary.
39
+ }
40
+
41
+ @ReactProp(name = "initialRegion")
42
+ override fun setInitialRegion(view: MapView, value: ReadableMap?) {
43
+ view.setInitialRegion(value?.toMapRegion())
44
+ }
45
+
46
+ @ReactProp(name = "region")
47
+ override fun setRegion(view: MapView, value: ReadableMap?) {
48
+ view.setRegion(value?.toMapRegion())
49
+ }
50
+
51
+ @ReactProp(name = "markers")
52
+ override fun setMarkers(view: MapView, value: ReadableArray?) {
53
+ view.setMarkers(value)
54
+ }
55
+
56
+ @ReactProp(name = "showsUserLocation")
57
+ override fun setShowsUserLocation(view: MapView, value: Boolean) {
58
+ view.setShowsUserLocation(value)
59
+ }
60
+
61
+ @ReactProp(name = "zoomEnabled")
62
+ override fun setZoomEnabled(view: MapView, value: Boolean) {
63
+ view.setZoomEnabled(value)
64
+ }
65
+
66
+ @ReactProp(name = "scrollEnabled")
67
+ override fun setScrollEnabled(view: MapView, value: Boolean) {
68
+ view.setScrollEnabled(value)
69
+ }
70
+
71
+ @ReactProp(name = "rotateEnabled")
72
+ override fun setRotateEnabled(view: MapView, value: Boolean) {
73
+ view.setRotateEnabled(value)
74
+ }
75
+
76
+ @ReactProp(name = "pitchEnabled")
77
+ override fun setPitchEnabled(view: MapView, value: Boolean) {
78
+ view.setPitchEnabled(value)
79
+ }
80
+
81
+ override fun animateToRegion(
82
+ view: MapView,
83
+ latitude: Double,
84
+ longitude: Double,
85
+ latitudeDelta: Double,
86
+ longitudeDelta: Double,
87
+ duration: Int
88
+ ) {
89
+ view.animateToRegion(
90
+ MapRegion(
91
+ latitude = latitude,
92
+ longitude = longitude,
93
+ latitudeDelta = latitudeDelta,
94
+ longitudeDelta = longitudeDelta
95
+ ),
96
+ duration
97
+ )
98
+ }
99
+
100
+ private fun ReadableMap.toMapRegion(): MapRegion {
101
+ return MapRegion(
102
+ latitude = getDouble("latitude"),
103
+ longitude = getDouble("longitude"),
104
+ latitudeDelta = getDouble("latitudeDelta"),
105
+ longitudeDelta = getDouble("longitudeDelta")
106
+ )
107
+ }
108
+
109
+ companion object {
110
+ const val REACT_CLASS = "RNMapsMapView"
111
+ }
112
+ }
@@ -0,0 +1,17 @@
1
+ package com.cnmaps
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfoProvider
7
+ import com.facebook.react.uimanager.ViewManager
8
+
9
+ class MapsPackage : BaseReactPackage() {
10
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
11
+ return listOf(MapViewManager())
12
+ }
13
+
14
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = null
15
+
16
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider { emptyMap() }
17
+ }