@lugg/maps 0.2.0-alpha.2 → 0.2.0-alpha.20

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 (96) hide show
  1. package/README.md +17 -4
  2. package/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +31 -37
  3. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +6 -5
  4. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +136 -14
  5. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +21 -0
  6. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
  7. package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
  8. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +157 -52
  9. package/ios/LuggAppleMapView.mm +154 -42
  10. package/ios/LuggGoogleMapView.mm +52 -22
  11. package/ios/LuggMarkerView.h +9 -0
  12. package/ios/LuggMarkerView.mm +79 -0
  13. package/ios/LuggPolylineView.h +4 -0
  14. package/ios/LuggPolylineView.mm +23 -0
  15. package/ios/core/GMSPolylineAnimator.h +3 -0
  16. package/ios/core/GMSPolylineAnimator.m +164 -41
  17. package/ios/core/MKPolylineAnimator.h +4 -0
  18. package/ios/core/MKPolylineAnimator.m +162 -43
  19. package/ios/core/PolylineAnimatorBase.h +14 -0
  20. package/ios/core/PolylineAnimatorBase.m +33 -0
  21. package/ios/extensions/MKMapView+Zoom.h +2 -0
  22. package/ios/extensions/MKMapView+Zoom.m +14 -4
  23. package/lib/module/MapProvider.js +13 -0
  24. package/lib/module/MapProvider.js.map +1 -0
  25. package/lib/module/MapProvider.types.js +4 -0
  26. package/lib/module/MapProvider.types.js.map +1 -0
  27. package/lib/module/MapProvider.web.js +20 -0
  28. package/lib/module/MapProvider.web.js.map +1 -0
  29. package/lib/module/MapView.js +2 -2
  30. package/lib/module/MapView.js.map +1 -1
  31. package/lib/module/MapView.web.js +272 -0
  32. package/lib/module/MapView.web.js.map +1 -0
  33. package/lib/module/components/Marker.js +10 -1
  34. package/lib/module/components/Marker.js.map +1 -1
  35. package/lib/module/components/Marker.web.js +33 -0
  36. package/lib/module/components/Marker.web.js.map +1 -0
  37. package/lib/module/components/Polyline.js +8 -3
  38. package/lib/module/components/Polyline.js.map +1 -1
  39. package/lib/module/components/Polyline.web.js +229 -0
  40. package/lib/module/components/Polyline.web.js.map +1 -0
  41. package/lib/module/components/index.js +2 -2
  42. package/lib/module/components/index.js.map +1 -1
  43. package/lib/module/components/index.web.js +5 -0
  44. package/lib/module/components/index.web.js.map +1 -0
  45. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +7 -1
  46. package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  47. package/lib/module/index.js +3 -2
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/index.web.js +6 -0
  50. package/lib/module/index.web.js.map +1 -0
  51. package/lib/typescript/src/MapProvider.d.ts +8 -0
  52. package/lib/typescript/src/MapProvider.d.ts.map +1 -0
  53. package/lib/typescript/src/MapProvider.types.d.ts +16 -0
  54. package/lib/typescript/src/MapProvider.types.d.ts.map +1 -0
  55. package/lib/typescript/src/MapProvider.web.d.ts +11 -0
  56. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -0
  57. package/lib/typescript/src/MapView.d.ts +1 -1
  58. package/lib/typescript/src/MapView.d.ts.map +1 -1
  59. package/lib/typescript/src/MapView.types.d.ts +2 -2
  60. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  61. package/lib/typescript/src/MapView.web.d.ts +3 -0
  62. package/lib/typescript/src/MapView.web.d.ts.map +1 -0
  63. package/lib/typescript/src/components/Marker.d.ts +21 -0
  64. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  65. package/lib/typescript/src/components/Marker.web.d.ts +3 -0
  66. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -0
  67. package/lib/typescript/src/components/Polyline.d.ts +32 -0
  68. package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
  69. package/lib/typescript/src/components/Polyline.web.d.ts +3 -0
  70. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -0
  71. package/lib/typescript/src/components/index.web.d.ts +5 -0
  72. package/lib/typescript/src/components/index.web.d.ts.map +1 -0
  73. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +4 -1
  74. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  75. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
  76. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
  77. package/lib/typescript/src/index.d.ts +3 -1
  78. package/lib/typescript/src/index.d.ts.map +1 -1
  79. package/lib/typescript/src/index.web.d.ts +7 -0
  80. package/lib/typescript/src/index.web.d.ts.map +1 -0
  81. package/package.json +15 -2
  82. package/src/MapProvider.tsx +10 -0
  83. package/src/MapProvider.types.ts +16 -0
  84. package/src/MapProvider.web.tsx +14 -0
  85. package/src/MapView.tsx +2 -2
  86. package/src/MapView.types.ts +2 -2
  87. package/src/MapView.web.tsx +337 -0
  88. package/src/components/Marker.tsx +37 -3
  89. package/src/components/Marker.web.tsx +33 -0
  90. package/src/components/Polyline.tsx +38 -1
  91. package/src/components/Polyline.web.tsx +287 -0
  92. package/src/components/index.web.ts +4 -0
  93. package/src/fabric/LuggMarkerViewNativeComponent.ts +7 -1
  94. package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  95. package/src/index.ts +8 -1
  96. package/src/index.web.ts +17 -0
package/README.md CHANGED
@@ -1,9 +1,6 @@
1
1
  # @lugg/maps
2
2
 
3
- React Native Fabric maps library for iOS and Android.
4
-
5
- - Google Maps (iOS & Android)
6
- - Apple Maps (iOS only)
3
+ Universal maps for your React Native apps 📍
7
4
 
8
5
  ## Installation
9
6
 
@@ -56,6 +53,22 @@ Add your Google Maps API key to `AndroidManifest.xml`:
56
53
  </application>
57
54
  ```
58
55
 
56
+ ### Web
57
+
58
+ Wrap your app with `MapProvider` and pass your Google Maps API key:
59
+
60
+ ```tsx
61
+ import { MapProvider } from '@lugg/maps';
62
+
63
+ function App() {
64
+ return (
65
+ <MapProvider apiKey="YOUR_WEB_API_KEY">
66
+ {/* Your app */}
67
+ </MapProvider>
68
+ );
69
+ }
70
+ ```
71
+
59
72
  ## Usage
60
73
 
61
74
  ```tsx
@@ -1,7 +1,6 @@
1
1
  package com.luggmaps
2
2
 
3
3
  import android.annotation.SuppressLint
4
- import android.util.Log
5
4
  import android.view.View
6
5
  import android.view.ViewGroup
7
6
  import com.facebook.react.uimanager.PixelUtil.dpToPx
@@ -55,8 +54,8 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
55
54
  private var isMapReady = false
56
55
  private var isDragging = false
57
56
  private var mapId: String = DEMO_MAP_ID
58
- private val pendingMarkerViews = mutableListOf<LuggMarkerView>()
59
- private val pendingPolylineViews = mutableListOf<LuggPolylineView>()
57
+ private val pendingMarkerViews = mutableSetOf<LuggMarkerView>()
58
+ private val pendingPolylineViews = mutableSetOf<LuggPolylineView>()
60
59
  private val polylineAnimators = mutableMapOf<LuggPolylineView, PolylineAnimator>()
61
60
 
62
61
  // Initial camera settings
@@ -103,7 +102,6 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
103
102
  override fun removeViewAt(index: Int) {
104
103
  val view = getChildAt(index)
105
104
  if (view is LuggMarkerView) {
106
- Log.d(TAG, "removing markerView: ${view.name}")
107
105
  view.marker?.remove()
108
106
  view.marker = null
109
107
  } else if (view is LuggPolylineView) {
@@ -123,7 +121,6 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
123
121
  }
124
122
 
125
123
  fun onDropViewInstance() {
126
- Log.d(TAG, "dropping mapView instance")
127
124
  pendingMarkerViews.clear()
128
125
  pendingPolylineViews.clear()
129
126
  polylineAnimators.values.forEach { it.destroy() }
@@ -149,10 +146,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
149
146
  view.onCreate(null)
150
147
  view.onResume()
151
148
  view.getMapAsync(this)
152
- mapWrapperView?.addView(
153
- view,
154
- LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
155
- )
149
+ mapWrapperView?.addView(view)
156
150
  }
157
151
  }
158
152
 
@@ -179,6 +173,9 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
179
173
 
180
174
  override fun onCameraMoveStarted(reason: Int) {
181
175
  isDragging = reason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE
176
+ if (isDragging) {
177
+ polylineAnimators.values.forEach { it.pause() }
178
+ }
182
179
  }
183
180
 
184
181
  override fun onCameraMove() {
@@ -191,6 +188,9 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
191
188
  val map = googleMap ?: return
192
189
  val position = map.cameraPosition
193
190
  eventDelegate?.onCameraIdle(this, position.target.latitude, position.target.longitude, position.zoom, isDragging)
191
+ if (isDragging) {
192
+ polylineAnimators.values.forEach { it.resume() }
193
+ }
194
194
  isDragging = false
195
195
  }
196
196
 
@@ -239,16 +239,12 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
239
239
 
240
240
  override fun markerViewDidLayout(markerView: LuggMarkerView) {
241
241
  if (googleMap == null) {
242
- if (!pendingMarkerViews.contains(markerView)) {
243
- pendingMarkerViews.add(markerView)
244
- }
242
+ pendingMarkerViews.add(markerView)
245
243
  return
246
244
  }
247
245
 
248
246
  if (markerView.hasCustomView) {
249
- // Recreate marker with custom view
250
- markerView.marker?.remove()
251
- addMarkerViewToMap(markerView)
247
+ markerView.updateIcon { addMarkerViewToMap(markerView) }
252
248
  } else {
253
249
  syncMarkerView(markerView)
254
250
  }
@@ -264,9 +260,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
264
260
 
265
261
  private fun syncMarkerView(markerView: LuggMarkerView) {
266
262
  if (googleMap == null) {
267
- if (!pendingMarkerViews.contains(markerView)) {
268
- pendingMarkerViews.add(markerView)
269
- }
263
+ pendingMarkerViews.add(markerView)
270
264
  return
271
265
  }
272
266
 
@@ -282,46 +276,43 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
282
276
  title = markerView.title
283
277
  snippet = markerView.description
284
278
  setAnchor(markerView.anchorX, markerView.anchorY)
285
- if (!markerView.hasCustomView) {
286
- iconView = null
287
- }
279
+ zIndex = markerView.zIndex
280
+ rotation = markerView.rotate
281
+ }
282
+
283
+ if (markerView.hasCustomView && markerView.scaleChanged) {
284
+ markerView.applyScaleToMarker()
285
+ markerView.clearScaleChanged()
288
286
  }
289
287
  }
290
288
 
291
289
  private fun processPendingMarkers() {
292
290
  if (googleMap == null) return
293
291
 
294
- Log.d(TAG, "processing pending markers ${pendingMarkerViews.size}")
295
292
  pendingMarkerViews.forEach { addMarkerViewToMap(it) }
296
293
  pendingMarkerViews.clear()
297
294
  }
298
295
 
299
296
  private fun addMarkerViewToMap(markerView: LuggMarkerView) {
300
297
  val map = googleMap ?: run {
301
- RNLog.w(reactContext, "Lugg: addMarkerViewToMap called without a map")
298
+ RNLog.w(reactContext, "LuggMaps: addMarkerViewToMap called without a map")
302
299
  return
303
300
  }
304
301
 
305
302
  val position = LatLng(markerView.latitude, markerView.longitude)
306
- val iconView = markerView.iconView
307
-
308
- (iconView.parent as? ViewGroup)?.removeView(iconView)
309
303
 
310
304
  val options = AdvancedMarkerOptions()
311
305
  .position(position)
312
306
  .title(markerView.title)
313
307
  .snippet(markerView.description)
314
- .collisionBehavior(CollisionBehavior.REQUIRED)
315
-
316
- Log.d(TAG, "adding marker: ${markerView.name} customview: ${markerView.hasCustomView}")
317
- if (markerView.hasCustomView) {
318
- options.iconView(iconView)
319
- }
320
308
 
321
309
  val marker = map.addMarker(options) as AdvancedMarker
322
310
  marker.setAnchor(markerView.anchorX, markerView.anchorY)
311
+ marker.zIndex = markerView.zIndex
312
+ marker.rotation = markerView.rotate
323
313
 
324
314
  markerView.marker = marker
315
+ markerView.applyIconToMarker()
325
316
  }
326
317
 
327
318
  // endregion
@@ -330,9 +321,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
330
321
 
331
322
  private fun syncPolylineView(polylineView: LuggPolylineView) {
332
323
  if (googleMap == null) {
333
- if (!pendingPolylineViews.contains(polylineView)) {
334
- pendingPolylineViews.add(polylineView)
335
- }
324
+ pendingPolylineViews.add(polylineView)
336
325
  return
337
326
  }
338
327
 
@@ -342,11 +331,13 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
342
331
  }
343
332
 
344
333
  polylineView.polyline?.width = polylineView.strokeWidth.dpToPx()
334
+ polylineView.polyline?.zIndex = polylineView.zIndex
345
335
 
346
336
  polylineAnimators[polylineView]?.apply {
347
337
  coordinates = polylineView.coordinates
348
338
  strokeColors = polylineView.strokeColors
349
339
  strokeWidth = polylineView.strokeWidth.dpToPx()
340
+ animatedOptions = polylineView.animatedOptions
350
341
  animated = polylineView.animated
351
342
  update()
352
343
  }
@@ -364,6 +355,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
364
355
 
365
356
  val options = PolylineOptions()
366
357
  .width(polylineView.strokeWidth.dpToPx())
358
+ .zIndex(polylineView.zIndex)
367
359
 
368
360
  val polyline = map.addPolyline(options)
369
361
  polylineView.polyline = polyline
@@ -373,6 +365,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
373
365
  coordinates = polylineView.coordinates
374
366
  strokeColors = polylineView.strokeColors
375
367
  strokeWidth = polylineView.strokeWidth.dpToPx()
368
+ animatedOptions = polylineView.animatedOptions
376
369
  animated = polylineView.animated
377
370
  update()
378
371
  }
@@ -388,7 +381,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
388
381
  if (value.isNullOrEmpty()) return
389
382
 
390
383
  if (mapView != null) {
391
- RNLog.w(reactContext, "Lugg: mapId cannot be changed after map is initialized")
384
+ RNLog.w(reactContext, "LuggMaps: mapId cannot be changed after map is initialized")
392
385
  return
393
386
  }
394
387
 
@@ -458,7 +451,8 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
458
451
  fun moveCamera(latitude: Double, longitude: Double, zoom: Double, duration: Int) {
459
452
  val map = googleMap ?: return
460
453
  val position = LatLng(latitude, longitude)
461
- val cameraUpdate = CameraUpdateFactory.newLatLngZoom(position, zoom.toFloat())
454
+ val targetZoom = if (zoom > 0) zoom.toFloat() else map.cameraPosition.zoom
455
+ val cameraUpdate = CameraUpdateFactory.newLatLngZoom(position, targetZoom)
462
456
  when {
463
457
  duration < 0 -> map.animateCamera(cameraUpdate)
464
458
  duration > 0 -> map.animateCamera(cameraUpdate, duration, null)
@@ -1,6 +1,7 @@
1
1
  package com.luggmaps
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.util.Log
4
5
  import com.facebook.react.uimanager.ThemedReactContext
5
6
  import com.facebook.react.views.view.ReactViewGroup
6
7
 
@@ -26,14 +27,14 @@ class LuggMapWrapperView(context: ThemedReactContext) : ReactViewGroup(context)
26
27
  bottom: Int
27
28
  ) {
28
29
  super.onLayout(changed, left, top, right, bottom)
29
- val width = right - left
30
- val height = bottom - top
30
+ val w = right - left
31
+ val h = bottom - top
31
32
  getChildAt(0)?.let {
32
33
  it.measure(
33
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
34
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
34
+ MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
35
+ MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)
35
36
  )
36
- it.layout(0, 0, width, height)
37
+ it.layout(0, 0, w, h)
37
38
  }
38
39
  }
39
40
  }
@@ -1,11 +1,16 @@
1
1
  package com.luggmaps
2
2
 
3
3
  import android.content.Context
4
- import android.util.Log
4
+ import android.graphics.Bitmap
5
+ import android.graphics.Canvas
5
6
  import android.view.View
7
+ import android.view.ViewGroup
8
+ import androidx.core.graphics.createBitmap
6
9
  import androidx.core.view.isNotEmpty
7
10
  import com.facebook.react.views.view.ReactViewGroup
8
11
  import com.google.android.gms.maps.model.AdvancedMarker
12
+ import com.google.android.gms.maps.model.BitmapDescriptor
13
+ import com.google.android.gms.maps.model.BitmapDescriptorFactory
9
14
 
10
15
  interface LuggMarkerViewDelegate {
11
16
  fun markerViewDidUpdate(markerView: LuggMarkerView)
@@ -13,6 +18,8 @@ interface LuggMarkerViewDelegate {
13
18
  }
14
19
 
15
20
  class LuggMarkerView(context: Context) : ReactViewGroup(context) {
21
+ private var scaleUpdateRunnable: Runnable? = null
22
+
16
23
  var name: String? = null
17
24
  private set
18
25
 
@@ -34,23 +41,118 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
34
41
  var anchorY: Float = 1.0f
35
42
  private set
36
43
 
44
+ var zIndex: Float = 0f
45
+ private set
46
+
47
+ var rotate: Float = 0f
48
+ private set
49
+
50
+ var scale: Float = 1f
51
+ private set
52
+
53
+ var scaleChanged: Boolean = false
54
+ private set
55
+
56
+ var rasterize: Boolean = true
57
+ private set
58
+
37
59
  var didLayout: Boolean = false
38
60
  private set
39
61
 
40
62
  val hasCustomView: Boolean
41
63
  get() = iconView.isNotEmpty()
42
64
 
43
- val iconView: ReactViewGroup = object : ReactViewGroup(context) {
44
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
45
- var maxWidth = 0
46
- var maxHeight = 0
47
- for (i in 0 until childCount) {
48
- val child = getChildAt(i)
49
- if (child.width > maxWidth) maxWidth = child.width
50
- if (child.height > maxHeight) maxHeight = child.height
65
+ val iconView: ReactViewGroup = ReactViewGroup(context)
66
+
67
+ private fun measureIconViewBounds(): Pair<Int, Int> {
68
+ var maxWidth = 0
69
+ var maxHeight = 0
70
+ for (i in 0 until iconView.childCount) {
71
+ val child = iconView.getChildAt(i)
72
+ val childRight = child.left + child.width
73
+ val childBottom = child.top + child.height
74
+ if (childRight > maxWidth) maxWidth = childRight
75
+ if (childBottom > maxHeight) maxHeight = childBottom
76
+ }
77
+ return Pair(maxWidth, maxHeight)
78
+ }
79
+
80
+ private fun createIconBitmap(): BitmapDescriptor? {
81
+ val (width, height) = measureIconViewBounds()
82
+ if (width <= 0 || height <= 0) return null
83
+
84
+ val scaledWidth = (width * scale).toInt()
85
+ val scaledHeight = (height * scale).toInt()
86
+
87
+ val bitmap = createBitmap(scaledWidth, scaledHeight)
88
+ val canvas = Canvas(bitmap)
89
+ canvas.scale(scale, scale)
90
+ iconView.draw(canvas)
91
+ return BitmapDescriptorFactory.fromBitmap(bitmap)
92
+ }
93
+
94
+ private fun createIconViewWrapper(): View {
95
+ val (width, height) = measureIconViewBounds()
96
+ val scaledWidth = (width * scale).toInt()
97
+ val scaledHeight = (height * scale).toInt()
98
+
99
+ (iconView.parent as? ViewGroup)?.removeView(iconView)
100
+ iconView.scaleX = scale
101
+ iconView.scaleY = scale
102
+ iconView.pivotX = 0f
103
+ iconView.pivotY = 0f
104
+
105
+ return object : ReactViewGroup(context) {
106
+ init {
107
+ addView(iconView)
108
+ }
109
+
110
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
111
+ setMeasuredDimension(scaledWidth, scaledHeight)
112
+ }
113
+ }
114
+ }
115
+
116
+ fun applyIconToMarker() {
117
+ val m = marker ?: return
118
+ if (!hasCustomView) return
119
+
120
+ if (rasterize) {
121
+ createIconBitmap()?.let { m.setIcon(it) }
122
+ } else {
123
+ m.iconView = createIconViewWrapper()
124
+ }
125
+ }
126
+
127
+ fun applyScaleToMarker() {
128
+ val m = marker ?: return
129
+ if (!hasCustomView) return
130
+
131
+ scaleUpdateRunnable?.let { removeCallbacks(it) }
132
+ scaleUpdateRunnable = Runnable {
133
+ if (rasterize) {
134
+ createIconBitmap()?.let { m.setIcon(it) }
135
+ } else {
136
+ m.iconView = createIconViewWrapper()
51
137
  }
138
+ }
139
+ post(scaleUpdateRunnable)
140
+ }
52
141
 
53
- setMeasuredDimension(maxWidth, maxHeight)
142
+ fun updateIcon(onAddMarker: () -> Unit) {
143
+ if (!hasCustomView) return
144
+ if (rasterize) {
145
+ post {
146
+ if (marker == null) {
147
+ onAddMarker()
148
+ } else {
149
+ applyIconToMarker()
150
+ }
151
+ }
152
+ } else {
153
+ marker?.remove()
154
+ marker = null
155
+ post { onAddMarker() }
54
156
  }
55
157
  }
56
158
 
@@ -90,6 +192,7 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
90
192
  bottom: Int
91
193
  ) {
92
194
  super.onLayout(changed, left, top, right, bottom)
195
+
93
196
  if (changed && !didLayout) {
94
197
  didLayout = true
95
198
  delegate?.markerViewDidLayout(this)
@@ -114,6 +217,27 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
114
217
  anchorY = y.toFloat()
115
218
  }
116
219
 
220
+ fun setZIndex(zIndex: Float) {
221
+ this.zIndex = zIndex
222
+ }
223
+
224
+ fun setRotate(rotate: Float) {
225
+ this.rotate = rotate
226
+ }
227
+
228
+ fun setScale(scale: Float) {
229
+ scaleChanged = this.scale != scale
230
+ this.scale = scale
231
+ }
232
+
233
+ fun clearScaleChanged() {
234
+ scaleChanged = false
235
+ }
236
+
237
+ fun setRasterize(rasterize: Boolean) {
238
+ this.rasterize = rasterize
239
+ }
240
+
117
241
  fun setName(name: String?) {
118
242
  this.name = name
119
243
  }
@@ -123,12 +247,10 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
123
247
  }
124
248
 
125
249
  fun onDropViewInstance() {
250
+ scaleUpdateRunnable?.let { removeCallbacks(it) }
251
+ scaleUpdateRunnable = null
126
252
  didLayout = false
127
253
  delegate = null
128
254
  iconView.removeAllViews()
129
255
  }
130
-
131
- companion object {
132
- private const val TAG = "Lugg"
133
- }
134
256
  }
@@ -63,6 +63,27 @@ class LuggMarkerViewManager :
63
63
  }
64
64
  }
65
65
 
66
+ @ReactProp(name = "zIndex", defaultFloat = 0f)
67
+ override fun setZIndex(view: LuggMarkerView, zIndex: Float) {
68
+ super.setZIndex(view, zIndex)
69
+ view.setZIndex(zIndex)
70
+ }
71
+
72
+ @ReactProp(name = "rotate", defaultDouble = 0.0)
73
+ override fun setRotate(view: LuggMarkerView, value: Double) {
74
+ view.setRotate(value.toFloat())
75
+ }
76
+
77
+ @ReactProp(name = "scale", defaultDouble = 1.0)
78
+ override fun setScale(view: LuggMarkerView, value: Double) {
79
+ view.setScale(value.toFloat())
80
+ }
81
+
82
+ @ReactProp(name = "rasterize", defaultBoolean = true)
83
+ override fun setRasterize(view: LuggMarkerView, value: Boolean) {
84
+ view.setRasterize(value)
85
+ }
86
+
66
87
  companion object {
67
88
  const val NAME = "LuggMarkerView"
68
89
  }
@@ -12,6 +12,8 @@ interface LuggPolylineViewDelegate {
12
12
  fun polylineViewDidUpdate(polylineView: LuggPolylineView)
13
13
  }
14
14
 
15
+ data class AnimatedOptions(val duration: Long = 2150L, val easing: String = "linear", val trailLength: Float = 1f, val delay: Long = 0L)
16
+
15
17
  class LuggPolylineView(context: Context) : ReactViewGroup(context) {
16
18
  var coordinates: List<LatLng> = emptyList()
17
19
  private set
@@ -25,6 +27,12 @@ class LuggPolylineView(context: Context) : ReactViewGroup(context) {
25
27
  var animated: Boolean = false
26
28
  private set
27
29
 
30
+ var animatedOptions: AnimatedOptions = AnimatedOptions()
31
+ private set
32
+
33
+ var zIndex: Float = 0f
34
+ private set
35
+
28
36
  var cachedSpans: List<StyleSpan>? = null
29
37
  private set
30
38
 
@@ -55,6 +63,14 @@ class LuggPolylineView(context: Context) : ReactViewGroup(context) {
55
63
  animated = value
56
64
  }
57
65
 
66
+ fun setAnimatedOptions(options: AnimatedOptions) {
67
+ animatedOptions = options
68
+ }
69
+
70
+ fun setZIndex(value: Float) {
71
+ zIndex = value
72
+ }
73
+
58
74
  fun getOrCreateSpans(): List<StyleSpan> {
59
75
  cachedSpans?.let { return it }
60
76
 
@@ -1,6 +1,7 @@
1
1
  package com.luggmaps
2
2
 
3
3
  import com.facebook.react.bridge.ReadableArray
4
+ import com.facebook.react.bridge.ReadableMap
4
5
  import com.facebook.react.module.annotations.ReactModule
5
6
  import com.facebook.react.uimanager.ThemedReactContext
6
7
  import com.facebook.react.uimanager.ViewGroupManager
@@ -65,6 +66,27 @@ class LuggPolylineViewManager :
65
66
  view.setAnimated(value)
66
67
  }
67
68
 
69
+ @ReactProp(name = "animatedOptions")
70
+ override fun setAnimatedOptions(view: LuggPolylineView, value: ReadableMap?) {
71
+ val options = if (value != null) {
72
+ AnimatedOptions(
73
+ duration = if (value.hasKey("duration")) value.getDouble("duration").toLong() else 2150L,
74
+ easing = if (value.hasKey("easing")) value.getString("easing") ?: "linear" else "linear",
75
+ trailLength = if (value.hasKey("trailLength")) value.getDouble("trailLength").toFloat() else 1f,
76
+ delay = if (value.hasKey("delay")) value.getDouble("delay").toLong() else 0L
77
+ )
78
+ } else {
79
+ AnimatedOptions()
80
+ }
81
+ view.setAnimatedOptions(options)
82
+ }
83
+
84
+ @ReactProp(name = "zIndex", defaultFloat = 0f)
85
+ override fun setZIndex(view: LuggPolylineView, value: Float) {
86
+ super.setZIndex(view, value)
87
+ view.setZIndex(value)
88
+ }
89
+
68
90
  companion object {
69
91
  const val NAME = "LuggPolylineView"
70
92
  }