@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.
- package/README.md +17 -4
- package/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +31 -37
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +6 -5
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +136 -14
- package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +21 -0
- package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
- package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
- package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +157 -52
- package/ios/LuggAppleMapView.mm +154 -42
- package/ios/LuggGoogleMapView.mm +52 -22
- package/ios/LuggMarkerView.h +9 -0
- package/ios/LuggMarkerView.mm +79 -0
- package/ios/LuggPolylineView.h +4 -0
- package/ios/LuggPolylineView.mm +23 -0
- package/ios/core/GMSPolylineAnimator.h +3 -0
- package/ios/core/GMSPolylineAnimator.m +164 -41
- package/ios/core/MKPolylineAnimator.h +4 -0
- package/ios/core/MKPolylineAnimator.m +162 -43
- package/ios/core/PolylineAnimatorBase.h +14 -0
- package/ios/core/PolylineAnimatorBase.m +33 -0
- package/ios/extensions/MKMapView+Zoom.h +2 -0
- package/ios/extensions/MKMapView+Zoom.m +14 -4
- package/lib/module/MapProvider.js +13 -0
- package/lib/module/MapProvider.js.map +1 -0
- package/lib/module/MapProvider.types.js +4 -0
- package/lib/module/MapProvider.types.js.map +1 -0
- package/lib/module/MapProvider.web.js +20 -0
- package/lib/module/MapProvider.web.js.map +1 -0
- package/lib/module/MapView.js +2 -2
- package/lib/module/MapView.js.map +1 -1
- package/lib/module/MapView.web.js +272 -0
- package/lib/module/MapView.web.js.map +1 -0
- package/lib/module/components/Marker.js +10 -1
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.web.js +33 -0
- package/lib/module/components/Marker.web.js.map +1 -0
- package/lib/module/components/Polyline.js +8 -3
- package/lib/module/components/Polyline.js.map +1 -1
- package/lib/module/components/Polyline.web.js +229 -0
- package/lib/module/components/Polyline.web.js.map +1 -0
- package/lib/module/components/index.js +2 -2
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/index.web.js +5 -0
- package/lib/module/components/index.web.js.map +1 -0
- package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +7 -1
- package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
- package/lib/module/index.js +3 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +6 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/typescript/src/MapProvider.d.ts +8 -0
- package/lib/typescript/src/MapProvider.d.ts.map +1 -0
- package/lib/typescript/src/MapProvider.types.d.ts +16 -0
- package/lib/typescript/src/MapProvider.types.d.ts.map +1 -0
- package/lib/typescript/src/MapProvider.web.d.ts +11 -0
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -0
- package/lib/typescript/src/MapView.d.ts +1 -1
- package/lib/typescript/src/MapView.d.ts.map +1 -1
- package/lib/typescript/src/MapView.types.d.ts +2 -2
- package/lib/typescript/src/MapView.types.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts +3 -0
- package/lib/typescript/src/MapView.web.d.ts.map +1 -0
- package/lib/typescript/src/components/Marker.d.ts +21 -0
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts +3 -0
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -0
- package/lib/typescript/src/components/Polyline.d.ts +32 -0
- package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
- package/lib/typescript/src/components/Polyline.web.d.ts +3 -0
- package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -0
- package/lib/typescript/src/components/index.web.d.ts +5 -0
- package/lib/typescript/src/components/index.web.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +4 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
- package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +7 -0
- package/lib/typescript/src/index.web.d.ts.map +1 -0
- package/package.json +15 -2
- package/src/MapProvider.tsx +10 -0
- package/src/MapProvider.types.ts +16 -0
- package/src/MapProvider.web.tsx +14 -0
- package/src/MapView.tsx +2 -2
- package/src/MapView.types.ts +2 -2
- package/src/MapView.web.tsx +337 -0
- package/src/components/Marker.tsx +37 -3
- package/src/components/Marker.web.tsx +33 -0
- package/src/components/Polyline.tsx +38 -1
- package/src/components/Polyline.web.tsx +287 -0
- package/src/components/index.web.ts +4 -0
- package/src/fabric/LuggMarkerViewNativeComponent.ts +7 -1
- package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
- package/src/index.ts +8 -1
- package/src/index.web.ts +17 -0
package/README.md
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
# @lugg/maps
|
|
2
2
|
|
|
3
|
-
|
|
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 =
|
|
59
|
-
private val pendingPolylineViews =
|
|
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
|
-
|
|
243
|
-
pendingMarkerViews.add(markerView)
|
|
244
|
-
}
|
|
242
|
+
pendingMarkerViews.add(markerView)
|
|
245
243
|
return
|
|
246
244
|
}
|
|
247
245
|
|
|
248
246
|
if (markerView.hasCustomView) {
|
|
249
|
-
|
|
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
|
-
|
|
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
|
-
|
|
286
|
-
|
|
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, "
|
|
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
|
-
|
|
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, "
|
|
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
|
|
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
|
|
30
|
-
val
|
|
30
|
+
val w = right - left
|
|
31
|
+
val h = bottom - top
|
|
31
32
|
getChildAt(0)?.let {
|
|
32
33
|
it.measure(
|
|
33
|
-
MeasureSpec.makeMeasureSpec(
|
|
34
|
-
MeasureSpec.makeMeasureSpec(
|
|
34
|
+
MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
|
|
35
|
+
MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)
|
|
35
36
|
)
|
|
36
|
-
it.layout(0, 0,
|
|
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.
|
|
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 =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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
|
}
|