@lugg/maps 1.0.0-beta.9 → 1.1.0
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 +15 -100
- package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +5 -0
- package/android/src/main/java/com/luggmaps/LuggMapView.kt +56 -2
- package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +18 -0
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +36 -2
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +7 -2
- package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +2 -1
- package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +332 -42
- package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +6 -0
- package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +61 -10
- package/ios/LuggMapView.mm +240 -10
- package/ios/LuggMapWrapperView.h +5 -0
- package/ios/LuggMapWrapperView.mm +18 -0
- package/ios/LuggMarkerView.mm +2 -0
- package/ios/core/AppleMapProvider.h +8 -0
- package/ios/core/AppleMapProvider.mm +63 -47
- package/ios/core/AppleStaticMapProvider.h +14 -0
- package/ios/core/AppleStaticMapProvider.mm +233 -0
- package/ios/core/GMSPolylineAnimator.m +40 -15
- package/ios/core/GoogleMapProvider.h +10 -0
- package/ios/core/GoogleMapProvider.mm +67 -54
- package/ios/core/GoogleStaticMapProvider.h +21 -0
- package/ios/core/GoogleStaticMapProvider.mm +217 -0
- package/ios/core/MKPolylineAnimator.m +67 -43
- package/ios/core/MapEdgeInsets.h +18 -0
- package/ios/core/MapProviderDelegate.h +11 -0
- package/ios/core/StaticMapProviderBase.h +80 -0
- package/ios/core/StaticMapProviderBase.mm +847 -0
- package/ios/events/CameraIdleEvent.h +4 -2
- package/ios/events/CameraMoveEvent.h +4 -2
- package/ios/events/CirclePressEvent.h +4 -2
- package/ios/events/GroundOverlayPressEvent.h +4 -2
- package/ios/events/LongPressEvent.h +4 -2
- package/ios/events/MarkerDragEvent.h +12 -6
- package/ios/events/MarkerPressEvent.h +4 -2
- package/ios/events/PolygonPressEvent.h +4 -2
- package/ios/events/PressEvent.h +4 -2
- package/ios/events/ReadyEvent.h +4 -2
- package/ios/events/TileOverlayPressEvent.h +4 -2
- package/ios/extensions/MKMapView+Zoom.h +20 -0
- package/ios/extensions/MKMapView+Zoom.m +28 -18
- package/ios/extensions/UIView+Snapshot.h +16 -0
- package/ios/extensions/UIView+Snapshot.m +27 -0
- package/lib/module/MapView.js +12 -0
- package/lib/module/MapView.js.map +1 -1
- package/lib/module/MapView.web.js +29 -10
- package/lib/module/MapView.web.js.map +1 -1
- package/lib/module/fabric/LuggMapViewNativeComponent.ts +10 -1
- package/lib/typescript/src/MapView.d.ts +1 -0
- package/lib/typescript/src/MapView.d.ts.map +1 -1
- package/lib/typescript/src/MapView.types.d.ts +32 -0
- package/lib/typescript/src/MapView.types.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +4 -0
- package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
- package/package.json +24 -14
- package/src/MapView.tsx +14 -0
- package/src/MapView.types.ts +32 -0
- package/src/MapView.web.tsx +39 -14
- package/src/fabric/LuggMapViewNativeComponent.ts +10 -1
- package/plugin/build/withMapsAndroid.d.ts +0 -5
- package/plugin/build/withMapsAndroid.js +0 -15
- package/plugin/build/withMapsIOS.d.ts +0 -5
- package/plugin/build/withMapsIOS.js +0 -27
|
@@ -15,6 +15,7 @@ using facebook::react::LuggMapViewTheme;
|
|
|
15
15
|
#import "../extensions/MKMapView+Zoom.h"
|
|
16
16
|
#import "LuggAnnotationView.h"
|
|
17
17
|
#import "MKPolylineAnimator.h"
|
|
18
|
+
#import "MapEdgeInsets.h"
|
|
18
19
|
|
|
19
20
|
@interface AppleMarkerAnnotation : NSObject <MKAnnotation>
|
|
20
21
|
@property(nonatomic, assign) CLLocationCoordinate2D coordinate;
|
|
@@ -145,6 +146,7 @@ static double tileToLng(NSInteger x, NSInteger z) {
|
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
@synthesize delegate = _delegate;
|
|
149
|
+
@synthesize staticMode = _staticMode;
|
|
148
150
|
|
|
149
151
|
- (instancetype)init {
|
|
150
152
|
if (self = [super init]) {
|
|
@@ -182,6 +184,10 @@ static double tileToLng(NSInteger x, NSInteger z) {
|
|
|
182
184
|
_mapView.delegate = self;
|
|
183
185
|
_mapView.insetsLayoutMarginsFromSafeArea = NO;
|
|
184
186
|
|
|
187
|
+
if (_staticMode) {
|
|
188
|
+
_mapView.userInteractionEnabled = NO;
|
|
189
|
+
}
|
|
190
|
+
|
|
185
191
|
[self applyZoomRange];
|
|
186
192
|
|
|
187
193
|
_tapGesture =
|
|
@@ -212,6 +218,19 @@ static double tileToLng(NSInteger x, NSInteger z) {
|
|
|
212
218
|
}
|
|
213
219
|
|
|
214
220
|
- (void)destroy {
|
|
221
|
+
[self destroyMapView];
|
|
222
|
+
_isMapReady = NO;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
- (CLLocationCoordinate2D)coordinate {
|
|
226
|
+
return _mapView.centerCoordinate;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
- (double)zoom {
|
|
230
|
+
return _mapView.zoomLevel;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
- (void)destroyMapView {
|
|
215
234
|
[self dismissNonBubbledCallout];
|
|
216
235
|
[self stopEdgeInsetsAnimation];
|
|
217
236
|
if (_tapGesture) {
|
|
@@ -222,9 +241,9 @@ static double tileToLng(NSInteger x, NSInteger z) {
|
|
|
222
241
|
[_mapView removeGestureRecognizer:_longPressGesture];
|
|
223
242
|
_longPressGesture = nil;
|
|
224
243
|
}
|
|
244
|
+
_mapView.delegate = nil;
|
|
225
245
|
[_mapView removeFromSuperview];
|
|
226
246
|
_mapView = nil;
|
|
227
|
-
_isMapReady = NO;
|
|
228
247
|
}
|
|
229
248
|
|
|
230
249
|
#pragma mark - Props
|
|
@@ -245,6 +264,10 @@ static double tileToLng(NSInteger x, NSInteger z) {
|
|
|
245
264
|
_mapView.pitchEnabled = enabled;
|
|
246
265
|
}
|
|
247
266
|
|
|
267
|
+
- (void)setCompassEnabled:(BOOL)enabled {
|
|
268
|
+
_mapView.showsCompass = enabled;
|
|
269
|
+
}
|
|
270
|
+
|
|
248
271
|
- (void)setUserLocationEnabled:(BOOL)enabled {
|
|
249
272
|
_mapView.showsUserLocation = enabled;
|
|
250
273
|
}
|
|
@@ -338,33 +361,36 @@ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
|
|
|
338
361
|
return map[string];
|
|
339
362
|
}
|
|
340
363
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return;
|
|
364
|
+
MKPointOfInterestFilter *_Nullable LuggPointOfInterestFilter(
|
|
365
|
+
BOOL poiEnabled, LuggMapViewPoiFilterMode filterMode,
|
|
366
|
+
NSArray<NSString *> *filterCategories) {
|
|
367
|
+
if (!poiEnabled) {
|
|
368
|
+
return MKPointOfInterestFilter.filterExcludingAllCategories;
|
|
346
369
|
}
|
|
347
|
-
if (
|
|
370
|
+
if (filterCategories.count > 0) {
|
|
348
371
|
NSMutableArray<MKPointOfInterestCategory> *categories =
|
|
349
372
|
[NSMutableArray array];
|
|
350
|
-
for (NSString *name in
|
|
373
|
+
for (NSString *name in filterCategories) {
|
|
351
374
|
MKPointOfInterestCategory category = poiCategoryFromString(name);
|
|
352
375
|
if (category) {
|
|
353
376
|
[categories addObject:category];
|
|
354
377
|
}
|
|
355
378
|
}
|
|
356
379
|
if (categories.count > 0) {
|
|
357
|
-
if (
|
|
358
|
-
|
|
380
|
+
if (filterMode == LuggMapViewPoiFilterMode::Excluding) {
|
|
381
|
+
return [[MKPointOfInterestFilter alloc]
|
|
359
382
|
initExcludingCategories:categories];
|
|
360
|
-
} else {
|
|
361
|
-
_mapView.pointOfInterestFilter = [[MKPointOfInterestFilter alloc]
|
|
362
|
-
initIncludingCategories:categories];
|
|
363
383
|
}
|
|
364
|
-
return
|
|
384
|
+
return
|
|
385
|
+
[[MKPointOfInterestFilter alloc] initIncludingCategories:categories];
|
|
365
386
|
}
|
|
366
387
|
}
|
|
367
|
-
|
|
388
|
+
return nil;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
- (void)applyPoiFilter {
|
|
392
|
+
_mapView.pointOfInterestFilter = LuggPointOfInterestFilter(
|
|
393
|
+
_poiEnabled, _poiFilterMode, _poiFilterCategories);
|
|
368
394
|
}
|
|
369
395
|
|
|
370
396
|
- (void)setInsetAdjustment:(LuggMapViewInsetAdjustment)insetAdjustment {
|
|
@@ -395,26 +421,25 @@ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
|
|
|
395
421
|
[self applyPoiFilter];
|
|
396
422
|
}
|
|
397
423
|
|
|
398
|
-
|
|
424
|
+
MKMapType LuggMKMapTypeFromMapType(LuggMapViewMapType mapType) {
|
|
399
425
|
switch (mapType) {
|
|
400
426
|
case LuggMapViewMapType::Satellite:
|
|
401
|
-
|
|
402
|
-
break;
|
|
427
|
+
return MKMapTypeSatellite;
|
|
403
428
|
case LuggMapViewMapType::Terrain:
|
|
404
|
-
|
|
405
|
-
break;
|
|
429
|
+
return MKMapTypeStandard;
|
|
406
430
|
case LuggMapViewMapType::Hybrid:
|
|
407
|
-
|
|
408
|
-
break;
|
|
431
|
+
return MKMapTypeHybrid;
|
|
409
432
|
case LuggMapViewMapType::MutedStandard:
|
|
410
|
-
|
|
411
|
-
break;
|
|
433
|
+
return MKMapTypeMutedStandard;
|
|
412
434
|
default:
|
|
413
|
-
|
|
414
|
-
break;
|
|
435
|
+
return MKMapTypeStandard;
|
|
415
436
|
}
|
|
416
437
|
}
|
|
417
438
|
|
|
439
|
+
- (void)setMapType:(LuggMapViewMapType)mapType {
|
|
440
|
+
_mapView.mapType = LuggMKMapTypeFromMapType(mapType);
|
|
441
|
+
}
|
|
442
|
+
|
|
418
443
|
- (void)setTheme:(LuggMapViewTheme)theme {
|
|
419
444
|
switch (theme) {
|
|
420
445
|
case LuggMapViewTheme::Dark:
|
|
@@ -441,13 +466,11 @@ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
|
|
|
441
466
|
|
|
442
467
|
- (void)setEdgeInsets:(UIEdgeInsets)edgeInsets
|
|
443
468
|
oldEdgeInsets:(UIEdgeInsets)oldEdgeInsets {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
CGFloat newOffsetX = (edgeInsets.left - edgeInsets.right) / 2.0;
|
|
447
|
-
CGFloat newOffsetY = (edgeInsets.top - edgeInsets.bottom) / 2.0;
|
|
469
|
+
CGPoint oldOffset = LuggMapInsetOffset(oldEdgeInsets);
|
|
470
|
+
CGPoint newOffset = LuggMapInsetOffset(edgeInsets);
|
|
448
471
|
|
|
449
|
-
CGFloat deltaX =
|
|
450
|
-
CGFloat deltaY =
|
|
472
|
+
CGFloat deltaX = newOffset.x - oldOffset.x;
|
|
473
|
+
CGFloat deltaY = newOffset.y - oldOffset.y;
|
|
451
474
|
|
|
452
475
|
_mapView.layoutMargins = edgeInsets;
|
|
453
476
|
_edgeInsetsCurrent = edgeInsets;
|
|
@@ -490,16 +513,8 @@ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
|
|
|
490
513
|
CFTimeInterval elapsed = CACurrentMediaTime() - _edgeInsetsAnimationStart;
|
|
491
514
|
CGFloat progress = MIN(elapsed / _edgeInsetsAnimationDuration, 1.0);
|
|
492
515
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
UIEdgeInsets current = UIEdgeInsetsMake(
|
|
497
|
-
_edgeInsetsFrom.top + (_edgeInsetsTo.top - _edgeInsetsFrom.top) * t,
|
|
498
|
-
_edgeInsetsFrom.left + (_edgeInsetsTo.left - _edgeInsetsFrom.left) * t,
|
|
499
|
-
_edgeInsetsFrom.bottom +
|
|
500
|
-
(_edgeInsetsTo.bottom - _edgeInsetsFrom.bottom) * t,
|
|
501
|
-
_edgeInsetsFrom.right +
|
|
502
|
-
(_edgeInsetsTo.right - _edgeInsetsFrom.right) * t);
|
|
516
|
+
UIEdgeInsets current =
|
|
517
|
+
LuggMapInsetsAtProgress(_edgeInsetsFrom, _edgeInsetsTo, progress);
|
|
503
518
|
|
|
504
519
|
[self setEdgeInsets:current oldEdgeInsets:_edgeInsetsCurrent];
|
|
505
520
|
|
|
@@ -832,7 +847,8 @@ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
|
|
|
832
847
|
renderer.strokeColors = colors;
|
|
833
848
|
}
|
|
834
849
|
renderer.animatedOptions = polylineView.animatedOptions;
|
|
835
|
-
|
|
850
|
+
// Static maps snapshot an arbitrary frame; render the full polyline
|
|
851
|
+
renderer.animated = polylineView.animated && !_staticMode;
|
|
836
852
|
polylineView.renderer = renderer;
|
|
837
853
|
return renderer;
|
|
838
854
|
}
|
|
@@ -1361,7 +1377,7 @@ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
|
|
|
1361
1377
|
renderer.strokeColors =
|
|
1362
1378
|
polylineView.strokeColors.count > 1 ? polylineView.strokeColors : nil;
|
|
1363
1379
|
renderer.animatedOptions = polylineView.animatedOptions;
|
|
1364
|
-
renderer.animated = polylineView.animated;
|
|
1380
|
+
renderer.animated = polylineView.animated && !_staticMode;
|
|
1365
1381
|
return;
|
|
1366
1382
|
}
|
|
1367
1383
|
|
|
@@ -1774,11 +1790,11 @@ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
|
|
|
1774
1790
|
} else if (duration > 0) {
|
|
1775
1791
|
CLLocationCoordinate2D center =
|
|
1776
1792
|
CLLocationCoordinate2DMake(latitude, longitude);
|
|
1777
|
-
|
|
1778
|
-
|
|
1793
|
+
MKMapCamera *camera = [_mapView cameraForCenterCoordinate:center
|
|
1794
|
+
zoomLevel:targetZoom];
|
|
1779
1795
|
[UIView animateWithDuration:duration / 1000.0
|
|
1780
1796
|
animations:^{
|
|
1781
|
-
[self->_mapView
|
|
1797
|
+
[self->_mapView setCamera:camera animated:NO];
|
|
1782
1798
|
}];
|
|
1783
1799
|
} else {
|
|
1784
1800
|
[_mapView
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import "StaticMapProviderBase.h"
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Static Apple map rendered with MKMapSnapshotter. The base map renders
|
|
7
|
+
* fully asynchronously (no live MKMapView is ever created), so static maps
|
|
8
|
+
* keep loading while the user scrolls without blocking the main thread.
|
|
9
|
+
*/
|
|
10
|
+
@interface AppleStaticMapProvider : StaticMapProviderBase
|
|
11
|
+
|
|
12
|
+
@end
|
|
13
|
+
|
|
14
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#import "AppleStaticMapProvider.h"
|
|
2
|
+
|
|
3
|
+
using facebook::react::LuggMapViewPoiFilterMode;
|
|
4
|
+
using facebook::react::LuggMapViewTheme;
|
|
5
|
+
|
|
6
|
+
#import "../extensions/MKMapView+Zoom.h"
|
|
7
|
+
#import "../extensions/UIView+Snapshot.h"
|
|
8
|
+
#import "AppleMapProvider.h"
|
|
9
|
+
#import "LuggAnnotationView.h"
|
|
10
|
+
|
|
11
|
+
// Standard MKMarkerAnnotationView balloon size; standalone (off-map) views
|
|
12
|
+
// don't size themselves
|
|
13
|
+
static const CGSize kDefaultMarkerSize = {28, 33};
|
|
14
|
+
|
|
15
|
+
// The rect the snapshot renders: the region for the requested zoom, expanded
|
|
16
|
+
// on the short axis to the view's aspect ratio - the same fit MKMapView
|
|
17
|
+
// applies in setRegion, so static and live maps frame alike. Passing this
|
|
18
|
+
// exact rect to MKMapSnapshotter makes the projection exact.
|
|
19
|
+
static MKMapRect LuggStaticFittedMapRect(CLLocationCoordinate2D center,
|
|
20
|
+
double zoom, CGSize size) {
|
|
21
|
+
MKCoordinateSpan span = LuggCoordinateSpanForZoomLevel(MIN(zoom, 28), center);
|
|
22
|
+
MKMapPoint topLeft = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
|
|
23
|
+
MIN(center.latitude + span.latitudeDelta / 2, 90.0),
|
|
24
|
+
center.longitude - span.longitudeDelta / 2));
|
|
25
|
+
MKMapPoint bottomRight = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
|
|
26
|
+
MAX(center.latitude - span.latitudeDelta / 2, -90.0),
|
|
27
|
+
center.longitude + span.longitudeDelta / 2));
|
|
28
|
+
MKMapRect rect =
|
|
29
|
+
MKMapRectMake(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
|
|
30
|
+
bottomRight.y - topLeft.y);
|
|
31
|
+
|
|
32
|
+
double viewAspect = size.width / size.height;
|
|
33
|
+
double rectAspect = rect.size.width / rect.size.height;
|
|
34
|
+
if (rectAspect > viewAspect) {
|
|
35
|
+
double height = rect.size.width / viewAspect;
|
|
36
|
+
rect.origin.y -= (height - rect.size.height) / 2;
|
|
37
|
+
rect.size.height = height;
|
|
38
|
+
} else {
|
|
39
|
+
double width = rect.size.height * viewAspect;
|
|
40
|
+
rect.origin.x -= (width - rect.size.width) / 2;
|
|
41
|
+
rect.size.width = width;
|
|
42
|
+
}
|
|
43
|
+
return rect;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@interface AppleStaticMapProvider () <MKMapViewDelegate>
|
|
47
|
+
@end
|
|
48
|
+
|
|
49
|
+
@implementation AppleStaticMapProvider {
|
|
50
|
+
MKMapSnapshotter *_snapshotter;
|
|
51
|
+
MKMapView *_warmupMapView;
|
|
52
|
+
BOOL _snapshotReady;
|
|
53
|
+
|
|
54
|
+
BOOL _poiEnabled;
|
|
55
|
+
LuggMapViewPoiFilterMode _poiFilterMode;
|
|
56
|
+
NSArray<NSString *> *_poiFilterCategories;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
- (instancetype)init {
|
|
60
|
+
if (self = [super init]) {
|
|
61
|
+
_poiEnabled = YES;
|
|
62
|
+
_poiFilterMode = LuggMapViewPoiFilterMode::Including;
|
|
63
|
+
_poiFilterCategories = @[];
|
|
64
|
+
}
|
|
65
|
+
return self;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#pragma mark - StaticMapProviderBase
|
|
69
|
+
|
|
70
|
+
- (MKMapRect)mapRectForSize:(CGSize)size {
|
|
71
|
+
return LuggStaticFittedMapRect(self.coordinate, self.zoom, size);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
- (UIView *)newDefaultMarkerOverlayView {
|
|
75
|
+
MKAnnotationView *pin =
|
|
76
|
+
[[LuggMarkerAnnotationView alloc] initWithAnnotation:nil
|
|
77
|
+
reuseIdentifier:nil];
|
|
78
|
+
pin.bounds =
|
|
79
|
+
CGRectMake(0, 0, kDefaultMarkerSize.width, kDefaultMarkerSize.height);
|
|
80
|
+
return pin;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Inverse of LuggStaticFittedMapRect: the pre-fit rect is square in map
|
|
84
|
+
// points with side latitudeDelta * worldHeight / (360 * cos(lat)), and the
|
|
85
|
+
// aspect fit scales it to the view's short side
|
|
86
|
+
- (double)zoomForMapPointsPerPoint:(double)mapPointsPerPoint {
|
|
87
|
+
CGSize size = self.projectedSize;
|
|
88
|
+
double side = mapPointsPerPoint * MIN(size.width, size.height);
|
|
89
|
+
double latitudeDelta = side * 360.0 *
|
|
90
|
+
cos(self.coordinate.latitude * M_PI / 180.0) /
|
|
91
|
+
MKMapSizeWorld.height;
|
|
92
|
+
double zoom = 0.5 + log2(360.0 / latitudeDelta);
|
|
93
|
+
return MAX(MIN(zoom, 28.0), 0.0);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
- (UITraitCollection *)snapshotTraitCollection {
|
|
97
|
+
UITraitCollection *base = self.wrapperView.traitCollection;
|
|
98
|
+
UIUserInterfaceStyle style;
|
|
99
|
+
switch (self.theme) {
|
|
100
|
+
case LuggMapViewTheme::Dark:
|
|
101
|
+
style = UIUserInterfaceStyleDark;
|
|
102
|
+
break;
|
|
103
|
+
case LuggMapViewTheme::Light:
|
|
104
|
+
style = UIUserInterfaceStyleLight;
|
|
105
|
+
break;
|
|
106
|
+
default:
|
|
107
|
+
return base;
|
|
108
|
+
}
|
|
109
|
+
return [UITraitCollection traitCollectionWithTraitsFromCollections:@[
|
|
110
|
+
base, [UITraitCollection traitCollectionWithUserInterfaceStyle:style]
|
|
111
|
+
]];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
- (void)renderBaseMap {
|
|
115
|
+
// MKMapSnapshotter bakes attribution into the image without inset control.
|
|
116
|
+
if (!UIEdgeInsetsEqualToEdgeInsets(self.edgeInsets, UIEdgeInsetsZero)) {
|
|
117
|
+
[self renderInsetBaseMap];
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (_snapshotter)
|
|
122
|
+
return;
|
|
123
|
+
|
|
124
|
+
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
|
|
125
|
+
options.mapRect = self.mapRect;
|
|
126
|
+
options.size = self.projectedSize;
|
|
127
|
+
options.mapType = LuggMKMapTypeFromMapType(self.mapType);
|
|
128
|
+
options.pointOfInterestFilter = LuggPointOfInterestFilter(
|
|
129
|
+
_poiEnabled, _poiFilterMode, _poiFilterCategories);
|
|
130
|
+
options.traitCollection = [self snapshotTraitCollection];
|
|
131
|
+
|
|
132
|
+
MKMapSnapshotter *snapshotter =
|
|
133
|
+
[[MKMapSnapshotter alloc] initWithOptions:options];
|
|
134
|
+
_snapshotter = snapshotter;
|
|
135
|
+
|
|
136
|
+
__weak AppleStaticMapProvider *weakSelf = self;
|
|
137
|
+
[snapshotter startWithQueue:dispatch_get_main_queue()
|
|
138
|
+
completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
|
|
139
|
+
AppleStaticMapProvider *strongSelf = weakSelf;
|
|
140
|
+
if (!strongSelf || strongSelf->_snapshotter != snapshotter)
|
|
141
|
+
return;
|
|
142
|
+
strongSelf->_snapshotter = nil;
|
|
143
|
+
if (error || !snapshot) {
|
|
144
|
+
// Keep the placeholder; resumeAnimations retries (e.g. back
|
|
145
|
+
// online)
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
[strongSelf displayBaseImage:snapshot.image fromCache:NO];
|
|
149
|
+
}];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
- (void)cancelBaseRender {
|
|
153
|
+
[_snapshotter cancel];
|
|
154
|
+
_snapshotter = nil;
|
|
155
|
+
_warmupMapView.delegate = nil;
|
|
156
|
+
[_warmupMapView removeFromSuperview];
|
|
157
|
+
_warmupMapView = nil;
|
|
158
|
+
_snapshotReady = NO;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#pragma mark - Inset snapshots
|
|
162
|
+
|
|
163
|
+
- (void)renderInsetBaseMap {
|
|
164
|
+
if (_warmupMapView) {
|
|
165
|
+
if (!_snapshotReady || !_warmupMapView.window)
|
|
166
|
+
return;
|
|
167
|
+
|
|
168
|
+
UIImageView *imageView = [_warmupMapView lugg_snapshotImageView];
|
|
169
|
+
if (!imageView)
|
|
170
|
+
return;
|
|
171
|
+
|
|
172
|
+
[self displayBaseImage:imageView.image fromCache:NO];
|
|
173
|
+
[self cancelBaseRender];
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
MKMapView *mapView =
|
|
178
|
+
[[MKMapView alloc] initWithFrame:self.wrapperView.bounds];
|
|
179
|
+
mapView.userInteractionEnabled = NO;
|
|
180
|
+
mapView.showsCompass = NO;
|
|
181
|
+
mapView.insetsLayoutMarginsFromSafeArea = NO;
|
|
182
|
+
mapView.layoutMargins = self.edgeInsets;
|
|
183
|
+
mapView.mapType = LuggMKMapTypeFromMapType(self.mapType);
|
|
184
|
+
mapView.pointOfInterestFilter = LuggPointOfInterestFilter(
|
|
185
|
+
_poiEnabled, _poiFilterMode, _poiFilterCategories);
|
|
186
|
+
mapView.overrideUserInterfaceStyle =
|
|
187
|
+
[self snapshotTraitCollection].userInterfaceStyle;
|
|
188
|
+
[mapView setVisibleMapRect:self.mapRect
|
|
189
|
+
edgePadding:UIEdgeInsetsZero
|
|
190
|
+
animated:NO];
|
|
191
|
+
_warmupMapView = mapView;
|
|
192
|
+
mapView.delegate = self;
|
|
193
|
+
[self.wrapperView insertSubview:mapView atIndex:0];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
- (void)mapViewWillStartRenderingMap:(MKMapView *)mapView {
|
|
197
|
+
_snapshotReady = NO;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
- (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView
|
|
201
|
+
fullyRendered:(BOOL)fullyRendered {
|
|
202
|
+
_snapshotReady = fullyRendered;
|
|
203
|
+
[self revealOverlays];
|
|
204
|
+
if (!fullyRendered)
|
|
205
|
+
return;
|
|
206
|
+
|
|
207
|
+
__weak AppleStaticMapProvider *weakSelf = self;
|
|
208
|
+
__weak MKMapView *weakMapView = mapView;
|
|
209
|
+
[[NSRunLoop mainRunLoop]
|
|
210
|
+
performInModes:@[ NSDefaultRunLoopMode ]
|
|
211
|
+
block:^{
|
|
212
|
+
AppleStaticMapProvider *strongSelf = weakSelf;
|
|
213
|
+
if (strongSelf && weakMapView &&
|
|
214
|
+
strongSelf->_warmupMapView == weakMapView)
|
|
215
|
+
[strongSelf renderInsetBaseMap];
|
|
216
|
+
}];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#pragma mark - Props
|
|
220
|
+
|
|
221
|
+
- (void)setPoiEnabled:(BOOL)enabled {
|
|
222
|
+
_poiEnabled = enabled;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
- (void)setPoiFilterMode:(LuggMapViewPoiFilterMode)mode {
|
|
226
|
+
_poiFilterMode = mode;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
- (void)setPoiFilterCategories:(NSArray<NSString *> *)categories {
|
|
230
|
+
_poiFilterCategories = categories;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@end
|
|
@@ -148,13 +148,25 @@ static const NSUInteger kMaxGradientSpans = 512;
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
GMSMutablePath *path = [GMSMutablePath path];
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
CLLocationCoordinate2D lastCoord = self.coordinates.firstObject.coordinate;
|
|
152
|
+
[path addCoordinate:lastCoord];
|
|
153
|
+
for (NSUInteger i = 1; i < self.coordinates.count; i++) {
|
|
154
|
+
CLLocationCoordinate2D coord = self.coordinates[i].coordinate;
|
|
155
|
+
if (coord.latitude == lastCoord.latitude && coord.longitude == lastCoord.longitude) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
[path addCoordinate:coord];
|
|
159
|
+
lastCoord = coord;
|
|
153
160
|
}
|
|
161
|
+
|
|
162
|
+
// Clear stale spans before swapping the path so Google Maps never rebuilds
|
|
163
|
+
// span models against a path with fewer segments (GMSModelStyleBuilder
|
|
164
|
+
// couldNotInstantiate -> EXC_BAD_ACCESS). Reassign spans once the new path is set.
|
|
165
|
+
_polyline.spans = nil;
|
|
154
166
|
_polyline.path = path;
|
|
155
167
|
|
|
156
|
-
if (self.strokeColors.count > 1) {
|
|
157
|
-
_polyline.spans = [self
|
|
168
|
+
if (path.count > 1 && self.strokeColors.count > 1) {
|
|
169
|
+
_polyline.spans = [self createGradientSpansForSegmentCount:path.count - 1];
|
|
158
170
|
} else {
|
|
159
171
|
_polyline.strokeColor = self.strokeColors.firstObject ?: [UIColor blackColor];
|
|
160
172
|
}
|
|
@@ -222,35 +234,44 @@ static const NSUInteger kMaxGradientSpans = 512;
|
|
|
222
234
|
}
|
|
223
235
|
|
|
224
236
|
if (headDist <= tailDist) {
|
|
237
|
+
_polyline.spans = nil;
|
|
225
238
|
_polyline.path = [GMSMutablePath path];
|
|
226
239
|
return;
|
|
227
240
|
}
|
|
228
241
|
|
|
229
|
-
CGFloat visibleLength = headDist - tailDist;
|
|
230
242
|
NSUInteger startIndex = [self indexForDistance:tailDist];
|
|
231
243
|
NSUInteger endIndex = [self indexForDistance:headDist];
|
|
232
244
|
|
|
233
245
|
GMSMutablePath *path = [GMSMutablePath path];
|
|
234
|
-
NSMutableArray<GMSStyleSpan *> *spans = [NSMutableArray array];
|
|
235
246
|
|
|
236
|
-
CLLocationCoordinate2D
|
|
237
|
-
[path addCoordinate:
|
|
247
|
+
CLLocationCoordinate2D lastCoord = [self coordinateAtDistance:tailDist];
|
|
248
|
+
[path addCoordinate:lastCoord];
|
|
238
249
|
|
|
239
250
|
for (NSUInteger i = startIndex + 1; i <= endIndex; i++) {
|
|
240
|
-
|
|
251
|
+
CLLocationCoordinate2D coord = self.coordinates[i].coordinate;
|
|
252
|
+
if (coord.latitude == lastCoord.latitude && coord.longitude == lastCoord.longitude) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
[path addCoordinate:coord];
|
|
256
|
+
lastCoord = coord;
|
|
241
257
|
}
|
|
242
258
|
|
|
243
259
|
CLLocationCoordinate2D endCoord = [self coordinateAtDistance:headDist];
|
|
244
|
-
|
|
245
|
-
(endIndex < self.coordinates.count) ? self.coordinates[endIndex].coordinate : endCoord;
|
|
246
|
-
if (endCoord.latitude != lastAdded.latitude || endCoord.longitude != lastAdded.longitude) {
|
|
260
|
+
if (endCoord.latitude != lastCoord.latitude || endCoord.longitude != lastCoord.longitude) {
|
|
247
261
|
[path addCoordinate:endCoord];
|
|
248
262
|
}
|
|
249
263
|
|
|
250
264
|
NSUInteger pathCount = path.count;
|
|
251
|
-
NSUInteger segmentCount = pathCount - 1;
|
|
265
|
+
NSUInteger segmentCount = (pathCount > 1) ? pathCount - 1 : 0;
|
|
266
|
+
|
|
267
|
+
if (segmentCount == 0) {
|
|
268
|
+
_polyline.spans = nil;
|
|
269
|
+
_polyline.path = path;
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
252
272
|
|
|
253
273
|
if (self.strokeColors.count <= 1) {
|
|
274
|
+
_polyline.spans = nil;
|
|
254
275
|
_polyline.path = path;
|
|
255
276
|
_polyline.strokeColor = self.strokeColors.firstObject ?: [UIColor blackColor];
|
|
256
277
|
return;
|
|
@@ -259,6 +280,7 @@ static const NSUInteger kMaxGradientSpans = 512;
|
|
|
259
280
|
NSUInteger spanCount = MIN(segmentCount, kMaxAnimationSpans);
|
|
260
281
|
double segmentsPerSpan = (double)segmentCount / spanCount;
|
|
261
282
|
|
|
283
|
+
NSMutableArray<GMSStyleSpan *> *spans = [NSMutableArray array];
|
|
262
284
|
for (NSUInteger i = 0; i < spanCount; i++) {
|
|
263
285
|
CGFloat gradientPos = ((CGFloat)i + 0.5) / spanCount;
|
|
264
286
|
UIColor *color = [self colorAtGradientPosition:gradientPos];
|
|
@@ -266,13 +288,16 @@ static const NSUInteger kMaxGradientSpans = 512;
|
|
|
266
288
|
[spans addObject:[GMSStyleSpan spanWithStyle:style segments:segmentsPerSpan]];
|
|
267
289
|
}
|
|
268
290
|
|
|
291
|
+
// Clear stale spans before swapping the path so Google Maps never rebuilds
|
|
292
|
+
// span models against a path with fewer segments (GMSModelStyleBuilder
|
|
293
|
+
// couldNotInstantiate -> EXC_BAD_ACCESS). Reassign spans once the new path is set.
|
|
294
|
+
_polyline.spans = nil;
|
|
269
295
|
_polyline.path = path;
|
|
270
296
|
_polyline.spans = spans;
|
|
271
297
|
}
|
|
272
298
|
|
|
273
|
-
- (NSArray<GMSStyleSpan *> *)
|
|
299
|
+
- (NSArray<GMSStyleSpan *> *)createGradientSpansForSegmentCount:(NSUInteger)segmentCount {
|
|
274
300
|
NSMutableArray<GMSStyleSpan *> *spans = [NSMutableArray array];
|
|
275
|
-
NSUInteger segmentCount = self.coordinates.count - 1;
|
|
276
301
|
NSUInteger spanCount = MIN(segmentCount, kMaxGradientSpans);
|
|
277
302
|
double segmentsPerSpan = (double)segmentCount / spanCount;
|
|
278
303
|
|
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
|
|
4
4
|
NS_ASSUME_NONNULL_BEGIN
|
|
5
5
|
|
|
6
|
+
/// Resolves a mapId prop value ("" or "DEMO_MAP_ID" -> demo map ID),
|
|
7
|
+
/// shared by the live and static Google providers.
|
|
8
|
+
GMSMapID *LuggGMSMapIDFromString(NSString *_Nullable mapId);
|
|
9
|
+
|
|
10
|
+
GMSMapViewType
|
|
11
|
+
LuggGMSMapTypeFromMapType(facebook::react::LuggMapViewMapType mapType);
|
|
12
|
+
|
|
13
|
+
UIUserInterfaceStyle
|
|
14
|
+
LuggInterfaceStyleFromTheme(facebook::react::LuggMapViewTheme theme);
|
|
15
|
+
|
|
6
16
|
@interface GoogleMapProvider : NSObject <MapProvider, GMSMapViewDelegate>
|
|
7
17
|
|
|
8
18
|
@property(nonatomic, copy, nullable) NSString *mapId;
|