@exterio/react-native-yamap-lite 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +510 -0
  3. package/YamapLite.podspec +21 -0
  4. package/android/build.gradle +101 -0
  5. package/android/gradle.properties +14 -0
  6. package/android/settings.gradle +1 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/java/com/yamaplite/ClusteredYamapLiteViewManager.kt +181 -0
  9. package/android/src/main/java/com/yamaplite/Components/ClusteredYamapLiteView.kt +169 -0
  10. package/android/src/main/java/com/yamaplite/Components/YamapLiteCircleView.kt +145 -0
  11. package/android/src/main/java/com/yamaplite/Components/YamapLiteMarkerView.kt +214 -0
  12. package/android/src/main/java/com/yamaplite/Components/YamapLitePolygon.kt +149 -0
  13. package/android/src/main/java/com/yamaplite/Components/YamapLitePolyline.kt +171 -0
  14. package/android/src/main/java/com/yamaplite/Components/YamapLiteView.kt +678 -0
  15. package/android/src/main/java/com/yamaplite/Events/CameraPositionChangeEvent.kt +38 -0
  16. package/android/src/main/java/com/yamaplite/Events/MapLoadEvent.kt +34 -0
  17. package/android/src/main/java/com/yamaplite/Events/PressEvent.kt +24 -0
  18. package/android/src/main/java/com/yamaplite/Utils/ImageCache.kt +45 -0
  19. package/android/src/main/java/com/yamaplite/Utils/PointParser.kt +39 -0
  20. package/android/src/main/java/com/yamaplite/Utils/ResolveImageHelper.kt +122 -0
  21. package/android/src/main/java/com/yamaplite/Utils/YamapUtils.kt +169 -0
  22. package/android/src/main/java/com/yamaplite/YamapLiteCircleViewManager.kt +67 -0
  23. package/android/src/main/java/com/yamaplite/YamapLiteMarkerViewManager.kt +82 -0
  24. package/android/src/main/java/com/yamaplite/YamapLitePackage.kt +41 -0
  25. package/android/src/main/java/com/yamaplite/YamapLitePolygonViewManager.kt +61 -0
  26. package/android/src/main/java/com/yamaplite/YamapLitePolylineViewManager.kt +75 -0
  27. package/android/src/main/java/com/yamaplite/YamapLiteViewManager.kt +176 -0
  28. package/ios/ClusteredYamapLiteView.h +15 -0
  29. package/ios/ClusteredYamapLiteView.mm +325 -0
  30. package/ios/ClusteredYamapLiteViewManager.mm +17 -0
  31. package/ios/Components/Circle.swift +108 -0
  32. package/ios/Components/ClusteredYamap.swift +190 -0
  33. package/ios/Components/Marker.swift +187 -0
  34. package/ios/Components/Polygon.swift +108 -0
  35. package/ios/Components/Polyline.swift +125 -0
  36. package/ios/Components/Yamap.swift +585 -0
  37. package/ios/Listeners/CameraListener.swift +54 -0
  38. package/ios/Listeners/ClusterListener.swift +38 -0
  39. package/ios/Listeners/MapInputListener.swift +35 -0
  40. package/ios/Listeners/MapLoadListener.swift +35 -0
  41. package/ios/Listeners/MapObjectTap.swift +12 -0
  42. package/ios/Listeners/UserLocationObjectListener.swift +29 -0
  43. package/ios/Models/YamapModels.swift +77 -0
  44. package/ios/Utils/ImageCache.swift +20 -0
  45. package/ios/Utils/PointsEqual.h +45 -0
  46. package/ios/Utils/ResolveImageHelper.swift +142 -0
  47. package/ios/YamapLiteCircleView.h +15 -0
  48. package/ios/YamapLiteCircleView.mm +102 -0
  49. package/ios/YamapLiteMarkerView.h +15 -0
  50. package/ios/YamapLiteMarkerView.mm +102 -0
  51. package/ios/YamapLitePolygonView.h +15 -0
  52. package/ios/YamapLitePolygonView.mm +120 -0
  53. package/ios/YamapLitePolylineView.h +15 -0
  54. package/ios/YamapLitePolylineView.mm +115 -0
  55. package/ios/YamapLiteView.h +15 -0
  56. package/ios/YamapLiteView.mm +361 -0
  57. package/ios/YamapLiteViewManager.mm +17 -0
  58. package/ios/YamapUtils.h +5 -0
  59. package/ios/YamapUtils.mm +205 -0
  60. package/lib/module/@types/index.js +8 -0
  61. package/lib/module/@types/index.js.map +1 -0
  62. package/lib/module/ClusteredYamapLiteViewNativeComponent.ts +98 -0
  63. package/lib/module/Components/Circle.js +20 -0
  64. package/lib/module/Components/Circle.js.map +1 -0
  65. package/lib/module/Components/ClusteredYamap.js +133 -0
  66. package/lib/module/Components/ClusteredYamap.js.map +1 -0
  67. package/lib/module/Components/Marker.js +40 -0
  68. package/lib/module/Components/Marker.js.map +1 -0
  69. package/lib/module/Components/Polygon.js +25 -0
  70. package/lib/module/Components/Polygon.js.map +1 -0
  71. package/lib/module/Components/Polyline.js +25 -0
  72. package/lib/module/Components/Polyline.js.map +1 -0
  73. package/lib/module/Components/Yamap.js +124 -0
  74. package/lib/module/Components/Yamap.js.map +1 -0
  75. package/lib/module/Components/index.js +9 -0
  76. package/lib/module/Components/index.js.map +1 -0
  77. package/lib/module/NativeYamapUtils.js +5 -0
  78. package/lib/module/NativeYamapUtils.js.map +1 -0
  79. package/lib/module/Utils/YamapUtils.js +14 -0
  80. package/lib/module/Utils/YamapUtils.js.map +1 -0
  81. package/lib/module/YamapCircleViewNativeComponent.ts +28 -0
  82. package/lib/module/YamapLiteViewNativeComponent.ts +93 -0
  83. package/lib/module/YamapMarkerViewNativeComponent.ts +32 -0
  84. package/lib/module/YamapPolygonViewNativeComponent.ts +28 -0
  85. package/lib/module/YamapPolylineViewNativeComponent.ts +31 -0
  86. package/lib/module/index.js +7 -0
  87. package/lib/module/index.js.map +1 -0
  88. package/lib/module/package.json +1 -0
  89. package/lib/typescript/package.json +1 -0
  90. package/lib/typescript/src/@types/index.d.ts +257 -0
  91. package/lib/typescript/src/@types/index.d.ts.map +1 -0
  92. package/lib/typescript/src/ClusteredYamapLiteViewNativeComponent.d.ts +82 -0
  93. package/lib/typescript/src/ClusteredYamapLiteViewNativeComponent.d.ts.map +1 -0
  94. package/lib/typescript/src/Components/Circle.d.ts +4 -0
  95. package/lib/typescript/src/Components/Circle.d.ts.map +1 -0
  96. package/lib/typescript/src/Components/ClusteredYamap.d.ts +3 -0
  97. package/lib/typescript/src/Components/ClusteredYamap.d.ts.map +1 -0
  98. package/lib/typescript/src/Components/Marker.d.ts +3 -0
  99. package/lib/typescript/src/Components/Marker.d.ts.map +1 -0
  100. package/lib/typescript/src/Components/Polygon.d.ts +4 -0
  101. package/lib/typescript/src/Components/Polygon.d.ts.map +1 -0
  102. package/lib/typescript/src/Components/Polyline.d.ts +4 -0
  103. package/lib/typescript/src/Components/Polyline.d.ts.map +1 -0
  104. package/lib/typescript/src/Components/Yamap.d.ts +3 -0
  105. package/lib/typescript/src/Components/Yamap.d.ts.map +1 -0
  106. package/lib/typescript/src/Components/index.d.ts +7 -0
  107. package/lib/typescript/src/Components/index.d.ts.map +1 -0
  108. package/lib/typescript/src/NativeYamapUtils.d.ts +30 -0
  109. package/lib/typescript/src/NativeYamapUtils.d.ts.map +1 -0
  110. package/lib/typescript/src/Utils/YamapUtils.d.ts +27 -0
  111. package/lib/typescript/src/Utils/YamapUtils.d.ts.map +1 -0
  112. package/lib/typescript/src/YamapCircleViewNativeComponent.d.ts +20 -0
  113. package/lib/typescript/src/YamapCircleViewNativeComponent.d.ts.map +1 -0
  114. package/lib/typescript/src/YamapLiteViewNativeComponent.d.ts +80 -0
  115. package/lib/typescript/src/YamapLiteViewNativeComponent.d.ts.map +1 -0
  116. package/lib/typescript/src/YamapMarkerViewNativeComponent.d.ts +25 -0
  117. package/lib/typescript/src/YamapMarkerViewNativeComponent.d.ts.map +1 -0
  118. package/lib/typescript/src/YamapPolygonViewNativeComponent.d.ts +20 -0
  119. package/lib/typescript/src/YamapPolygonViewNativeComponent.d.ts.map +1 -0
  120. package/lib/typescript/src/YamapPolylineViewNativeComponent.d.ts +23 -0
  121. package/lib/typescript/src/YamapPolylineViewNativeComponent.d.ts.map +1 -0
  122. package/lib/typescript/src/index.d.ts +5 -0
  123. package/lib/typescript/src/index.d.ts.map +1 -0
  124. package/package.json +189 -0
  125. package/src/@types/index.ts +314 -0
  126. package/src/ClusteredYamapLiteViewNativeComponent.ts +98 -0
  127. package/src/Components/Circle.tsx +22 -0
  128. package/src/Components/ClusteredYamap.tsx +194 -0
  129. package/src/Components/Marker.tsx +50 -0
  130. package/src/Components/Polygon.tsx +27 -0
  131. package/src/Components/Polyline.tsx +27 -0
  132. package/src/Components/Yamap.tsx +176 -0
  133. package/src/Components/index.ts +6 -0
  134. package/src/NativeYamapUtils.ts +47 -0
  135. package/src/Utils/YamapUtils.ts +63 -0
  136. package/src/YamapCircleViewNativeComponent.ts +28 -0
  137. package/src/YamapLiteViewNativeComponent.ts +93 -0
  138. package/src/YamapMarkerViewNativeComponent.ts +32 -0
  139. package/src/YamapPolygonViewNativeComponent.ts +28 -0
  140. package/src/YamapPolylineViewNativeComponent.ts +31 -0
  141. package/src/index.tsx +5 -0
@@ -0,0 +1,678 @@
1
+ package com.yamaplite.components
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import android.graphics.PointF
6
+ import android.os.Handler
7
+ import android.os.Looper
8
+ import android.util.Log
9
+ import android.view.View
10
+ import android.widget.FrameLayout
11
+ import com.facebook.react.bridge.Arguments
12
+ import com.facebook.react.bridge.ReactContext
13
+ import com.facebook.react.bridge.WritableArray
14
+ import com.facebook.react.bridge.WritableMap
15
+ import com.facebook.react.uimanager.UIManagerHelper
16
+ import com.yamaplite.events.CameraPositionChangeEvent
17
+ import com.yamaplite.events.MapLoadEvent
18
+ import com.yamaplite.events.PressEvent
19
+ import com.yamaplite.utils.ResolveImageHelper
20
+ import com.yandex.mapkit.Animation
21
+ import com.yandex.mapkit.MapKitFactory
22
+ import com.yandex.mapkit.ScreenPoint
23
+ import com.yandex.mapkit.geometry.BoundingBox
24
+ import com.yandex.mapkit.geometry.Geometry
25
+ import com.yandex.mapkit.geometry.Point
26
+ import com.yandex.mapkit.layers.ObjectEvent
27
+ import com.yandex.mapkit.logo.Alignment
28
+ import com.yandex.mapkit.logo.HorizontalAlignment
29
+ import com.yandex.mapkit.logo.Padding
30
+ import com.yandex.mapkit.logo.VerticalAlignment
31
+ import com.yandex.mapkit.map.CameraListener
32
+ import com.yandex.mapkit.map.CameraPosition
33
+ import com.yandex.mapkit.map.CameraUpdateReason
34
+ import com.yandex.mapkit.map.CircleMapObject
35
+ import com.yandex.mapkit.map.ClusterizedPlacemarkCollection
36
+ import com.yandex.mapkit.map.IconStyle
37
+ import com.yandex.mapkit.map.InputListener
38
+ import com.yandex.mapkit.map.Map as YMap
39
+ import com.yandex.mapkit.map.MapLoadStatistics
40
+ import com.yandex.mapkit.map.MapLoadedListener
41
+ import com.yandex.mapkit.map.MapObjectCollection
42
+ import com.yandex.mapkit.map.MapObjectVisitor
43
+ import com.yandex.mapkit.map.MapType
44
+ import com.yandex.mapkit.map.PlacemarkMapObject
45
+ import com.yandex.mapkit.map.PolygonMapObject
46
+ import com.yandex.mapkit.map.PolylineMapObject
47
+ import com.yandex.mapkit.mapview.MapView
48
+ import com.yandex.mapkit.user_location.UserLocationLayer
49
+ import com.yandex.mapkit.user_location.UserLocationObjectListener
50
+ import com.yandex.mapkit.user_location.UserLocationView
51
+ import kotlinx.coroutines.CoroutineScope
52
+ import kotlinx.coroutines.Dispatchers
53
+ import kotlinx.coroutines.cancel
54
+ import kotlinx.coroutines.launch
55
+
56
+ open class YamapLiteView(context: Context) :
57
+ FrameLayout(context),
58
+ MapLoadedListener,
59
+ CameraListener,
60
+ UserLocationObjectListener,
61
+ InputListener {
62
+ protected val mapView: MapView = MapView(context)
63
+ private val reactChildren = mutableListOf<View>()
64
+ private val coroutineScope = CoroutineScope(Dispatchers.Main)
65
+
66
+ private var userLocationLayer: UserLocationLayer? = null
67
+ private var isUserLocationEnabled = false
68
+ private var isNightMode = false
69
+ private var mapStyle: String? = null
70
+ private var userLocationIcon: String? = null
71
+ private var userLocationIconScale = 1.0f
72
+ private var userLocationAccuracyFillColor: String? = null
73
+ private var userLocationAccuracyStrokeColor: String? = null
74
+ private var userLocationAccuracyStrokeWidth = 2.0f
75
+ private var scrollGesturesEnabled = true
76
+ private var zoomGesturesEnabled = true
77
+ private var tiltGesturesEnabled = true
78
+ private var rotateGesturesEnabled = true
79
+ private var fastTapEnabled = true
80
+ private var maxFps = 60.0f
81
+ private var mapType: String = "map"
82
+ private var followUser = false
83
+ private var logoPosition: Map<String, Any>? = null
84
+ private var logoPadding: Map<String, Any>? = null
85
+ private var userLocationView: UserLocationView? = null
86
+
87
+ init {
88
+ setupMap()
89
+ mapView.mapWindow.map.setMapLoadedListener(this)
90
+ mapView.mapWindow.map.addCameraListener(this)
91
+ mapView.mapWindow.map.addInputListener(this)
92
+ }
93
+
94
+ private fun setupMap() {
95
+ addView(mapView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
96
+ }
97
+
98
+ fun setUserLocationIcon(icon: String?) {
99
+ userLocationIcon = icon
100
+ if (userLocationView != null) {
101
+ updateUserLocationIcon()
102
+ }
103
+ }
104
+
105
+ fun setUserLocationIconScale(scale: Float) {
106
+ userLocationIconScale = scale
107
+ if (userLocationView != null) {
108
+ updateUserLocationIcon()
109
+ }
110
+ }
111
+
112
+ fun setShowUserPosition(show: Boolean) {
113
+ if (userLocationLayer == null) {
114
+ userLocationLayer = MapKitFactory.getInstance().createUserLocationLayer(mapView.mapWindow)
115
+ }
116
+
117
+ if (show) {
118
+ userLocationLayer!!.setObjectListener(this)
119
+ userLocationLayer!!.isVisible = true
120
+ userLocationLayer!!.isHeadingModeActive = true
121
+ } else {
122
+ userLocationLayer!!.isVisible = false
123
+ userLocationLayer!!.isHeadingModeActive = false
124
+ userLocationLayer!!.setObjectListener(null)
125
+ }
126
+ }
127
+
128
+ fun setNightMode(nightMode: Boolean) {
129
+ mapView.mapWindow.map.isNightModeEnabled = nightMode
130
+ }
131
+
132
+ fun setMapStyle(style: String?) {
133
+ mapStyle = style
134
+ if (!style.isNullOrEmpty()) {
135
+ mapView.mapWindow.map.setMapStyle(style)
136
+ }
137
+ }
138
+
139
+ fun setScrollGesturesEnabled(enabled: Boolean) {
140
+ mapView.mapWindow.map.isScrollGesturesEnabled = enabled
141
+ }
142
+
143
+ fun setZoomGesturesEnabled(enabled: Boolean) {
144
+ mapView.mapWindow.map.isZoomGesturesEnabled = enabled
145
+ }
146
+
147
+ fun setTiltGesturesEnabled(enabled: Boolean) {
148
+ mapView.mapWindow.map.isTiltGesturesEnabled = enabled
149
+ }
150
+
151
+ fun setRotateGesturesEnabled(enabled: Boolean) {
152
+ mapView.mapWindow.map.isRotateGesturesEnabled = enabled
153
+ }
154
+
155
+ fun setFastTapEnabled(enabled: Boolean) {
156
+ mapView.mapWindow.map.isFastTapEnabled = enabled
157
+ }
158
+
159
+ fun setInitialRegion(region: Map<String, Any>?) {
160
+ if (region == null) return
161
+ val latitude = region["lat"] as? Double ?: return
162
+ val longitude = region["lon"] as? Double ?: return
163
+ val zoom = (region["zoom"] as? Double ?: 10.0).toFloat()
164
+ val azimuth = (region["azimuth"] as? Double ?: 0.0).toFloat()
165
+ val tilt = (region["tilt"] as? Double ?: 0.0).toFloat()
166
+
167
+ val point = Point(latitude, longitude)
168
+ val cameraPosition = CameraPosition(point, zoom, azimuth, tilt)
169
+ mapView.getMapWindow().map.move(cameraPosition)
170
+ }
171
+
172
+ fun setMaxFps(fps: Float) {
173
+ maxFps = if (fps <= 0f || fps > 60f) 60f else fps
174
+ mapView.mapWindow.setMaxFps(maxFps)
175
+ }
176
+
177
+ fun setMapType(type: String?) {
178
+ mapType = type ?: "map"
179
+ mapView.mapWindow.map.mapType =
180
+ when (mapType) {
181
+ "satellite" -> MapType.SATELLITE
182
+ "hybrid" -> MapType.HYBRID
183
+ else -> MapType.MAP
184
+ }
185
+ }
186
+
187
+ fun setLogoPosition(position: Map<String, Any>) {
188
+ var horizontalAlignment = HorizontalAlignment.RIGHT
189
+ var verticalAlignment = VerticalAlignment.BOTTOM
190
+
191
+ if (position.containsKey("horizontal")) {
192
+ when (position.get("horizontal")) {
193
+ "left" -> horizontalAlignment = HorizontalAlignment.LEFT
194
+ "center" -> horizontalAlignment = HorizontalAlignment.CENTER
195
+ else -> {}
196
+ }
197
+ }
198
+
199
+ if (position.containsKey("vertical")) {
200
+ when (position.get("vertical")) {
201
+ "top" -> verticalAlignment = VerticalAlignment.TOP
202
+ "bottom" -> verticalAlignment = VerticalAlignment.BOTTOM
203
+ else -> {}
204
+ }
205
+ }
206
+
207
+ mapView.getMapWindow().map.logo.setAlignment(Alignment(horizontalAlignment, verticalAlignment))
208
+ }
209
+
210
+ fun setLogoPadding(horizontalPadding: Int, verticalPadding: Int) {
211
+ mapView.getMapWindow().map.logo.setPadding(Padding(horizontalPadding, verticalPadding))
212
+ }
213
+
214
+ fun getCameraPosition(): WritableMap? {
215
+ try {
216
+ val map = mapView.mapWindow.map
217
+ val cameraPosition = map.cameraPosition
218
+ val result = Arguments.createMap()
219
+ result.putDouble("lat", cameraPosition.target.latitude)
220
+ result.putDouble("lon", cameraPosition.target.longitude)
221
+ result.putDouble("zoom", cameraPosition.zoom.toDouble())
222
+ result.putDouble("azimuth", cameraPosition.azimuth.toDouble())
223
+ result.putDouble("tilt", cameraPosition.tilt.toDouble())
224
+ return result
225
+ } catch (e: Exception) {
226
+ Log.e("YamapLiteView", "Failed to get camera position", e)
227
+ return null
228
+ }
229
+ }
230
+
231
+ private fun moveCamera(cameraPosition: CameraPosition, duration: Int, animation: String) {
232
+ val map = mapView.mapWindow.map
233
+ if (duration > 0) {
234
+ val animType = if (animation == "LINEAR") Animation.Type.LINEAR else Animation.Type.SMOOTH
235
+ map.move(cameraPosition, Animation(animType, duration.toFloat() / 1000.0f), null)
236
+ } else {
237
+ map.move(cameraPosition)
238
+ }
239
+ }
240
+
241
+ fun setCenter(
242
+ latitude: Double,
243
+ longitude: Double,
244
+ zoom: Float,
245
+ azimuth: Float,
246
+ tilt: Float,
247
+ duration: Int,
248
+ animation: String
249
+ ) {
250
+ try {
251
+ val point = Point(latitude, longitude)
252
+ moveCamera(CameraPosition(point, zoom, azimuth, tilt), duration, animation)
253
+ } catch (e: Exception) {
254
+ Log.e("YamapLiteView", "Failed to set center", e)
255
+ }
256
+ }
257
+
258
+ fun setZoom(zoom: Float, duration: Int, animation: String) {
259
+ try {
260
+ val currentPosition = mapView.mapWindow.map.cameraPosition
261
+ val cameraPosition =
262
+ CameraPosition(
263
+ currentPosition.target,
264
+ zoom,
265
+ currentPosition.azimuth,
266
+ currentPosition.tilt
267
+ )
268
+ moveCamera(cameraPosition, duration, animation)
269
+ } catch (e: Exception) {
270
+ Log.e("YamapLiteView", "Failed to set zoom", e)
271
+ }
272
+ }
273
+
274
+ fun fitAllMarkers() {
275
+ try {
276
+ val map = mapView.mapWindow.map
277
+ val markerPoints = mutableListOf<Point>()
278
+
279
+ for (i in 0 until reactChildren.size) {
280
+ val child = reactChildren[i]
281
+ if (child is YamapLiteMarkerView) {
282
+ markerPoints.add(Point(child.latitude, child.longitude))
283
+ }
284
+ }
285
+
286
+ if (markerPoints.size == 0) {
287
+ return
288
+ }
289
+
290
+ val boundingBox = calculateBoundingBox(ArrayList(markerPoints))
291
+ val geometry = Geometry.fromBoundingBox(boundingBox)
292
+ val cameraPosition = map.cameraPosition(geometry)
293
+ map.move(cameraPosition, Animation(Animation.Type.SMOOTH, 0.7f), null)
294
+ } catch (e: Exception) {
295
+ Log.e("YamapLiteView", "Failed to fit all markers", e)
296
+ }
297
+ }
298
+
299
+ fun setFollowUser(follow: Boolean) {
300
+ if (userLocationLayer == null) {
301
+ setShowUserPosition(true)
302
+ }
303
+
304
+ if (follow) {
305
+ userLocationLayer!!.isAutoZoomEnabled = true
306
+ userLocationLayer!!.setAnchor(
307
+ PointF((width * 0.5).toFloat(), (height * 0.5).toFloat()),
308
+ PointF((width * 0.5).toFloat(), (height * 0.83).toFloat())
309
+ )
310
+ } else {
311
+ userLocationLayer!!.isAutoZoomEnabled = false
312
+ userLocationLayer!!.resetAnchor()
313
+ }
314
+ }
315
+
316
+ fun setUserLocationAccuracyFillColor(color: String?) {
317
+ userLocationAccuracyFillColor = color ?: "#00FF00"
318
+ }
319
+
320
+ fun setUserLocationAccuracyStrokeColor(color: String?) {
321
+ userLocationAccuracyStrokeColor = color ?: "#000000"
322
+ }
323
+
324
+ fun setUserLocationAccuracyStrokeWidth(width: Float) {
325
+ userLocationAccuracyStrokeWidth = width
326
+ }
327
+
328
+ private fun calculateBoundingBox(points: ArrayList<Point?>): BoundingBox {
329
+ var minLat = Double.MAX_VALUE
330
+ var maxLat = -Double.MAX_VALUE
331
+ var minLon = Double.MAX_VALUE
332
+ var maxLon = -Double.MAX_VALUE
333
+
334
+ for (point in points) {
335
+ if (point != null) {
336
+ minLat = minOf(minLat, point.latitude)
337
+ maxLat = maxOf(maxLat, point.latitude)
338
+ minLon = minOf(minLon, point.longitude)
339
+ maxLon = maxOf(maxLon, point.longitude)
340
+ }
341
+ }
342
+
343
+ return BoundingBox(Point(minLat, minLon), Point(maxLat, maxLon))
344
+ }
345
+
346
+ protected fun addReactChildToList(child: View, index: Int) {
347
+ if (index < 0 || index > reactChildren.size) {
348
+ reactChildren.add(child)
349
+ } else {
350
+ reactChildren.add(index, child)
351
+ }
352
+ }
353
+
354
+ protected fun removeReactChildFromListAt(index: Int): View? {
355
+ if (index < 0 || index >= reactChildren.size) return null
356
+ return reactChildren.removeAt(index)
357
+ }
358
+
359
+ fun addReactChild(child: View, index: Int) {
360
+ addReactChildToList(child, index)
361
+ if (child is YamapLiteMarkerView) {
362
+ child.addToMap(mapView)
363
+ } else if (child is YamapCircle) {
364
+ child.addToMap(mapView)
365
+ } else if (child is YamapPolyline) {
366
+ child.addToMap(mapView)
367
+ } else if (child is YamapPolygon) {
368
+ child.addToMap(mapView)
369
+ }
370
+ }
371
+
372
+ fun removeReactChildAt(index: Int) {
373
+ val child = removeReactChildFromListAt(index) ?: return
374
+ if (child is YamapLiteMarkerView) {
375
+ child.removeFromMap(mapView)
376
+ } else if (child is YamapCircle) {
377
+ child.removeFromMap(mapView)
378
+ } else if (child is YamapPolyline) {
379
+ child.removeFromMap(mapView)
380
+ } else if (child is YamapPolygon) {
381
+ child.removeFromMap(mapView)
382
+ }
383
+ }
384
+
385
+ open fun onDropViewInstance() {
386
+ coroutineScope.cancel()
387
+ }
388
+
389
+ fun getReactChildAt(index: Int): View? {
390
+ if (index < 0 || index >= reactChildren.size) {
391
+ return null
392
+ }
393
+ return reactChildren[index]
394
+ }
395
+
396
+ fun getReactChildCount(): Int {
397
+ return reactChildren.size
398
+ }
399
+
400
+ fun getMapObjectCount(): Int {
401
+ val visitor = MapObjectCountVisitor()
402
+ mapView.mapWindow.map.mapObjects.traverse(visitor)
403
+ return visitor.count
404
+ }
405
+
406
+ override fun onAttachedToWindow() {
407
+ super.onAttachedToWindow()
408
+ try {
409
+ MapKitFactory.getInstance().onStart()
410
+ } catch (e: Exception) {
411
+ e.printStackTrace()
412
+ }
413
+ mapView.onStart()
414
+ }
415
+
416
+ override fun onDetachedFromWindow() {
417
+ super.onDetachedFromWindow()
418
+ mapView.onStop()
419
+ try {
420
+ MapKitFactory.getInstance().onStop()
421
+ } catch (e: Exception) {
422
+ e.printStackTrace()
423
+ }
424
+ }
425
+
426
+ override fun onMapLoaded(statistics: MapLoadStatistics) {
427
+ val reactContext = context as? ReactContext
428
+ if (reactContext == null) {
429
+ return
430
+ }
431
+
432
+ val viewId = getId()
433
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
434
+ val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, viewId)
435
+ if (eventDispatcher != null) {
436
+ eventDispatcher.dispatchEvent(MapLoadEvent(surfaceId, viewId, statistics))
437
+ }
438
+ }
439
+
440
+ override fun onCameraPositionChanged(
441
+ map: YMap,
442
+ cameraPosition: CameraPosition,
443
+ reason: CameraUpdateReason,
444
+ finished: Boolean
445
+ ) {
446
+ val reactContext = context as? ReactContext
447
+ if (reactContext == null) {
448
+ return
449
+ }
450
+
451
+ val viewId = getId()
452
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
453
+
454
+ val handler = Handler(Looper.getMainLooper())
455
+ handler.post {
456
+ val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, viewId)
457
+ if (eventDispatcher != null) {
458
+ try {
459
+ eventDispatcher.dispatchEvent(
460
+ CameraPositionChangeEvent(
461
+ surfaceId,
462
+ viewId,
463
+ "onCameraPositionChange",
464
+ cameraPosition,
465
+ reason,
466
+ finished,
467
+ )
468
+ )
469
+ } catch (e: Exception) {
470
+ Log.e("YamapLiteView", "Error dispatching CameraPositionChangeEvent event", e)
471
+ }
472
+
473
+ if (finished) {
474
+ try {
475
+ eventDispatcher.dispatchEvent(
476
+ CameraPositionChangeEvent(
477
+ surfaceId,
478
+ viewId,
479
+ "onCameraPositionChangeEnd",
480
+ cameraPosition,
481
+ reason,
482
+ finished,
483
+ )
484
+ )
485
+ } catch (e: Exception) {
486
+ Log.e("YamapLiteView", "Error dispatching CameraPositionChangeEndEvent event", e)
487
+ }
488
+ }
489
+ }
490
+ }
491
+ }
492
+
493
+ override fun onMapTap(map: YMap, point: Point) {
494
+ val reactContext = context as? ReactContext
495
+ if (reactContext == null) {
496
+ return
497
+ }
498
+ val viewId = getId()
499
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
500
+ val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, viewId)
501
+ if (eventDispatcher != null) {
502
+ eventDispatcher.dispatchEvent(PressEvent(surfaceId, viewId, "onMapPress", point))
503
+ }
504
+ }
505
+
506
+ override fun onMapLongTap(map: YMap, point: Point) {
507
+ val reactContext = context as? ReactContext
508
+ if (reactContext == null) {
509
+ return
510
+ }
511
+ val viewId = getId()
512
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
513
+ val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, viewId)
514
+ if (eventDispatcher != null) {
515
+ eventDispatcher.dispatchEvent(PressEvent(surfaceId, viewId, "onMapLongPress", point))
516
+ }
517
+ }
518
+
519
+ private fun updateUserLocationIcon() {
520
+ if (userLocationView == null || userLocationIcon == null) {
521
+ return
522
+ }
523
+
524
+ val userIconStyle = IconStyle()
525
+ userIconStyle.setScale(userLocationIconScale)
526
+
527
+ val pin = userLocationView!!.pin
528
+ val arrow = userLocationView!!.arrow
529
+ coroutineScope.launch {
530
+ val icon = ResolveImageHelper.getInstance().resolveImage(context, userLocationIcon!!, 50)
531
+ icon?.let {
532
+ pin.setIcon(it, userIconStyle)
533
+ arrow.setIcon(it, userIconStyle)
534
+ }
535
+ }
536
+ val circle = userLocationView!!.accuracyCircle
537
+ if (userLocationAccuracyFillColor != null) {
538
+ circle.fillColor = Color.parseColor(userLocationAccuracyFillColor)
539
+ }
540
+ if (userLocationAccuracyStrokeColor != null) {
541
+ circle.strokeColor = Color.parseColor(userLocationAccuracyStrokeColor)
542
+ }
543
+ circle.strokeWidth = userLocationAccuracyStrokeWidth
544
+ }
545
+
546
+ fun fitMarkers(points: ArrayList<Point?>) {
547
+ if (points.size == 0) {
548
+ return
549
+ }
550
+ if (points.size == 1) {
551
+ val center = Point(points[0]!!.latitude, points[0]!!.longitude)
552
+ mapView.getMapWindow().map.move(CameraPosition(center, 15f, 0f, 0f))
553
+ return
554
+ }
555
+ var cameraPosition =
556
+ mapView.getMapWindow()
557
+ .map
558
+ .cameraPosition(Geometry.fromBoundingBox(calculateBoundingBox(points)))
559
+ cameraPosition =
560
+ CameraPosition(
561
+ cameraPosition.target,
562
+ cameraPosition.zoom - 0.8f,
563
+ cameraPosition.azimuth,
564
+ cameraPosition.tilt
565
+ )
566
+ mapView.getMapWindow().map.move(cameraPosition, Animation(Animation.Type.SMOOTH, 0.7f), null)
567
+ }
568
+
569
+ fun getVisibleRegion(): WritableMap? {
570
+ val map = mapView.mapWindow.map
571
+ val visibleRegion = map.visibleRegion
572
+ val result = Arguments.createMap()
573
+ result.putMap(
574
+ "bottomLeft",
575
+ Arguments.createMap().apply {
576
+ putDouble("lat", visibleRegion.bottomLeft.latitude)
577
+ putDouble("lon", visibleRegion.bottomLeft.longitude)
578
+ }
579
+ )
580
+ result.putMap(
581
+ "topLeft",
582
+ Arguments.createMap().apply {
583
+ putDouble("lat", visibleRegion.topLeft.latitude)
584
+ putDouble("lon", visibleRegion.topLeft.longitude)
585
+ }
586
+ )
587
+ result.putMap(
588
+ "topRight",
589
+ Arguments.createMap().apply {
590
+ putDouble("lat", visibleRegion.topRight.latitude)
591
+ putDouble("lon", visibleRegion.topRight.longitude)
592
+ }
593
+ )
594
+ result.putMap(
595
+ "bottomRight",
596
+ Arguments.createMap().apply {
597
+ putDouble("lat", visibleRegion.bottomRight.latitude)
598
+ putDouble("lon", visibleRegion.bottomRight.longitude)
599
+ }
600
+ )
601
+ return result
602
+ }
603
+
604
+ fun getScreenPoints(points: List<Point>): WritableArray {
605
+ val result = Arguments.createArray()
606
+ for (point in points) {
607
+ val screenPoint = mapView.mapWindow.worldToScreen(point) ?: continue
608
+ result.pushMap(
609
+ Arguments.createMap().apply {
610
+ putDouble("x", screenPoint.x.toDouble())
611
+ putDouble("y", screenPoint.y.toDouble())
612
+ }
613
+ )
614
+ }
615
+ return result
616
+ }
617
+
618
+ fun getWorldPoints(points: ArrayList<ScreenPoint?>): WritableArray {
619
+ val result = Arguments.createArray()
620
+ for (screenPoint in points) {
621
+ if (screenPoint == null) continue
622
+ val worldPoint = mapView.mapWindow.screenToWorld(screenPoint) ?: continue
623
+ result.pushMap(
624
+ Arguments.createMap().apply {
625
+ putDouble("lat", worldPoint.latitude)
626
+ putDouble("lon", worldPoint.longitude)
627
+ }
628
+ )
629
+ }
630
+ return result
631
+ }
632
+
633
+ override fun onObjectAdded(_userLocationView: UserLocationView) {
634
+ userLocationView = _userLocationView
635
+ updateUserLocationIcon()
636
+ }
637
+
638
+ override fun onObjectRemoved(userLocationView: UserLocationView) {}
639
+
640
+ override fun onObjectUpdated(_userLocationView: UserLocationView, objectEvent: ObjectEvent) {
641
+ userLocationView = _userLocationView
642
+ updateUserLocationIcon()
643
+ }
644
+
645
+ private class MapObjectCountVisitor : MapObjectVisitor {
646
+ var count = 0
647
+
648
+ override fun onPlacemarkVisited(placemark: PlacemarkMapObject) {
649
+ count++
650
+ }
651
+
652
+ override fun onPolylineVisited(polyline: PolylineMapObject) {
653
+ count++
654
+ }
655
+
656
+ override fun onPolygonVisited(polygon: PolygonMapObject) {
657
+ count++
658
+ }
659
+
660
+ override fun onCircleVisited(circle: CircleMapObject) {
661
+ count++
662
+ }
663
+
664
+ override fun onCollectionVisitStart(collection: MapObjectCollection): Boolean {
665
+ return true
666
+ }
667
+
668
+ override fun onCollectionVisitEnd(collection: MapObjectCollection) {}
669
+
670
+ override fun onClusterizedCollectionVisitStart(
671
+ collection: ClusterizedPlacemarkCollection
672
+ ): Boolean {
673
+ return true
674
+ }
675
+
676
+ override fun onClusterizedCollectionVisitEnd(collection: ClusterizedPlacemarkCollection) {}
677
+ }
678
+ }
@@ -0,0 +1,38 @@
1
+ package com.yamaplite.events
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+ import com.yandex.mapkit.map.CameraPosition
7
+ import com.yandex.mapkit.map.CameraUpdateReason
8
+
9
+ class CameraPositionChangeEvent(
10
+ surfaceId: Int,
11
+ viewTag: Int,
12
+ private val eventName: String,
13
+ private val cameraPosition: CameraPosition,
14
+ private val reason: CameraUpdateReason,
15
+ private val finished: Boolean,
16
+ ) : Event<CameraPositionChangeEvent>(surfaceId, viewTag) {
17
+
18
+ override fun getEventName(): String = eventName
19
+
20
+ override fun getEventData(): WritableMap =
21
+ Arguments.createMap().apply {
22
+ putMap(
23
+ "point",
24
+ Arguments.createMap().apply {
25
+ putDouble("lat", cameraPosition.target.latitude)
26
+ putDouble("lon", cameraPosition.target.longitude)
27
+ },
28
+ )
29
+ putDouble("zoom", cameraPosition.zoom.toDouble())
30
+ putDouble("azimuth", cameraPosition.azimuth.toDouble())
31
+ putDouble("tilt", cameraPosition.tilt.toDouble())
32
+ putBoolean("finished", finished)
33
+ putDouble("target", 0.0)
34
+ putString("reason", reason.toString())
35
+ }
36
+
37
+ override fun getCoalescingKey(): Short = 0
38
+ }