@lugg/maps 0.2.0-alpha.2 → 0.2.0-alpha.21
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 +161 -46
- 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/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]) {
|
|
@@ -242,15 +282,8 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
242
282
|
marker.position = markerView.coordinate;
|
|
243
283
|
marker.title = markerView.title;
|
|
244
284
|
marker.snippet = markerView.markerDescription;
|
|
245
|
-
marker.
|
|
246
|
-
|
|
247
|
-
if (markerView.hasCustomView) {
|
|
248
|
-
UIView *iconView = markerView.iconView;
|
|
249
|
-
[iconView removeFromSuperview];
|
|
250
|
-
marker.iconView = iconView;
|
|
251
|
-
} else {
|
|
252
|
-
marker.iconView = nil;
|
|
253
|
-
}
|
|
285
|
+
marker.zIndex = (int)markerView.zIndex;
|
|
286
|
+
[self applyMarkerStyle:markerView marker:marker];
|
|
254
287
|
}
|
|
255
288
|
|
|
256
289
|
- (void)processPendingMarkers {
|
|
@@ -270,22 +303,15 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
270
303
|
return;
|
|
271
304
|
}
|
|
272
305
|
|
|
273
|
-
UIView *iconView = markerView.iconView;
|
|
274
|
-
[iconView removeFromSuperview];
|
|
275
|
-
|
|
276
306
|
GMSAdvancedMarker *marker = [[GMSAdvancedMarker alloc] init];
|
|
277
307
|
marker.position = markerView.coordinate;
|
|
278
308
|
marker.title = markerView.title;
|
|
279
309
|
marker.snippet = markerView.markerDescription;
|
|
280
|
-
marker.
|
|
310
|
+
marker.zIndex = (int)markerView.zIndex;
|
|
281
311
|
|
|
282
|
-
|
|
283
|
-
marker.iconView = iconView;
|
|
284
|
-
}
|
|
312
|
+
[self applyMarkerStyle:markerView marker:marker];
|
|
285
313
|
|
|
286
|
-
marker.groundAnchor = markerView.anchor;
|
|
287
314
|
marker.map = _mapView;
|
|
288
|
-
|
|
289
315
|
markerView.marker = marker;
|
|
290
316
|
}
|
|
291
317
|
|
|
@@ -306,12 +332,14 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
306
332
|
|
|
307
333
|
GMSPolyline *polyline = (GMSPolyline *)polylineView.polyline;
|
|
308
334
|
polyline.strokeWidth = polylineView.strokeWidth;
|
|
335
|
+
polyline.zIndex = (int)polylineView.zIndex;
|
|
309
336
|
|
|
310
337
|
GMSPolylineAnimator *animator =
|
|
311
338
|
[_polylineAnimators objectForKey:polylineView];
|
|
312
339
|
if (animator) {
|
|
313
340
|
animator.coordinates = polylineView.coordinates;
|
|
314
341
|
animator.strokeColors = polylineView.strokeColors;
|
|
342
|
+
animator.animatedOptions = polylineView.animatedOptions;
|
|
315
343
|
animator.animated = polylineView.animated;
|
|
316
344
|
[animator update];
|
|
317
345
|
}
|
|
@@ -335,6 +363,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
335
363
|
|
|
336
364
|
GMSPolyline *polyline = [GMSPolyline polylineWithPath:[GMSMutablePath path]];
|
|
337
365
|
polyline.strokeWidth = polylineView.strokeWidth;
|
|
366
|
+
polyline.zIndex = (int)polylineView.zIndex;
|
|
338
367
|
polyline.map = _mapView;
|
|
339
368
|
polylineView.polyline = polyline;
|
|
340
369
|
|
|
@@ -342,6 +371,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
342
371
|
animator.polyline = polyline;
|
|
343
372
|
animator.coordinates = polylineView.coordinates;
|
|
344
373
|
animator.strokeColors = polylineView.strokeColors;
|
|
374
|
+
animator.animatedOptions = polylineView.animatedOptions;
|
|
345
375
|
animator.animated = polylineView.animated;
|
|
346
376
|
[animator update];
|
|
347
377
|
|
|
@@ -393,10 +423,10 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
393
423
|
return;
|
|
394
424
|
}
|
|
395
425
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
426
|
+
float targetZoom = zoom > 0 ? (float)zoom : _mapView.camera.zoom;
|
|
427
|
+
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:latitude
|
|
428
|
+
longitude:longitude
|
|
429
|
+
zoom:targetZoom];
|
|
400
430
|
if (duration < 0) {
|
|
401
431
|
[_mapView animateToCameraPosition:camera];
|
|
402
432
|
} else if (duration > 0) {
|
package/ios/LuggMarkerView.h
CHANGED
|
@@ -14,16 +14,25 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
14
14
|
|
|
15
15
|
@interface LuggMarkerView : RCTViewComponentView
|
|
16
16
|
|
|
17
|
+
@property(nonatomic, readonly, nullable) NSString *name;
|
|
17
18
|
@property(nonatomic, readonly) CLLocationCoordinate2D coordinate;
|
|
18
19
|
@property(nonatomic, readonly, nullable) NSString *title;
|
|
19
20
|
@property(nonatomic, readonly, nullable) NSString *markerDescription;
|
|
20
21
|
@property(nonatomic, readonly) CGPoint anchor;
|
|
22
|
+
@property(nonatomic, readonly) NSInteger zIndex;
|
|
23
|
+
@property(nonatomic, readonly) CLLocationDegrees rotate;
|
|
24
|
+
@property(nonatomic, readonly) CGFloat scale;
|
|
25
|
+
@property(nonatomic, readonly) BOOL rasterize;
|
|
21
26
|
@property(nonatomic, readonly) BOOL hasCustomView;
|
|
22
27
|
@property(nonatomic, readonly) BOOL didLayout;
|
|
23
28
|
@property(nonatomic, readonly) UIView *iconView;
|
|
24
29
|
@property(nonatomic, weak, nullable) id<LuggMarkerViewDelegate> delegate;
|
|
25
30
|
@property(nonatomic, strong, nullable) NSObject *marker;
|
|
26
31
|
|
|
32
|
+
- (nullable UIImage *)createIconImage;
|
|
33
|
+
- (nullable UIImage *)createScaledIconImage;
|
|
34
|
+
- (void)resetIconViewTransform;
|
|
35
|
+
|
|
27
36
|
@end
|
|
28
37
|
|
|
29
38
|
NS_ASSUME_NONNULL_END
|
package/ios/LuggMarkerView.mm
CHANGED
|
@@ -13,10 +13,15 @@ using namespace facebook::react;
|
|
|
13
13
|
@end
|
|
14
14
|
|
|
15
15
|
@implementation LuggMarkerView {
|
|
16
|
+
NSString *_name;
|
|
16
17
|
CLLocationCoordinate2D _coordinate;
|
|
17
18
|
NSString *_title;
|
|
18
19
|
NSString *_markerDescription;
|
|
19
20
|
CGPoint _anchor;
|
|
21
|
+
NSInteger _zIndex;
|
|
22
|
+
CLLocationDegrees _rotate;
|
|
23
|
+
CGFloat _scale;
|
|
24
|
+
BOOL _rasterize;
|
|
20
25
|
BOOL _didLayout;
|
|
21
26
|
UIView *_iconView;
|
|
22
27
|
}
|
|
@@ -34,6 +39,10 @@ using namespace facebook::react;
|
|
|
34
39
|
|
|
35
40
|
_coordinate = CLLocationCoordinate2DMake(0, 0);
|
|
36
41
|
_anchor = CGPointMake(0.5, 1.0);
|
|
42
|
+
_zIndex = 0;
|
|
43
|
+
_rotate = 0;
|
|
44
|
+
_scale = 1;
|
|
45
|
+
_rasterize = YES;
|
|
37
46
|
_didLayout = NO;
|
|
38
47
|
|
|
39
48
|
_iconView = [[UIView alloc] init];
|
|
@@ -52,12 +61,17 @@ using namespace facebook::react;
|
|
|
52
61
|
const auto &newViewProps =
|
|
53
62
|
*std::static_pointer_cast<LuggMarkerViewProps const>(props);
|
|
54
63
|
|
|
64
|
+
_name = [NSString stringWithUTF8String:newViewProps.name.c_str()];
|
|
55
65
|
_coordinate = CLLocationCoordinate2DMake(newViewProps.coordinate.latitude,
|
|
56
66
|
newViewProps.coordinate.longitude);
|
|
57
67
|
_title = [NSString stringWithUTF8String:newViewProps.title.c_str()];
|
|
58
68
|
_markerDescription =
|
|
59
69
|
[NSString stringWithUTF8String:newViewProps.description.c_str()];
|
|
60
70
|
_anchor = CGPointMake(newViewProps.anchor.x, newViewProps.anchor.y);
|
|
71
|
+
_zIndex = newViewProps.zIndex.value_or(0);
|
|
72
|
+
_rotate = newViewProps.rotate;
|
|
73
|
+
_scale = newViewProps.scale;
|
|
74
|
+
_rasterize = newViewProps.rasterize;
|
|
61
75
|
}
|
|
62
76
|
|
|
63
77
|
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
|
|
@@ -109,6 +123,10 @@ using namespace facebook::react;
|
|
|
109
123
|
}
|
|
110
124
|
}
|
|
111
125
|
|
|
126
|
+
- (NSString *)name {
|
|
127
|
+
return _name;
|
|
128
|
+
}
|
|
129
|
+
|
|
112
130
|
- (CLLocationCoordinate2D)coordinate {
|
|
113
131
|
return _coordinate;
|
|
114
132
|
}
|
|
@@ -125,6 +143,22 @@ using namespace facebook::react;
|
|
|
125
143
|
return _anchor;
|
|
126
144
|
}
|
|
127
145
|
|
|
146
|
+
- (NSInteger)zIndex {
|
|
147
|
+
return _zIndex;
|
|
148
|
+
}
|
|
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
|
+
|
|
128
162
|
- (BOOL)hasCustomView {
|
|
129
163
|
return _iconView.subviews.count > 0;
|
|
130
164
|
}
|
|
@@ -137,11 +171,56 @@ using namespace facebook::react;
|
|
|
137
171
|
return _iconView;
|
|
138
172
|
}
|
|
139
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
|
+
|
|
140
218
|
- (void)prepareForRecycle {
|
|
141
219
|
[super prepareForRecycle];
|
|
142
220
|
_didLayout = NO;
|
|
143
221
|
self.marker = nil;
|
|
144
222
|
self.delegate = nil;
|
|
223
|
+
[self resetIconViewTransform];
|
|
145
224
|
for (UIView *subview in _iconView.subviews) {
|
|
146
225
|
[subview removeFromSuperview];
|
|
147
226
|
}
|
package/ios/LuggPolylineView.h
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#import "core/PolylineAnimatorBase.h"
|
|
1
2
|
#import <CoreLocation/CoreLocation.h>
|
|
2
3
|
#import <React/RCTViewComponentView.h>
|
|
3
4
|
#import <UIKit/UIKit.h>
|
|
@@ -16,7 +17,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
16
17
|
@property(nonatomic, readonly) NSArray<CLLocation *> *coordinates;
|
|
17
18
|
@property(nonatomic, readonly) NSArray<UIColor *> *strokeColors;
|
|
18
19
|
@property(nonatomic, readonly) BOOL animated;
|
|
20
|
+
@property(nonatomic, readonly, nullable)
|
|
21
|
+
PolylineAnimatedOptions *animatedOptions;
|
|
19
22
|
@property(nonatomic, readonly) CGFloat strokeWidth;
|
|
23
|
+
@property(nonatomic, readonly) NSInteger zIndex;
|
|
20
24
|
@property(nonatomic, weak, nullable) id<LuggPolylineViewDelegate> delegate;
|
|
21
25
|
@property(nonatomic, strong, nullable) NSObject *polyline;
|
|
22
26
|
@property(nonatomic, weak, nullable) NSObject *renderer;
|
package/ios/LuggPolylineView.mm
CHANGED
|
@@ -17,7 +17,9 @@ using namespace facebook::react;
|
|
|
17
17
|
NSArray<CLLocation *> *_coordinates;
|
|
18
18
|
NSArray<UIColor *> *_strokeColors;
|
|
19
19
|
BOOL _animated;
|
|
20
|
+
PolylineAnimatedOptions *_animatedOptions;
|
|
20
21
|
CGFloat _strokeWidth;
|
|
22
|
+
NSInteger _zIndex;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
@@ -72,7 +74,20 @@ using namespace facebook::react;
|
|
|
72
74
|
|
|
73
75
|
_animated = newViewProps.animated;
|
|
74
76
|
|
|
77
|
+
const auto &opts = newViewProps.animatedOptions;
|
|
78
|
+
PolylineAnimatedOptions *options = [[PolylineAnimatedOptions alloc] init];
|
|
79
|
+
options.duration = opts.duration > 0 ? opts.duration : 2150;
|
|
80
|
+
options.trailLength = (opts.trailLength > 0 && opts.trailLength <= 1.0)
|
|
81
|
+
? opts.trailLength
|
|
82
|
+
: 1.0;
|
|
83
|
+
options.delay = opts.delay;
|
|
84
|
+
options.easing = !opts.easing.empty()
|
|
85
|
+
? [NSString stringWithUTF8String:opts.easing.c_str()]
|
|
86
|
+
: @"linear";
|
|
87
|
+
_animatedOptions = options;
|
|
88
|
+
|
|
75
89
|
_strokeWidth = newViewProps.strokeWidth > 0 ? newViewProps.strokeWidth : 1.0;
|
|
90
|
+
_zIndex = newViewProps.zIndex.value_or(0);
|
|
76
91
|
}
|
|
77
92
|
|
|
78
93
|
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
|
|
@@ -97,10 +112,18 @@ using namespace facebook::react;
|
|
|
97
112
|
return _animated;
|
|
98
113
|
}
|
|
99
114
|
|
|
115
|
+
- (PolylineAnimatedOptions *)animatedOptions {
|
|
116
|
+
return _animatedOptions;
|
|
117
|
+
}
|
|
118
|
+
|
|
100
119
|
- (CGFloat)strokeWidth {
|
|
101
120
|
return _strokeWidth;
|
|
102
121
|
}
|
|
103
122
|
|
|
123
|
+
- (NSInteger)zIndex {
|
|
124
|
+
return _zIndex;
|
|
125
|
+
}
|
|
126
|
+
|
|
104
127
|
- (void)prepareForRecycle {
|
|
105
128
|
[super prepareForRecycle];
|
|
106
129
|
self.polyline = nil;
|
|
@@ -1,15 +1,53 @@
|
|
|
1
1
|
#import "GMSPolylineAnimator.h"
|
|
2
2
|
#import <QuartzCore/QuartzCore.h>
|
|
3
3
|
|
|
4
|
+
@interface GMSDisplayLinkProxy : NSObject
|
|
5
|
+
@property(nonatomic, weak) id target;
|
|
6
|
+
@property(nonatomic, assign) SEL selector;
|
|
7
|
+
@end
|
|
8
|
+
|
|
9
|
+
@implementation GMSDisplayLinkProxy
|
|
10
|
+
- (instancetype)initWithTarget:(id)target selector:(SEL)selector {
|
|
11
|
+
if (self = [super init]) {
|
|
12
|
+
_target = target;
|
|
13
|
+
_selector = selector;
|
|
14
|
+
}
|
|
15
|
+
return self;
|
|
16
|
+
}
|
|
17
|
+
- (void)tick:(CADisplayLink *)displayLink {
|
|
18
|
+
if (_target) {
|
|
19
|
+
#pragma clang diagnostic push
|
|
20
|
+
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
|
21
|
+
[_target performSelector:_selector withObject:displayLink];
|
|
22
|
+
#pragma clang diagnostic pop
|
|
23
|
+
} else {
|
|
24
|
+
[displayLink invalidate];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
@end
|
|
28
|
+
|
|
4
29
|
@implementation GMSPolylineAnimator {
|
|
5
30
|
CADisplayLink *_displayLink;
|
|
31
|
+
GMSDisplayLinkProxy *_displayLinkProxy;
|
|
6
32
|
CGFloat _animationProgress;
|
|
33
|
+
CGFloat _delayRemaining;
|
|
34
|
+
NSArray<NSNumber *> *_cumulativeDistances;
|
|
35
|
+
CGFloat _totalLength;
|
|
7
36
|
}
|
|
8
37
|
|
|
38
|
+
@synthesize animatedOptions = _animatedOptions;
|
|
39
|
+
|
|
9
40
|
- (void)dealloc {
|
|
10
41
|
[self stopAnimation];
|
|
11
42
|
}
|
|
12
43
|
|
|
44
|
+
- (void)setCoordinates:(NSArray<CLLocation *> *)coordinates {
|
|
45
|
+
[super setCoordinates:coordinates];
|
|
46
|
+
if (_animated && _displayLink) {
|
|
47
|
+
[self computeCumulativeDistances];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
13
51
|
- (void)setAnimated:(BOOL)animated {
|
|
14
52
|
if (_animated == animated) {
|
|
15
53
|
return;
|
|
@@ -24,26 +62,74 @@
|
|
|
24
62
|
}
|
|
25
63
|
}
|
|
26
64
|
|
|
65
|
+
- (void)setAnimatedOptions:(PolylineAnimatedOptions *)animatedOptions {
|
|
66
|
+
_animatedOptions = animatedOptions ?: [PolylineAnimatedOptions defaultOptions];
|
|
67
|
+
if (_animated && _displayLink) {
|
|
68
|
+
[self stopAnimation];
|
|
69
|
+
[self startAnimation];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
27
73
|
- (void)startAnimation {
|
|
28
74
|
if (_displayLink) {
|
|
29
75
|
return;
|
|
30
76
|
}
|
|
77
|
+
[self computeCumulativeDistances];
|
|
31
78
|
_animationProgress = 0;
|
|
32
|
-
|
|
79
|
+
_delayRemaining = self.animatedOptions.delay / 1000.0;
|
|
80
|
+
_displayLinkProxy = [[GMSDisplayLinkProxy alloc] initWithTarget:self selector:@selector(animationTick:)];
|
|
81
|
+
_displayLink = [CADisplayLink displayLinkWithTarget:_displayLinkProxy selector:@selector(tick:)];
|
|
33
82
|
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
34
83
|
}
|
|
35
84
|
|
|
85
|
+
- (void)computeCumulativeDistances {
|
|
86
|
+
NSMutableArray<NSNumber *> *distances = [NSMutableArray array];
|
|
87
|
+
CGFloat total = 0;
|
|
88
|
+
[distances addObject:@(0)];
|
|
89
|
+
|
|
90
|
+
for (NSUInteger i = 1; i < self.coordinates.count; i++) {
|
|
91
|
+
CLLocation *prev = self.coordinates[i - 1];
|
|
92
|
+
CLLocation *curr = self.coordinates[i];
|
|
93
|
+
total += [prev distanceFromLocation:curr];
|
|
94
|
+
[distances addObject:@(total)];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_cumulativeDistances = [distances copy];
|
|
98
|
+
_totalLength = total;
|
|
99
|
+
}
|
|
100
|
+
|
|
36
101
|
- (void)stopAnimation {
|
|
37
102
|
[_displayLink invalidate];
|
|
38
103
|
_displayLink = nil;
|
|
104
|
+
_displayLinkProxy = nil;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
- (void)pause {
|
|
108
|
+
_displayLink.paused = YES;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
- (void)resume {
|
|
112
|
+
_displayLink.paused = NO;
|
|
39
113
|
}
|
|
40
114
|
|
|
41
115
|
- (void)animationTick:(CADisplayLink *)displayLink {
|
|
42
|
-
|
|
116
|
+
if (_delayRemaining > 0) {
|
|
117
|
+
_delayRemaining -= displayLink.duration;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
CGFloat duration = self.animatedOptions.duration / 1000.0;
|
|
122
|
+
if (duration <= 0) duration = 2.15;
|
|
123
|
+
|
|
124
|
+
CGFloat trailLength = MAX(0.01, MIN(1.0, self.animatedOptions.trailLength));
|
|
125
|
+
CGFloat maxProgress = (trailLength < 1.0) ? 1.0 : 2.15;
|
|
126
|
+
|
|
127
|
+
CGFloat speed = displayLink.duration / duration;
|
|
43
128
|
_animationProgress += speed;
|
|
44
129
|
|
|
45
|
-
if (_animationProgress >=
|
|
130
|
+
if (_animationProgress >= maxProgress) {
|
|
46
131
|
_animationProgress = 0;
|
|
132
|
+
_delayRemaining = self.animatedOptions.delay / 1000.0;
|
|
47
133
|
}
|
|
48
134
|
|
|
49
135
|
[self updateAnimatedPolyline];
|
|
@@ -71,63 +157,100 @@
|
|
|
71
157
|
}
|
|
72
158
|
}
|
|
73
159
|
|
|
160
|
+
- (NSUInteger)indexForDistance:(CGFloat)distance {
|
|
161
|
+
NSUInteger left = 0;
|
|
162
|
+
NSUInteger right = _cumulativeDistances.count - 1;
|
|
163
|
+
|
|
164
|
+
while (left < right) {
|
|
165
|
+
NSUInteger mid = (left + right + 1) / 2;
|
|
166
|
+
if (_cumulativeDistances[mid].doubleValue <= distance) {
|
|
167
|
+
left = mid;
|
|
168
|
+
} else {
|
|
169
|
+
right = mid - 1;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return MIN(left, _cumulativeDistances.count - 2);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
- (CLLocationCoordinate2D)coordinateAtDistance:(CGFloat)distance {
|
|
177
|
+
if (distance <= 0) {
|
|
178
|
+
return self.coordinates.firstObject.coordinate;
|
|
179
|
+
}
|
|
180
|
+
if (distance >= _totalLength) {
|
|
181
|
+
return self.coordinates.lastObject.coordinate;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
NSUInteger idx = [self indexForDistance:distance];
|
|
185
|
+
CGFloat segStart = _cumulativeDistances[idx].doubleValue;
|
|
186
|
+
CGFloat segEnd = _cumulativeDistances[idx + 1].doubleValue;
|
|
187
|
+
CGFloat segLength = segEnd - segStart;
|
|
188
|
+
|
|
189
|
+
CGFloat t = (segLength > 0) ? (distance - segStart) / segLength : 0;
|
|
190
|
+
CLLocationCoordinate2D c1 = self.coordinates[idx].coordinate;
|
|
191
|
+
CLLocationCoordinate2D c2 = self.coordinates[idx + 1].coordinate;
|
|
192
|
+
|
|
193
|
+
return CLLocationCoordinate2DMake(c1.latitude + (c2.latitude - c1.latitude) * t,
|
|
194
|
+
c1.longitude + (c2.longitude - c1.longitude) * t);
|
|
195
|
+
}
|
|
196
|
+
|
|
74
197
|
- (void)updateAnimatedPolyline {
|
|
75
|
-
if (!_polyline || self.coordinates.count < 2) {
|
|
198
|
+
if (!_polyline || self.coordinates.count < 2 || _totalLength <= 0) {
|
|
76
199
|
return;
|
|
77
200
|
}
|
|
78
201
|
|
|
79
|
-
|
|
80
|
-
CGFloat
|
|
81
|
-
CGFloat
|
|
202
|
+
CGFloat trailLength = MAX(0.01, MIN(1.0, self.animatedOptions.trailLength));
|
|
203
|
+
CGFloat maxProgress = (trailLength < 1.0) ? 1.0 : 2.0;
|
|
204
|
+
CGFloat progress = MIN(_animationProgress, maxProgress);
|
|
205
|
+
CGFloat easedProgress = [self applyEasing:progress / maxProgress] * maxProgress;
|
|
206
|
+
|
|
207
|
+
CGFloat headDist, tailDist;
|
|
82
208
|
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
209
|
+
if (trailLength < 1.0) {
|
|
210
|
+
headDist = easedProgress * _totalLength;
|
|
211
|
+
tailDist = MAX(0, headDist - _totalLength * trailLength);
|
|
212
|
+
} else if (easedProgress <= 1.0) {
|
|
213
|
+
tailDist = 0;
|
|
214
|
+
headDist = easedProgress * _totalLength;
|
|
86
215
|
} else {
|
|
87
|
-
CGFloat shrinkProgress =
|
|
88
|
-
|
|
89
|
-
|
|
216
|
+
CGFloat shrinkProgress = easedProgress - 1.0;
|
|
217
|
+
tailDist = shrinkProgress * _totalLength;
|
|
218
|
+
headDist = _totalLength;
|
|
90
219
|
}
|
|
91
220
|
|
|
92
|
-
if (
|
|
221
|
+
if (headDist <= tailDist) {
|
|
93
222
|
_polyline.path = [GMSMutablePath path];
|
|
94
223
|
return;
|
|
95
224
|
}
|
|
96
225
|
|
|
97
|
-
|
|
98
|
-
NSUInteger
|
|
99
|
-
|
|
226
|
+
CGFloat visibleLength = headDist - tailDist;
|
|
227
|
+
NSUInteger startIndex = [self indexForDistance:tailDist];
|
|
228
|
+
NSUInteger endIndex = [self indexForDistance:headDist];
|
|
100
229
|
|
|
101
230
|
GMSMutablePath *path = [GMSMutablePath path];
|
|
102
231
|
NSMutableArray<GMSStyleSpan *> *spans = [NSMutableArray array];
|
|
103
232
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (i == startIndex && tailPos > (CGFloat)startIndex) {
|
|
108
|
-
CGFloat t = tailPos - (CGFloat)startIndex;
|
|
109
|
-
CLLocationCoordinate2D nextCoord = self.coordinates[i + 1].coordinate;
|
|
110
|
-
coord.latitude = coord.latitude + (nextCoord.latitude - coord.latitude) * t;
|
|
111
|
-
coord.longitude = coord.longitude + (nextCoord.longitude - coord.longitude) * t;
|
|
112
|
-
}
|
|
233
|
+
CLLocationCoordinate2D startCoord = [self coordinateAtDistance:tailDist];
|
|
234
|
+
[path addCoordinate:startCoord];
|
|
113
235
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
coord.latitude = prevCoord.latitude + (coord.latitude - prevCoord.latitude) * t;
|
|
118
|
-
coord.longitude = prevCoord.longitude + (coord.longitude - prevCoord.longitude) * t;
|
|
119
|
-
}
|
|
236
|
+
for (NSUInteger i = startIndex + 1; i <= endIndex; i++) {
|
|
237
|
+
[path addCoordinate:self.coordinates[i].coordinate];
|
|
238
|
+
}
|
|
120
239
|
|
|
121
|
-
|
|
240
|
+
CLLocationCoordinate2D endCoord = [self coordinateAtDistance:headDist];
|
|
241
|
+
CLLocationCoordinate2D lastAdded =
|
|
242
|
+
(endIndex < self.coordinates.count) ? self.coordinates[endIndex].coordinate : endCoord;
|
|
243
|
+
if (endCoord.latitude != lastAdded.latitude || endCoord.longitude != lastAdded.longitude) {
|
|
244
|
+
[path addCoordinate:endCoord];
|
|
245
|
+
}
|
|
122
246
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
247
|
+
NSUInteger pathCount = path.count;
|
|
248
|
+
for (NSUInteger i = 0; i < pathCount - 1; i++) {
|
|
249
|
+
CGFloat segMidDist = tailDist + visibleLength * ((CGFloat)i + 0.5) / (CGFloat)(pathCount - 1);
|
|
250
|
+
CGFloat gradientPos = (segMidDist - tailDist) / visibleLength;
|
|
251
|
+
UIColor *color = [self colorAtGradientPosition:gradientPos];
|
|
252
|
+
GMSStrokeStyle *style = [GMSStrokeStyle solidColor:color];
|
|
253
|
+
[spans addObject:[GMSStyleSpan spanWithStyle:style]];
|
|
131
254
|
}
|
|
132
255
|
|
|
133
256
|
_polyline.path = path;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#import "PolylineAnimatorBase.h"
|
|
1
2
|
#import <MapKit/MapKit.h>
|
|
2
3
|
|
|
3
4
|
@interface MKPolylineAnimator : MKOverlayPathRenderer
|
|
@@ -6,7 +7,10 @@
|
|
|
6
7
|
|
|
7
8
|
@property(nonatomic, strong) NSArray<UIColor *> *strokeColors;
|
|
8
9
|
@property(nonatomic, assign) BOOL animated;
|
|
10
|
+
@property(nonatomic, strong) PolylineAnimatedOptions *animatedOptions;
|
|
9
11
|
|
|
10
12
|
- (void)updatePolyline:(MKPolyline *)polyline;
|
|
13
|
+
- (void)pause;
|
|
14
|
+
- (void)resume;
|
|
11
15
|
|
|
12
16
|
@end
|