@lugg/maps 0.2.0-alpha.17 → 0.2.0-alpha.19
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/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +16 -17
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +1 -0
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +129 -13
- package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +15 -0
- package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +8 -0
- package/ios/LuggAppleMapView.mm +58 -25
- package/ios/LuggGoogleMapView.mm +43 -20
- package/ios/LuggMarkerView.h +7 -0
- package/ios/LuggMarkerView.mm +66 -0
- package/ios/core/GMSPolylineAnimator.h +2 -0
- package/ios/core/GMSPolylineAnimator.m +8 -0
- package/ios/core/MKPolylineAnimator.h +2 -0
- package/ios/core/MKPolylineAnimator.m +8 -0
- package/lib/module/MapProvider.web.js +5 -2
- package/lib/module/MapProvider.web.js.map +1 -1
- package/lib/module/MapView.web.js +14 -11
- package/lib/module/MapView.web.js.map +1 -1
- package/lib/module/components/Marker.js +6 -0
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.web.js +8 -0
- package/lib/module/components/Marker.web.js.map +1 -1
- package/lib/module/components/Polyline.web.js +15 -4
- package/lib/module/components/Polyline.web.js.map +1 -1
- package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +7 -1
- package/lib/typescript/src/MapProvider.web.d.ts +8 -2
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.d.ts +17 -0
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
- package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +4 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/MapProvider.web.tsx +5 -2
- package/src/MapView.web.tsx +11 -11
- package/src/components/Marker.tsx +32 -2
- package/src/components/Marker.web.tsx +9 -0
- package/src/components/Polyline.web.tsx +13 -4
- package/src/fabric/LuggMarkerViewNativeComponent.ts +7 -1
|
@@ -146,10 +146,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
|
|
|
146
146
|
view.onCreate(null)
|
|
147
147
|
view.onResume()
|
|
148
148
|
view.getMapAsync(this)
|
|
149
|
-
mapWrapperView?.addView(
|
|
150
|
-
view,
|
|
151
|
-
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
152
|
-
)
|
|
149
|
+
mapWrapperView?.addView(view)
|
|
153
150
|
}
|
|
154
151
|
}
|
|
155
152
|
|
|
@@ -176,6 +173,9 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
|
|
|
176
173
|
|
|
177
174
|
override fun onCameraMoveStarted(reason: Int) {
|
|
178
175
|
isDragging = reason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE
|
|
176
|
+
if (isDragging) {
|
|
177
|
+
polylineAnimators.values.forEach { it.pause() }
|
|
178
|
+
}
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
override fun onCameraMove() {
|
|
@@ -188,6 +188,9 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
|
|
|
188
188
|
val map = googleMap ?: return
|
|
189
189
|
val position = map.cameraPosition
|
|
190
190
|
eventDelegate?.onCameraIdle(this, position.target.latitude, position.target.longitude, position.zoom, isDragging)
|
|
191
|
+
if (isDragging) {
|
|
192
|
+
polylineAnimators.values.forEach { it.resume() }
|
|
193
|
+
}
|
|
191
194
|
isDragging = false
|
|
192
195
|
}
|
|
193
196
|
|
|
@@ -241,9 +244,7 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
|
|
|
241
244
|
}
|
|
242
245
|
|
|
243
246
|
if (markerView.hasCustomView) {
|
|
244
|
-
|
|
245
|
-
markerView.marker?.remove()
|
|
246
|
-
addMarkerViewToMap(markerView)
|
|
247
|
+
markerView.updateIcon { addMarkerViewToMap(markerView) }
|
|
247
248
|
} else {
|
|
248
249
|
syncMarkerView(markerView)
|
|
249
250
|
}
|
|
@@ -276,9 +277,12 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
|
|
|
276
277
|
snippet = markerView.description
|
|
277
278
|
setAnchor(markerView.anchorX, markerView.anchorY)
|
|
278
279
|
zIndex = markerView.zIndex
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
280
|
+
rotation = markerView.rotate
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (markerView.hasCustomView && markerView.scaleChanged) {
|
|
284
|
+
markerView.applyScaleToMarker()
|
|
285
|
+
markerView.clearScaleChanged()
|
|
282
286
|
}
|
|
283
287
|
}
|
|
284
288
|
|
|
@@ -296,24 +300,19 @@ class LuggGoogleMapView(private val reactContext: ThemedReactContext) :
|
|
|
296
300
|
}
|
|
297
301
|
|
|
298
302
|
val position = LatLng(markerView.latitude, markerView.longitude)
|
|
299
|
-
val iconView = markerView.iconView
|
|
300
|
-
|
|
301
|
-
(iconView.parent as? ViewGroup)?.removeView(iconView)
|
|
302
303
|
|
|
303
304
|
val options = AdvancedMarkerOptions()
|
|
304
305
|
.position(position)
|
|
305
306
|
.title(markerView.title)
|
|
306
307
|
.snippet(markerView.description)
|
|
307
308
|
|
|
308
|
-
if (markerView.hasCustomView) {
|
|
309
|
-
options.iconView(iconView)
|
|
310
|
-
}
|
|
311
|
-
|
|
312
309
|
val marker = map.addMarker(options) as AdvancedMarker
|
|
313
310
|
marker.setAnchor(markerView.anchorX, markerView.anchorY)
|
|
314
311
|
marker.zIndex = markerView.zIndex
|
|
312
|
+
marker.rotation = markerView.rotate
|
|
315
313
|
|
|
316
314
|
markerView.marker = marker
|
|
315
|
+
markerView.applyIconToMarker()
|
|
317
316
|
}
|
|
318
317
|
|
|
319
318
|
// endregion
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
package com.luggmaps
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.graphics.Canvas
|
|
4
6
|
import android.view.View
|
|
7
|
+
import android.view.ViewGroup
|
|
8
|
+
import androidx.core.graphics.createBitmap
|
|
5
9
|
import androidx.core.view.isNotEmpty
|
|
6
10
|
import com.facebook.react.views.view.ReactViewGroup
|
|
7
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
|
|
8
14
|
|
|
9
15
|
interface LuggMarkerViewDelegate {
|
|
10
16
|
fun markerViewDidUpdate(markerView: LuggMarkerView)
|
|
@@ -12,6 +18,8 @@ interface LuggMarkerViewDelegate {
|
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
class LuggMarkerView(context: Context) : ReactViewGroup(context) {
|
|
21
|
+
private var scaleUpdateRunnable: Runnable? = null
|
|
22
|
+
|
|
15
23
|
var name: String? = null
|
|
16
24
|
private set
|
|
17
25
|
|
|
@@ -36,23 +44,115 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
|
|
|
36
44
|
var zIndex: Float = 0f
|
|
37
45
|
private set
|
|
38
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
|
+
|
|
39
59
|
var didLayout: Boolean = false
|
|
40
60
|
private set
|
|
41
61
|
|
|
42
62
|
val hasCustomView: Boolean
|
|
43
63
|
get() = iconView.isNotEmpty()
|
|
44
64
|
|
|
45
|
-
val iconView: ReactViewGroup =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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()
|
|
53
137
|
}
|
|
138
|
+
}
|
|
139
|
+
post(scaleUpdateRunnable)
|
|
140
|
+
}
|
|
54
141
|
|
|
55
|
-
|
|
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() }
|
|
56
156
|
}
|
|
57
157
|
}
|
|
58
158
|
|
|
@@ -92,6 +192,7 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
|
|
|
92
192
|
bottom: Int
|
|
93
193
|
) {
|
|
94
194
|
super.onLayout(changed, left, top, right, bottom)
|
|
195
|
+
|
|
95
196
|
if (changed && !didLayout) {
|
|
96
197
|
didLayout = true
|
|
97
198
|
delegate?.markerViewDidLayout(this)
|
|
@@ -120,6 +221,23 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
|
|
|
120
221
|
this.zIndex = zIndex
|
|
121
222
|
}
|
|
122
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
|
+
|
|
123
241
|
fun setName(name: String?) {
|
|
124
242
|
this.name = name
|
|
125
243
|
}
|
|
@@ -129,12 +247,10 @@ class LuggMarkerView(context: Context) : ReactViewGroup(context) {
|
|
|
129
247
|
}
|
|
130
248
|
|
|
131
249
|
fun onDropViewInstance() {
|
|
250
|
+
scaleUpdateRunnable?.let { removeCallbacks(it) }
|
|
251
|
+
scaleUpdateRunnable = null
|
|
132
252
|
didLayout = false
|
|
133
253
|
delegate = null
|
|
134
254
|
iconView.removeAllViews()
|
|
135
255
|
}
|
|
136
|
-
|
|
137
|
-
companion object {
|
|
138
|
-
private const val TAG = "Lugg"
|
|
139
|
-
}
|
|
140
256
|
}
|
|
@@ -69,6 +69,21 @@ class LuggMarkerViewManager :
|
|
|
69
69
|
view.setZIndex(zIndex)
|
|
70
70
|
}
|
|
71
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
|
+
|
|
72
87
|
companion object {
|
|
73
88
|
const val NAME = "LuggMarkerView"
|
|
74
89
|
}
|
|
@@ -143,6 +143,14 @@ class PolylineAnimator {
|
|
|
143
143
|
animator = null
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
fun pause() {
|
|
147
|
+
animator?.pause()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fun resume() {
|
|
151
|
+
animator?.resume()
|
|
152
|
+
}
|
|
153
|
+
|
|
146
154
|
private fun updateAnimatedPolyline() {
|
|
147
155
|
val poly = polyline ?: return
|
|
148
156
|
if (coordinates.size < 2 || totalLength <= 0f) {
|
package/ios/LuggAppleMapView.mm
CHANGED
|
@@ -103,11 +103,13 @@ using namespace luggmaps::events;
|
|
|
103
103
|
(AppleMarkerAnnotation *)markerView.marker;
|
|
104
104
|
|
|
105
105
|
if (annotation) {
|
|
106
|
+
annotation.annotationView.transform = CGAffineTransformIdentity;
|
|
106
107
|
annotation.markerView = nil;
|
|
107
108
|
annotation.annotationView = nil;
|
|
108
109
|
[_mapView removeAnnotation:annotation];
|
|
109
110
|
markerView.marker = nil;
|
|
110
111
|
}
|
|
112
|
+
[markerView resetIconViewTransform];
|
|
111
113
|
} else if ([childComponentView isKindOfClass:[LuggPolylineView class]]) {
|
|
112
114
|
LuggPolylineView *polylineView = (LuggPolylineView *)childComponentView;
|
|
113
115
|
polylineView.delegate = nil;
|
|
@@ -256,6 +258,38 @@ using namespace luggmaps::events;
|
|
|
256
258
|
|
|
257
259
|
#pragma mark - Annotation Helpers
|
|
258
260
|
|
|
261
|
+
- (void)applyMarkerStyle:(LuggMarkerView *)markerView
|
|
262
|
+
annotationView:(MKAnnotationView *)annotationView {
|
|
263
|
+
annotationView.transform = CGAffineTransformIdentity;
|
|
264
|
+
|
|
265
|
+
UIView *iconView = markerView.iconView;
|
|
266
|
+
CGRect frame = iconView.frame;
|
|
267
|
+
if (frame.size.width <= 0 || frame.size.height <= 0)
|
|
268
|
+
return;
|
|
269
|
+
|
|
270
|
+
CGFloat scale = markerView.scale;
|
|
271
|
+
CGPoint anchor = markerView.anchor;
|
|
272
|
+
|
|
273
|
+
if (markerView.rasterize) {
|
|
274
|
+
annotationView.image = [markerView createScaledIconImage];
|
|
275
|
+
} else {
|
|
276
|
+
iconView.layer.anchorPoint = anchor;
|
|
277
|
+
iconView.transform = CGAffineTransformMakeScale(scale, scale);
|
|
278
|
+
iconView.frame =
|
|
279
|
+
CGRectMake(frame.size.width * (0.5 - anchor.x) * (scale - 1),
|
|
280
|
+
frame.size.height * (0.5 - anchor.y) * (scale - 1),
|
|
281
|
+
frame.size.width, frame.size.height);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
annotationView.bounds =
|
|
285
|
+
CGRectMake(0, 0, frame.size.width * scale, frame.size.height * scale);
|
|
286
|
+
annotationView.centerOffset =
|
|
287
|
+
CGPointMake(frame.size.width * scale * (anchor.x - 0.5),
|
|
288
|
+
-frame.size.height * scale * (anchor.y - 0.5));
|
|
289
|
+
annotationView.transform =
|
|
290
|
+
CGAffineTransformMakeRotation(markerView.rotate * M_PI / 180.0);
|
|
291
|
+
}
|
|
292
|
+
|
|
259
293
|
- (void)updateAnnotationViewFrame:(AppleMarkerAnnotation *)annotation {
|
|
260
294
|
MKAnnotationView *annotationView = annotation.annotationView;
|
|
261
295
|
LuggMarkerView *markerView = annotation.markerView;
|
|
@@ -264,16 +298,7 @@ using namespace luggmaps::events;
|
|
|
264
298
|
return;
|
|
265
299
|
}
|
|
266
300
|
|
|
267
|
-
|
|
268
|
-
CGRect frame = iconView.frame;
|
|
269
|
-
if (frame.size.width > 0 && frame.size.height > 0) {
|
|
270
|
-
annotationView.frame = frame;
|
|
271
|
-
|
|
272
|
-
CGPoint anchor = markerView.anchor;
|
|
273
|
-
annotationView.centerOffset =
|
|
274
|
-
CGPointMake(frame.size.width * (anchor.x - 0.5),
|
|
275
|
-
-frame.size.height * (anchor.y - 0.5));
|
|
276
|
-
}
|
|
301
|
+
[self applyMarkerStyle:markerView annotationView:annotationView];
|
|
277
302
|
}
|
|
278
303
|
|
|
279
304
|
#pragma mark - PolylineViewDelegate
|
|
@@ -427,6 +452,15 @@ using namespace luggmaps::events;
|
|
|
427
452
|
|
|
428
453
|
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
|
|
429
454
|
_isDragging = [self isUserInteracting:mapView];
|
|
455
|
+
if (_isDragging) {
|
|
456
|
+
for (UIView *subview in self.subviews) {
|
|
457
|
+
if ([subview isKindOfClass:[LuggPolylineView class]]) {
|
|
458
|
+
MKPolylineAnimator *renderer =
|
|
459
|
+
(MKPolylineAnimator *)((LuggPolylineView *)subview).renderer;
|
|
460
|
+
[renderer pause];
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
430
464
|
}
|
|
431
465
|
|
|
432
466
|
- (BOOL)isUserInteracting:(MKMapView *)mapView {
|
|
@@ -450,6 +484,15 @@ using namespace luggmaps::events;
|
|
|
450
484
|
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
|
|
451
485
|
BOOL wasDragging = _isDragging;
|
|
452
486
|
_isDragging = NO;
|
|
487
|
+
if (wasDragging) {
|
|
488
|
+
for (UIView *subview in self.subviews) {
|
|
489
|
+
if ([subview isKindOfClass:[LuggPolylineView class]]) {
|
|
490
|
+
MKPolylineAnimator *renderer =
|
|
491
|
+
(MKPolylineAnimator *)((LuggPolylineView *)subview).renderer;
|
|
492
|
+
[renderer resume];
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
453
496
|
CameraIdleEvent{mapView.centerCoordinate.latitude,
|
|
454
497
|
mapView.centerCoordinate.longitude, mapView.zoomLevel,
|
|
455
498
|
static_cast<bool>(wasDragging)}
|
|
@@ -477,23 +520,13 @@ using namespace luggmaps::events;
|
|
|
477
520
|
annotationView.layer.zPosition = markerView.zIndex;
|
|
478
521
|
annotationView.zPriority = markerView.zIndex;
|
|
479
522
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
// Set frame and centerOffset based on iconView
|
|
485
|
-
CGRect frame = iconView.frame;
|
|
486
|
-
if (frame.size.width > 0 && frame.size.height > 0) {
|
|
487
|
-
annotationView.frame =
|
|
488
|
-
CGRectMake(0, 0, frame.size.width, frame.size.height);
|
|
489
|
-
iconView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
|
|
490
|
-
|
|
491
|
-
CGPoint anchor = markerView.anchor;
|
|
492
|
-
annotationView.centerOffset =
|
|
493
|
-
CGPointMake(frame.size.width * (anchor.x - 0.5),
|
|
494
|
-
-frame.size.height * (anchor.y - 0.5));
|
|
523
|
+
if (!markerView.rasterize) {
|
|
524
|
+
UIView *iconView = markerView.iconView;
|
|
525
|
+
[iconView removeFromSuperview];
|
|
526
|
+
[annotationView addSubview:iconView];
|
|
495
527
|
}
|
|
496
528
|
|
|
529
|
+
[self applyMarkerStyle:markerView annotationView:annotationView];
|
|
497
530
|
markerAnnotation.annotationView = annotationView;
|
|
498
531
|
|
|
499
532
|
return annotationView;
|
package/ios/LuggGoogleMapView.mm
CHANGED
|
@@ -89,6 +89,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
89
89
|
marker.map = nil;
|
|
90
90
|
markerView.marker = nil;
|
|
91
91
|
}
|
|
92
|
+
[markerView resetIconViewTransform];
|
|
92
93
|
} else if ([childComponentView isKindOfClass:[LuggPolylineView class]]) {
|
|
93
94
|
LuggPolylineView *polylineView = (LuggPolylineView *)childComponentView;
|
|
94
95
|
[_polylineAnimators removeObjectForKey:polylineView];
|
|
@@ -189,6 +190,11 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
189
190
|
|
|
190
191
|
- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture {
|
|
191
192
|
_isDragging = gesture;
|
|
193
|
+
if (_isDragging) {
|
|
194
|
+
for (GMSPolylineAnimator *animator in _polylineAnimators.objectEnumerator) {
|
|
195
|
+
[animator pause];
|
|
196
|
+
}
|
|
197
|
+
}
|
|
192
198
|
}
|
|
193
199
|
|
|
194
200
|
- (void)mapView:(GMSMapView *)mapView
|
|
@@ -202,6 +208,11 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
202
208
|
idleAtCameraPosition:(GMSCameraPosition *)position {
|
|
203
209
|
BOOL wasDragging = _isDragging;
|
|
204
210
|
_isDragging = NO;
|
|
211
|
+
if (wasDragging) {
|
|
212
|
+
for (GMSPolylineAnimator *animator in _polylineAnimators.objectEnumerator) {
|
|
213
|
+
[animator resume];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
205
216
|
CameraIdleEvent{position.target.latitude, position.target.longitude,
|
|
206
217
|
position.zoom, static_cast<bool>(wasDragging)}
|
|
207
218
|
.emit<LuggGoogleMapViewEventEmitter>(_eventEmitter);
|
|
@@ -225,6 +236,35 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
225
236
|
|
|
226
237
|
#pragma mark - Marker Management
|
|
227
238
|
|
|
239
|
+
- (void)applyMarkerStyle:(LuggMarkerView *)markerView
|
|
240
|
+
marker:(GMSAdvancedMarker *)marker {
|
|
241
|
+
if (markerView.hasCustomView) {
|
|
242
|
+
if (markerView.rasterize) {
|
|
243
|
+
marker.iconView = nil;
|
|
244
|
+
marker.icon = [markerView createScaledIconImage];
|
|
245
|
+
marker.rotation = markerView.rotate;
|
|
246
|
+
} else {
|
|
247
|
+
UIView *iconView = markerView.iconView;
|
|
248
|
+
if (marker.iconView != iconView) {
|
|
249
|
+
[iconView removeFromSuperview];
|
|
250
|
+
marker.iconView = iconView;
|
|
251
|
+
}
|
|
252
|
+
CGFloat scale = markerView.scale;
|
|
253
|
+
CGFloat radians = markerView.rotate * M_PI / 180.0;
|
|
254
|
+
iconView.transform =
|
|
255
|
+
CGAffineTransformConcat(CGAffineTransformMakeScale(scale, scale),
|
|
256
|
+
CGAffineTransformMakeRotation(radians));
|
|
257
|
+
marker.rotation = 0;
|
|
258
|
+
}
|
|
259
|
+
marker.groundAnchor = markerView.anchor;
|
|
260
|
+
} else {
|
|
261
|
+
marker.iconView = nil;
|
|
262
|
+
marker.icon = nil;
|
|
263
|
+
marker.rotation = markerView.rotate;
|
|
264
|
+
marker.groundAnchor = CGPointMake(0.5, 1);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
228
268
|
- (void)syncMarkerView:(LuggMarkerView *)markerView caller:(NSString *)caller {
|
|
229
269
|
if (!_mapView) {
|
|
230
270
|
if (![_pendingMarkerViews containsObject:markerView]) {
|
|
@@ -243,17 +283,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
243
283
|
marker.title = markerView.title;
|
|
244
284
|
marker.snippet = markerView.markerDescription;
|
|
245
285
|
marker.zIndex = (int)markerView.zIndex;
|
|
246
|
-
|
|
247
|
-
UIView *iconView = markerView.iconView;
|
|
248
|
-
if (marker.iconView != iconView) {
|
|
249
|
-
[iconView removeFromSuperview];
|
|
250
|
-
marker.iconView = iconView;
|
|
251
|
-
}
|
|
252
|
-
marker.groundAnchor = markerView.anchor;
|
|
253
|
-
} else {
|
|
254
|
-
marker.iconView = nil;
|
|
255
|
-
marker.groundAnchor = CGPointMake(0.5, 1);
|
|
256
|
-
}
|
|
286
|
+
[self applyMarkerStyle:markerView marker:marker];
|
|
257
287
|
}
|
|
258
288
|
|
|
259
289
|
- (void)processPendingMarkers {
|
|
@@ -273,22 +303,15 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
273
303
|
return;
|
|
274
304
|
}
|
|
275
305
|
|
|
276
|
-
UIView *iconView = markerView.iconView;
|
|
277
|
-
[iconView removeFromSuperview];
|
|
278
|
-
|
|
279
306
|
GMSAdvancedMarker *marker = [[GMSAdvancedMarker alloc] init];
|
|
280
307
|
marker.position = markerView.coordinate;
|
|
281
308
|
marker.title = markerView.title;
|
|
282
309
|
marker.snippet = markerView.markerDescription;
|
|
310
|
+
marker.zIndex = (int)markerView.zIndex;
|
|
283
311
|
|
|
284
|
-
|
|
285
|
-
marker.iconView = iconView;
|
|
286
|
-
marker.groundAnchor = markerView.anchor;
|
|
287
|
-
}
|
|
312
|
+
[self applyMarkerStyle:markerView marker:marker];
|
|
288
313
|
|
|
289
|
-
marker.zIndex = (int)markerView.zIndex;
|
|
290
314
|
marker.map = _mapView;
|
|
291
|
-
|
|
292
315
|
markerView.marker = marker;
|
|
293
316
|
}
|
|
294
317
|
|
package/ios/LuggMarkerView.h
CHANGED
|
@@ -20,12 +20,19 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
20
20
|
@property(nonatomic, readonly, nullable) NSString *markerDescription;
|
|
21
21
|
@property(nonatomic, readonly) CGPoint anchor;
|
|
22
22
|
@property(nonatomic, readonly) NSInteger zIndex;
|
|
23
|
+
@property(nonatomic, readonly) CLLocationDegrees rotate;
|
|
24
|
+
@property(nonatomic, readonly) CGFloat scale;
|
|
25
|
+
@property(nonatomic, readonly) BOOL rasterize;
|
|
23
26
|
@property(nonatomic, readonly) BOOL hasCustomView;
|
|
24
27
|
@property(nonatomic, readonly) BOOL didLayout;
|
|
25
28
|
@property(nonatomic, readonly) UIView *iconView;
|
|
26
29
|
@property(nonatomic, weak, nullable) id<LuggMarkerViewDelegate> delegate;
|
|
27
30
|
@property(nonatomic, strong, nullable) NSObject *marker;
|
|
28
31
|
|
|
32
|
+
- (nullable UIImage *)createIconImage;
|
|
33
|
+
- (nullable UIImage *)createScaledIconImage;
|
|
34
|
+
- (void)resetIconViewTransform;
|
|
35
|
+
|
|
29
36
|
@end
|
|
30
37
|
|
|
31
38
|
NS_ASSUME_NONNULL_END
|
package/ios/LuggMarkerView.mm
CHANGED
|
@@ -19,6 +19,9 @@ using namespace facebook::react;
|
|
|
19
19
|
NSString *_markerDescription;
|
|
20
20
|
CGPoint _anchor;
|
|
21
21
|
NSInteger _zIndex;
|
|
22
|
+
CLLocationDegrees _rotate;
|
|
23
|
+
CGFloat _scale;
|
|
24
|
+
BOOL _rasterize;
|
|
22
25
|
BOOL _didLayout;
|
|
23
26
|
UIView *_iconView;
|
|
24
27
|
}
|
|
@@ -37,6 +40,9 @@ using namespace facebook::react;
|
|
|
37
40
|
_coordinate = CLLocationCoordinate2DMake(0, 0);
|
|
38
41
|
_anchor = CGPointMake(0.5, 1.0);
|
|
39
42
|
_zIndex = 0;
|
|
43
|
+
_rotate = 0;
|
|
44
|
+
_scale = 1;
|
|
45
|
+
_rasterize = YES;
|
|
40
46
|
_didLayout = NO;
|
|
41
47
|
|
|
42
48
|
_iconView = [[UIView alloc] init];
|
|
@@ -63,6 +69,9 @@ using namespace facebook::react;
|
|
|
63
69
|
[NSString stringWithUTF8String:newViewProps.description.c_str()];
|
|
64
70
|
_anchor = CGPointMake(newViewProps.anchor.x, newViewProps.anchor.y);
|
|
65
71
|
_zIndex = newViewProps.zIndex.value_or(0);
|
|
72
|
+
_rotate = newViewProps.rotate;
|
|
73
|
+
_scale = newViewProps.scale;
|
|
74
|
+
_rasterize = newViewProps.rasterize;
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
|
|
@@ -138,6 +147,18 @@ using namespace facebook::react;
|
|
|
138
147
|
return _zIndex;
|
|
139
148
|
}
|
|
140
149
|
|
|
150
|
+
- (CLLocationDegrees)rotate {
|
|
151
|
+
return _rotate;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
- (CGFloat)scale {
|
|
155
|
+
return _scale;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
- (BOOL)rasterize {
|
|
159
|
+
return _rasterize;
|
|
160
|
+
}
|
|
161
|
+
|
|
141
162
|
- (BOOL)hasCustomView {
|
|
142
163
|
return _iconView.subviews.count > 0;
|
|
143
164
|
}
|
|
@@ -150,11 +171,56 @@ using namespace facebook::react;
|
|
|
150
171
|
return _iconView;
|
|
151
172
|
}
|
|
152
173
|
|
|
174
|
+
- (UIImage *)createIconImage {
|
|
175
|
+
CGSize size = _iconView.bounds.size;
|
|
176
|
+
if (size.width <= 0 || size.height <= 0) {
|
|
177
|
+
return nil;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
UIGraphicsImageRendererFormat *format =
|
|
181
|
+
[UIGraphicsImageRendererFormat defaultFormat];
|
|
182
|
+
format.scale = [UIScreen mainScreen].scale;
|
|
183
|
+
UIGraphicsImageRenderer *renderer =
|
|
184
|
+
[[UIGraphicsImageRenderer alloc] initWithSize:size format:format];
|
|
185
|
+
|
|
186
|
+
return [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
|
|
187
|
+
[self->_iconView.layer renderInContext:context.CGContext];
|
|
188
|
+
}];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
- (UIImage *)createScaledIconImage {
|
|
192
|
+
CGSize size = _iconView.bounds.size;
|
|
193
|
+
if (size.width <= 0 || size.height <= 0) {
|
|
194
|
+
return nil;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
CGSize scaledSize = CGSizeMake(size.width * _scale, size.height * _scale);
|
|
198
|
+
|
|
199
|
+
UIGraphicsImageRendererFormat *format =
|
|
200
|
+
[UIGraphicsImageRendererFormat defaultFormat];
|
|
201
|
+
format.scale = [UIScreen mainScreen].scale;
|
|
202
|
+
UIGraphicsImageRenderer *renderer =
|
|
203
|
+
[[UIGraphicsImageRenderer alloc] initWithSize:scaledSize format:format];
|
|
204
|
+
|
|
205
|
+
return [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
|
|
206
|
+
CGContextScaleCTM(context.CGContext, self->_scale, self->_scale);
|
|
207
|
+
[self->_iconView.layer renderInContext:context.CGContext];
|
|
208
|
+
}];
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
- (void)resetIconViewTransform {
|
|
212
|
+
_iconView.transform = CGAffineTransformIdentity;
|
|
213
|
+
_iconView.layer.anchorPoint = CGPointMake(0.5, 0.5);
|
|
214
|
+
_iconView.frame = CGRectMake(0, 0, _iconView.bounds.size.width,
|
|
215
|
+
_iconView.bounds.size.height);
|
|
216
|
+
}
|
|
217
|
+
|
|
153
218
|
- (void)prepareForRecycle {
|
|
154
219
|
[super prepareForRecycle];
|
|
155
220
|
_didLayout = NO;
|
|
156
221
|
self.marker = nil;
|
|
157
222
|
self.delegate = nil;
|
|
223
|
+
[self resetIconViewTransform];
|
|
158
224
|
for (UIView *subview in _iconView.subviews) {
|
|
159
225
|
[subview removeFromSuperview];
|
|
160
226
|
}
|