@lugg/maps 0.2.0-alpha.3 → 0.2.0-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +21 -3
  2. package/android/src/main/java/com/luggmaps/LuggMapView.kt +265 -0
  3. package/android/src/main/java/com/luggmaps/{LuggGoogleMapViewManager.kt → LuggMapViewManager.kt} +75 -36
  4. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +6 -5
  5. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +136 -14
  6. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +21 -0
  7. package/android/src/main/java/com/luggmaps/LuggPackage.kt +1 -4
  8. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
  9. package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
  10. package/android/src/main/java/com/luggmaps/{LuggGoogleMapView.kt → core/GoogleMapProvider.kt} +251 -241
  11. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +55 -0
  12. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +163 -52
  13. package/ios/LuggMapView.h +9 -0
  14. package/ios/LuggMapView.mm +312 -0
  15. package/ios/LuggMarkerView.h +9 -0
  16. package/ios/LuggMarkerView.mm +79 -0
  17. package/ios/LuggPolylineView.h +4 -0
  18. package/ios/LuggPolylineView.mm +23 -0
  19. package/ios/core/AppleMapProvider.h +15 -0
  20. package/ios/core/AppleMapProvider.mm +664 -0
  21. package/ios/core/GMSPolylineAnimator.h +3 -0
  22. package/ios/core/GMSPolylineAnimator.m +175 -40
  23. package/ios/core/GoogleMapProvider.h +13 -0
  24. package/ios/core/GoogleMapProvider.mm +513 -0
  25. package/ios/core/MKPolylineAnimator.h +4 -0
  26. package/ios/core/MKPolylineAnimator.m +224 -68
  27. package/ios/core/MapProviderDelegate.h +72 -0
  28. package/ios/core/PolylineAnimatorBase.h +24 -1
  29. package/ios/core/PolylineAnimatorBase.m +82 -19
  30. package/ios/extensions/MKMapView+Zoom.h +2 -0
  31. package/ios/extensions/MKMapView+Zoom.m +14 -4
  32. package/lib/module/MapProvider.js +13 -0
  33. package/lib/module/MapProvider.js.map +1 -0
  34. package/lib/module/MapProvider.types.js +4 -0
  35. package/lib/module/MapProvider.types.js.map +1 -0
  36. package/lib/module/MapProvider.web.js +20 -0
  37. package/lib/module/MapProvider.web.js.map +1 -0
  38. package/lib/module/MapView.js +29 -16
  39. package/lib/module/MapView.js.map +1 -1
  40. package/lib/module/MapView.web.js +290 -0
  41. package/lib/module/MapView.web.js.map +1 -0
  42. package/lib/module/components/Marker.js +19 -2
  43. package/lib/module/components/Marker.js.map +1 -1
  44. package/lib/module/components/Marker.web.js +33 -0
  45. package/lib/module/components/Marker.web.js.map +1 -0
  46. package/lib/module/components/Polyline.js +17 -4
  47. package/lib/module/components/Polyline.js.map +1 -1
  48. package/lib/module/components/Polyline.web.js +229 -0
  49. package/lib/module/components/Polyline.web.js.map +1 -0
  50. package/lib/module/components/index.js +2 -2
  51. package/lib/module/components/index.js.map +1 -1
  52. package/lib/module/components/index.web.js +5 -0
  53. package/lib/module/components/index.web.js.map +1 -0
  54. package/lib/module/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +19 -7
  55. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +7 -1
  56. package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  57. package/lib/module/index.js +4 -2
  58. package/lib/module/index.js.map +1 -1
  59. package/lib/module/index.web.js +7 -0
  60. package/lib/module/index.web.js.map +1 -0
  61. package/lib/typescript/src/MapProvider.d.ts +8 -0
  62. package/lib/typescript/src/MapProvider.d.ts.map +1 -0
  63. package/lib/typescript/src/MapProvider.types.d.ts +16 -0
  64. package/lib/typescript/src/MapProvider.types.d.ts.map +1 -0
  65. package/lib/typescript/src/MapProvider.web.d.ts +11 -0
  66. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -0
  67. package/lib/typescript/src/MapView.d.ts +4 -4
  68. package/lib/typescript/src/MapView.d.ts.map +1 -1
  69. package/lib/typescript/src/MapView.types.d.ts +23 -7
  70. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  71. package/lib/typescript/src/MapView.web.d.ts +3 -0
  72. package/lib/typescript/src/MapView.web.d.ts.map +1 -0
  73. package/lib/typescript/src/components/Marker.d.ts +25 -1
  74. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  75. package/lib/typescript/src/components/Marker.web.d.ts +3 -0
  76. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -0
  77. package/lib/typescript/src/components/Polyline.d.ts +36 -1
  78. package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
  79. package/lib/typescript/src/components/Polyline.web.d.ts +3 -0
  80. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -0
  81. package/lib/typescript/src/components/index.d.ts +4 -2
  82. package/lib/typescript/src/components/index.d.ts.map +1 -1
  83. package/lib/typescript/src/components/index.web.d.ts +5 -0
  84. package/lib/typescript/src/components/index.web.d.ts.map +1 -0
  85. package/lib/typescript/src/fabric/{LuggGoogleMapViewNativeComponent.d.ts → LuggMapViewNativeComponent.d.ts} +8 -4
  86. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -0
  87. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +4 -1
  88. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  89. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
  90. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
  91. package/lib/typescript/src/index.d.ts +8 -3
  92. package/lib/typescript/src/index.d.ts.map +1 -1
  93. package/lib/typescript/src/index.web.d.ts +10 -0
  94. package/lib/typescript/src/index.web.d.ts.map +1 -0
  95. package/lib/typescript/src/types.d.ts +4 -0
  96. package/lib/typescript/src/types.d.ts.map +1 -1
  97. package/package.json +17 -3
  98. package/src/MapProvider.tsx +10 -0
  99. package/src/MapProvider.types.ts +16 -0
  100. package/src/MapProvider.web.tsx +14 -0
  101. package/src/MapView.tsx +28 -26
  102. package/src/MapView.types.ts +24 -7
  103. package/src/MapView.web.tsx +364 -0
  104. package/src/components/Marker.tsx +50 -4
  105. package/src/components/Marker.web.tsx +33 -0
  106. package/src/components/Polyline.tsx +51 -2
  107. package/src/components/Polyline.web.tsx +287 -0
  108. package/src/components/index.ts +8 -2
  109. package/src/components/index.web.ts +4 -0
  110. package/src/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +19 -7
  111. package/src/fabric/LuggMarkerViewNativeComponent.ts +7 -1
  112. package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  113. package/src/index.ts +18 -2
  114. package/src/index.web.ts +20 -0
  115. package/src/types.ts +5 -0
  116. package/ios/LuggAppleMapView.h +0 -16
  117. package/ios/LuggAppleMapView.mm +0 -580
  118. package/ios/LuggGoogleMapView.h +0 -13
  119. package/ios/LuggGoogleMapView.mm +0 -454
  120. package/lib/module/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
  121. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts +0 -54
  122. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts.map +0 -1
  123. package/lib/typescript/src/fabric/LuggGoogleMapViewNativeComponent.d.ts.map +0 -1
  124. package/src/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
@@ -0,0 +1,664 @@
1
+ #import "AppleMapProvider.h"
2
+ #import "../LuggMarkerView.h"
3
+ #import "../LuggPolylineView.h"
4
+ #import "../extensions/MKMapView+Zoom.h"
5
+ #import "MKPolylineAnimator.h"
6
+
7
+ @interface AppleMarkerAnnotation : NSObject <MKAnnotation>
8
+ @property(nonatomic, assign) CLLocationCoordinate2D coordinate;
9
+ @property(nonatomic, copy, nullable) NSString *title;
10
+ @property(nonatomic, copy, nullable) NSString *subtitle;
11
+ @property(nonatomic, strong) LuggMarkerView *markerView;
12
+ @property(nonatomic, weak) MKAnnotationView *annotationView;
13
+ @end
14
+
15
+ @implementation AppleMarkerAnnotation
16
+ @end
17
+
18
+ @implementation LuggAppleMapViewContent
19
+ @end
20
+
21
+ @interface AppleMapProvider () <LuggMarkerViewDelegate,
22
+ LuggPolylineViewDelegate>
23
+ @end
24
+
25
+ @implementation AppleMapProvider {
26
+ LuggAppleMapViewContent *_mapView;
27
+ BOOL _isMapReady;
28
+ BOOL _isDragging;
29
+ double _minZoom;
30
+ double _maxZoom;
31
+ NSMapTable<id<MKOverlay>, LuggPolylineView *> *_overlayToPolylineMap;
32
+
33
+ // Edge insets animation
34
+ CADisplayLink *_edgeInsetsDisplayLink;
35
+ UIEdgeInsets _edgeInsetsFrom;
36
+ UIEdgeInsets _edgeInsetsTo;
37
+ CFTimeInterval _edgeInsetsAnimationStart;
38
+ CFTimeInterval _edgeInsetsAnimationDuration;
39
+ }
40
+
41
+ @synthesize delegate = _delegate;
42
+
43
+ - (instancetype)init {
44
+ if (self = [super init]) {
45
+ _overlayToPolylineMap = [NSMapTable strongToWeakObjectsMapTable];
46
+ }
47
+ return self;
48
+ }
49
+
50
+ - (BOOL)isMapReady {
51
+ return _isMapReady;
52
+ }
53
+
54
+ - (MKMapView *)mapView {
55
+ return _mapView;
56
+ }
57
+
58
+ #pragma mark - MapProvider
59
+
60
+ - (void)initializeMapInView:(UIView *)wrapperView
61
+ initialCoordinate:(CLLocationCoordinate2D)coordinate
62
+ initialZoom:(double)zoom {
63
+ if (_mapView)
64
+ return;
65
+
66
+ _mapView = [[LuggAppleMapViewContent alloc] initWithFrame:wrapperView.bounds];
67
+ _mapView.autoresizingMask =
68
+ UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
69
+ _mapView.delegate = self;
70
+ _mapView.insetsLayoutMarginsFromSafeArea = NO;
71
+
72
+ [self applyZoomRange];
73
+
74
+ [wrapperView addSubview:_mapView];
75
+
76
+ MKCoordinateRegion region = [_mapView regionForCenterCoordinate:coordinate
77
+ zoomLevel:zoom];
78
+ [_mapView setRegion:region animated:NO];
79
+
80
+ _isMapReady = YES;
81
+
82
+ [_delegate mapProviderDidReady];
83
+ }
84
+
85
+ - (void)destroy {
86
+ [self stopEdgeInsetsAnimation];
87
+ [_mapView removeFromSuperview];
88
+ _mapView = nil;
89
+ _isMapReady = NO;
90
+ }
91
+
92
+ #pragma mark - Props
93
+
94
+ - (void)setZoomEnabled:(BOOL)enabled {
95
+ _mapView.zoomEnabled = enabled;
96
+ }
97
+
98
+ - (void)setScrollEnabled:(BOOL)enabled {
99
+ _mapView.scrollEnabled = enabled;
100
+ }
101
+
102
+ - (void)setRotateEnabled:(BOOL)enabled {
103
+ _mapView.rotateEnabled = enabled;
104
+ }
105
+
106
+ - (void)setPitchEnabled:(BOOL)enabled {
107
+ _mapView.pitchEnabled = enabled;
108
+ }
109
+
110
+ - (void)setUserLocationEnabled:(BOOL)enabled {
111
+ _mapView.showsUserLocation = enabled;
112
+ }
113
+
114
+ - (void)setTheme:(NSInteger)theme {
115
+ switch (theme) {
116
+ case 1: // Dark
117
+ _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
118
+ break;
119
+ case 0: // Light
120
+ _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
121
+ break;
122
+ default: // System
123
+ _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
124
+ break;
125
+ }
126
+ }
127
+
128
+ - (void)setMinZoom:(double)minZoom {
129
+ _minZoom = minZoom;
130
+ [self applyZoomRange];
131
+ }
132
+
133
+ - (void)setMaxZoom:(double)maxZoom {
134
+ _maxZoom = maxZoom;
135
+ [self applyZoomRange];
136
+ }
137
+
138
+ - (void)setEdgeInsets:(UIEdgeInsets)edgeInsets
139
+ oldEdgeInsets:(UIEdgeInsets)oldEdgeInsets {
140
+ CGFloat oldOffsetX = (oldEdgeInsets.left - oldEdgeInsets.right) / 2.0;
141
+ CGFloat oldOffsetY = (oldEdgeInsets.top - oldEdgeInsets.bottom) / 2.0;
142
+ CGFloat newOffsetX = (edgeInsets.left - edgeInsets.right) / 2.0;
143
+ CGFloat newOffsetY = (edgeInsets.top - edgeInsets.bottom) / 2.0;
144
+
145
+ CGFloat deltaX = newOffsetX - oldOffsetX;
146
+ CGFloat deltaY = newOffsetY - oldOffsetY;
147
+
148
+ _mapView.layoutMargins = edgeInsets;
149
+
150
+ if (deltaX != 0 || deltaY != 0) {
151
+ CLLocationCoordinate2D currentCenter = _mapView.centerCoordinate;
152
+ CGPoint centerPoint = [_mapView convertCoordinate:currentCenter
153
+ toPointToView:_mapView];
154
+ CGPoint newPoint =
155
+ CGPointMake(centerPoint.x - deltaX, centerPoint.y - deltaY);
156
+ CLLocationCoordinate2D newCenter = [_mapView convertPoint:newPoint
157
+ toCoordinateFromView:_mapView];
158
+ [_mapView setCenterCoordinate:newCenter animated:NO];
159
+ }
160
+ }
161
+
162
+ - (void)setEdgeInsets:(UIEdgeInsets)edgeInsets
163
+ oldEdgeInsets:(UIEdgeInsets)oldEdgeInsets
164
+ duration:(double)duration {
165
+ [self stopEdgeInsetsAnimation];
166
+
167
+ if (duration != 0 && _mapView) {
168
+ double actualDuration = duration < 0 ? 0.3 : duration / 1000.0;
169
+ _edgeInsetsFrom = oldEdgeInsets;
170
+ _edgeInsetsTo = edgeInsets;
171
+ _edgeInsetsAnimationDuration = actualDuration;
172
+ _edgeInsetsAnimationStart = CACurrentMediaTime();
173
+
174
+ _edgeInsetsDisplayLink = [CADisplayLink
175
+ displayLinkWithTarget:self
176
+ selector:@selector(edgeInsetsAnimationTick:)];
177
+ [_edgeInsetsDisplayLink addToRunLoop:[NSRunLoop mainRunLoop]
178
+ forMode:NSRunLoopCommonModes];
179
+ } else {
180
+ [self setEdgeInsets:edgeInsets oldEdgeInsets:oldEdgeInsets];
181
+ }
182
+ }
183
+
184
+ - (void)edgeInsetsAnimationTick:(CADisplayLink *)displayLink {
185
+ CFTimeInterval elapsed = CACurrentMediaTime() - _edgeInsetsAnimationStart;
186
+ CGFloat progress = MIN(elapsed / _edgeInsetsAnimationDuration, 1.0);
187
+
188
+ // Ease out cubic
189
+ CGFloat t = 1.0 - (1.0 - progress) * (1.0 - progress) * (1.0 - progress);
190
+
191
+ UIEdgeInsets current = UIEdgeInsetsMake(
192
+ _edgeInsetsFrom.top + (_edgeInsetsTo.top - _edgeInsetsFrom.top) * t,
193
+ _edgeInsetsFrom.left + (_edgeInsetsTo.left - _edgeInsetsFrom.left) * t,
194
+ _edgeInsetsFrom.bottom +
195
+ (_edgeInsetsTo.bottom - _edgeInsetsFrom.bottom) * t,
196
+ _edgeInsetsFrom.right +
197
+ (_edgeInsetsTo.right - _edgeInsetsFrom.right) * t);
198
+
199
+ [self setEdgeInsets:current oldEdgeInsets:_mapView.layoutMargins];
200
+
201
+ if (progress >= 1.0) {
202
+ [self stopEdgeInsetsAnimation];
203
+ }
204
+ }
205
+
206
+ - (void)stopEdgeInsetsAnimation {
207
+ [_edgeInsetsDisplayLink invalidate];
208
+ _edgeInsetsDisplayLink = nil;
209
+ }
210
+
211
+ - (CLLocationDistance)cameraDistanceForZoomLevel:(double)zoomLevel {
212
+ return 128000000.0 / pow(2, zoomLevel);
213
+ }
214
+
215
+ - (void)applyZoomRange {
216
+ if (!_mapView)
217
+ return;
218
+
219
+ CLLocationDistance minDistance =
220
+ _maxZoom > 0 ? [self cameraDistanceForZoomLevel:_maxZoom] : 0;
221
+ CLLocationDistance maxDistance =
222
+ _minZoom > 0 ? [self cameraDistanceForZoomLevel:_minZoom] : -1;
223
+
224
+ MKMapCameraZoomRange *zoomRange = [[MKMapCameraZoomRange alloc]
225
+ initWithMinCenterCoordinateDistance:minDistance
226
+ maxCenterCoordinateDistance:maxDistance];
227
+ _mapView.cameraZoomRange = zoomRange;
228
+ }
229
+
230
+ #pragma mark - MKMapViewDelegate
231
+
232
+ - (BOOL)isUserInteracting {
233
+ UIView *mapContainerView = _mapView.subviews.firstObject;
234
+ for (UIGestureRecognizer *gesture in mapContainerView.gestureRecognizers) {
235
+ if (gesture.state == UIGestureRecognizerStateBegan ||
236
+ gesture.state == UIGestureRecognizerStateChanged) {
237
+ return YES;
238
+ }
239
+ }
240
+ return NO;
241
+ }
242
+
243
+ - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
244
+ _isDragging = [self isUserInteracting];
245
+ if (_isDragging) {
246
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
247
+ .objectEnumerator) {
248
+ MKPolylineAnimator *renderer =
249
+ (MKPolylineAnimator *)polylineView.renderer;
250
+ [renderer pause];
251
+ }
252
+ }
253
+ }
254
+
255
+ - (void)mapViewDidChangeVisibleRegion:(MKMapView *)mapView {
256
+ [_delegate mapProviderDidMoveCamera:mapView.centerCoordinate.latitude
257
+ longitude:mapView.centerCoordinate.longitude
258
+ zoom:mapView.zoomLevel
259
+ gesture:_isDragging];
260
+ }
261
+
262
+ - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
263
+ BOOL wasDragging = _isDragging;
264
+ _isDragging = NO;
265
+ if (wasDragging) {
266
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
267
+ .objectEnumerator) {
268
+ MKPolylineAnimator *renderer =
269
+ (MKPolylineAnimator *)polylineView.renderer;
270
+ [renderer resume];
271
+ }
272
+ }
273
+ [_delegate mapProviderDidIdleCamera:mapView.centerCoordinate.latitude
274
+ longitude:mapView.centerCoordinate.longitude
275
+ zoom:mapView.zoomLevel
276
+ gesture:wasDragging];
277
+ }
278
+
279
+ - (MKAnnotationView *)mapView:(MKMapView *)mapView
280
+ viewForAnnotation:(id<MKAnnotation>)annotation {
281
+ if (![annotation isKindOfClass:[AppleMarkerAnnotation class]]) {
282
+ return nil;
283
+ }
284
+
285
+ AppleMarkerAnnotation *markerAnnotation = (AppleMarkerAnnotation *)annotation;
286
+ LuggMarkerView *markerView = markerAnnotation.markerView;
287
+
288
+ if (!markerView || !markerView.hasCustomView) {
289
+ return nil;
290
+ }
291
+
292
+ MKAnnotationView *annotationView =
293
+ [[MKAnnotationView alloc] initWithAnnotation:annotation
294
+ reuseIdentifier:nil];
295
+ annotationView.canShowCallout = YES;
296
+ annotationView.displayPriority = MKFeatureDisplayPriorityRequired;
297
+ annotationView.layer.zPosition = markerView.zIndex;
298
+ annotationView.zPriority = markerView.zIndex;
299
+
300
+ if (!markerView.rasterize) {
301
+ UIView *iconView = markerView.iconView;
302
+ [iconView removeFromSuperview];
303
+ [annotationView addSubview:iconView];
304
+ }
305
+
306
+ [self applyMarkerStyle:markerView annotationView:annotationView];
307
+ markerAnnotation.annotationView = annotationView;
308
+
309
+ return annotationView;
310
+ }
311
+
312
+ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView
313
+ rendererForOverlay:(id<MKOverlay>)overlay {
314
+ if ([overlay isKindOfClass:[MKPolyline class]]) {
315
+ LuggPolylineView *polylineView =
316
+ [_overlayToPolylineMap objectForKey:overlay];
317
+ MKPolyline *polyline = (MKPolyline *)overlay;
318
+
319
+ if (polylineView) {
320
+ NSArray<UIColor *> *colors = polylineView.strokeColors;
321
+
322
+ MKPolylineAnimator *renderer =
323
+ [[MKPolylineAnimator alloc] initWithPolyline:polyline];
324
+ renderer.lineWidth = polylineView.strokeWidth;
325
+ renderer.strokeColor = colors.firstObject;
326
+ if (colors.count > 1) {
327
+ renderer.strokeColors = colors;
328
+ }
329
+ renderer.animatedOptions = polylineView.animatedOptions;
330
+ renderer.animated = polylineView.animated;
331
+ polylineView.renderer = renderer;
332
+ return renderer;
333
+ }
334
+
335
+ MKPolylineRenderer *renderer =
336
+ [[MKPolylineRenderer alloc] initWithPolyline:polyline];
337
+ return renderer;
338
+ }
339
+ return nil;
340
+ }
341
+
342
+ #pragma mark - MarkerViewDelegate
343
+
344
+ - (void)markerViewDidLayout:(LuggMarkerView *)markerView {
345
+ AppleMarkerAnnotation *annotation =
346
+ (AppleMarkerAnnotation *)markerView.marker;
347
+ if (annotation) {
348
+ [self updateAnnotationViewFrame:annotation];
349
+ }
350
+ }
351
+
352
+ - (void)markerViewDidUpdate:(LuggMarkerView *)markerView {
353
+ AppleMarkerAnnotation *annotation =
354
+ (AppleMarkerAnnotation *)markerView.marker;
355
+
356
+ if (!annotation)
357
+ return;
358
+
359
+ annotation.coordinate = markerView.coordinate;
360
+ annotation.title = markerView.title;
361
+ annotation.subtitle = markerView.markerDescription;
362
+
363
+ MKAnnotationView *annotationView = annotation.annotationView;
364
+ if (annotationView) {
365
+ annotationView.layer.zPosition = markerView.zIndex;
366
+ annotationView.zPriority = markerView.zIndex;
367
+ }
368
+
369
+ [self updateAnnotationViewFrame:annotation];
370
+ }
371
+
372
+ #pragma mark - PolylineViewDelegate
373
+
374
+ - (void)polylineViewDidUpdate:(LuggPolylineView *)polylineView {
375
+ [self syncPolylineView:polylineView];
376
+ }
377
+
378
+ #pragma mark - Marker Management
379
+
380
+ - (void)addMarkerView:(LuggMarkerView *)markerView {
381
+ markerView.delegate = self;
382
+
383
+ AppleMarkerAnnotation *annotation = [[AppleMarkerAnnotation alloc] init];
384
+ annotation.markerView = markerView;
385
+ markerView.marker = annotation;
386
+
387
+ if (_mapView) {
388
+ [_mapView addAnnotation:annotation];
389
+ }
390
+
391
+ [self markerViewDidUpdate:markerView];
392
+ }
393
+
394
+ - (void)removeMarkerView:(LuggMarkerView *)markerView {
395
+ markerView.delegate = nil;
396
+
397
+ AppleMarkerAnnotation *annotation =
398
+ (AppleMarkerAnnotation *)markerView.marker;
399
+
400
+ if (annotation) {
401
+ annotation.annotationView.transform = CGAffineTransformIdentity;
402
+ annotation.markerView = nil;
403
+ annotation.annotationView = nil;
404
+ [_mapView removeAnnotation:annotation];
405
+ markerView.marker = nil;
406
+ }
407
+ [markerView resetIconViewTransform];
408
+ }
409
+
410
+ - (void)syncMarkerView:(LuggMarkerView *)markerView {
411
+ [self markerViewDidUpdate:markerView];
412
+ }
413
+
414
+ - (void)applyMarkerStyle:(LuggMarkerView *)markerView
415
+ annotationView:(MKAnnotationView *)annotationView {
416
+ annotationView.transform = CGAffineTransformIdentity;
417
+
418
+ UIView *iconView = markerView.iconView;
419
+ CGRect frame = iconView.frame;
420
+ if (frame.size.width <= 0 || frame.size.height <= 0)
421
+ return;
422
+
423
+ CGFloat scale = markerView.scale;
424
+ CGPoint anchor = markerView.anchor;
425
+
426
+ if (markerView.rasterize) {
427
+ annotationView.image = [markerView createScaledIconImage];
428
+ } else {
429
+ iconView.layer.anchorPoint = anchor;
430
+ iconView.transform = CGAffineTransformMakeScale(scale, scale);
431
+ iconView.frame =
432
+ CGRectMake(frame.size.width * (0.5 - anchor.x) * (scale - 1),
433
+ frame.size.height * (0.5 - anchor.y) * (scale - 1),
434
+ frame.size.width, frame.size.height);
435
+ }
436
+
437
+ annotationView.bounds =
438
+ CGRectMake(0, 0, frame.size.width * scale, frame.size.height * scale);
439
+ annotationView.centerOffset =
440
+ CGPointMake(frame.size.width * scale * (anchor.x - 0.5),
441
+ -frame.size.height * scale * (anchor.y - 0.5));
442
+ annotationView.transform =
443
+ CGAffineTransformMakeRotation(markerView.rotate * M_PI / 180.0);
444
+ }
445
+
446
+ - (void)updateAnnotationViewFrame:(AppleMarkerAnnotation *)annotation {
447
+ MKAnnotationView *annotationView = annotation.annotationView;
448
+ LuggMarkerView *markerView = annotation.markerView;
449
+
450
+ if (!annotationView || !markerView)
451
+ return;
452
+
453
+ [self applyMarkerStyle:markerView annotationView:annotationView];
454
+ }
455
+
456
+ #pragma mark - Polyline Management
457
+
458
+ - (void)addPolylineView:(LuggPolylineView *)polylineView {
459
+ polylineView.delegate = self;
460
+ [self addPolylineOverlayToMap:polylineView];
461
+ }
462
+
463
+ - (void)removePolylineView:(LuggPolylineView *)polylineView {
464
+ polylineView.delegate = nil;
465
+ MKPolyline *polyline = (MKPolyline *)polylineView.polyline;
466
+ if (polyline) {
467
+ [_overlayToPolylineMap removeObjectForKey:polyline];
468
+ [_mapView removeOverlay:polyline];
469
+ polylineView.polyline = nil;
470
+ }
471
+ }
472
+
473
+ - (void)syncPolylineView:(LuggPolylineView *)polylineView {
474
+ if (!_mapView)
475
+ return;
476
+
477
+ MKPolylineAnimator *renderer = (MKPolylineAnimator *)polylineView.renderer;
478
+ MKPolyline *oldPolyline = (MKPolyline *)polylineView.polyline;
479
+
480
+ NSArray<CLLocation *> *coordinates = polylineView.coordinates;
481
+ if (coordinates.count == 0) {
482
+ if (renderer) {
483
+ renderer.animated = NO;
484
+ }
485
+ if (oldPolyline) {
486
+ [_overlayToPolylineMap removeObjectForKey:oldPolyline];
487
+ [_mapView removeOverlay:oldPolyline];
488
+ polylineView.polyline = nil;
489
+ polylineView.renderer = nil;
490
+ }
491
+ return;
492
+ }
493
+
494
+ CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(
495
+ sizeof(CLLocationCoordinate2D) * coordinates.count);
496
+ for (NSUInteger i = 0; i < coordinates.count; i++) {
497
+ coords[i] = coordinates[i].coordinate;
498
+ }
499
+ MKPolyline *newPolyline =
500
+ [MKPolyline polylineWithCoordinates:coords count:coordinates.count];
501
+ free(coords);
502
+
503
+ polylineView.polyline = newPolyline;
504
+ [_overlayToPolylineMap setObject:polylineView forKey:newPolyline];
505
+
506
+ if (renderer && oldPolyline) {
507
+ [_overlayToPolylineMap removeObjectForKey:oldPolyline];
508
+ [_mapView removeOverlay:oldPolyline];
509
+ [self insertOverlay:newPolyline withZIndex:polylineView.zIndex];
510
+ [renderer updatePolyline:newPolyline];
511
+ renderer.lineWidth = polylineView.strokeWidth;
512
+ renderer.strokeColor = polylineView.strokeColors.firstObject;
513
+ renderer.strokeColors =
514
+ polylineView.strokeColors.count > 1 ? polylineView.strokeColors : nil;
515
+ renderer.animatedOptions = polylineView.animatedOptions;
516
+ renderer.animated = polylineView.animated;
517
+ return;
518
+ }
519
+
520
+ if (oldPolyline) {
521
+ [_overlayToPolylineMap removeObjectForKey:oldPolyline];
522
+ [_mapView removeOverlay:oldPolyline];
523
+ }
524
+ [self insertOverlay:newPolyline withZIndex:polylineView.zIndex];
525
+ }
526
+
527
+ - (void)addPolylineOverlayToMap:(LuggPolylineView *)polylineView {
528
+ if (!_mapView)
529
+ return;
530
+
531
+ NSArray<CLLocation *> *coordinates = polylineView.coordinates;
532
+ if (coordinates.count == 0)
533
+ return;
534
+
535
+ CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(
536
+ sizeof(CLLocationCoordinate2D) * coordinates.count);
537
+ for (NSUInteger i = 0; i < coordinates.count; i++) {
538
+ coords[i] = coordinates[i].coordinate;
539
+ }
540
+
541
+ MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords
542
+ count:coordinates.count];
543
+ free(coords);
544
+
545
+ polylineView.polyline = polyline;
546
+ [_overlayToPolylineMap setObject:polylineView forKey:polyline];
547
+ [self insertOverlay:polyline withZIndex:polylineView.zIndex];
548
+ }
549
+
550
+ - (void)insertOverlay:(id<MKOverlay>)overlay withZIndex:(NSInteger)zIndex {
551
+ if (zIndex == 0) {
552
+ [_mapView addOverlay:overlay];
553
+ return;
554
+ }
555
+
556
+ NSArray<id<MKOverlay>> *overlays = _mapView.overlays;
557
+ NSInteger insertIndex = overlays.count;
558
+
559
+ for (NSInteger i = 0; i < overlays.count; i++) {
560
+ LuggPolylineView *existingPolylineView =
561
+ [_overlayToPolylineMap objectForKey:overlays[i]];
562
+ if (existingPolylineView && existingPolylineView.zIndex > zIndex) {
563
+ insertIndex = i;
564
+ break;
565
+ }
566
+ }
567
+
568
+ [_mapView insertOverlay:overlay atIndex:insertIndex];
569
+ }
570
+
571
+ #pragma mark - Lifecycle
572
+
573
+ - (void)pauseAnimations {
574
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
575
+ .objectEnumerator) {
576
+ MKPolylineAnimator *renderer = (MKPolylineAnimator *)polylineView.renderer;
577
+ [renderer pause];
578
+ }
579
+ }
580
+
581
+ - (void)resumeAnimations {
582
+ for (LuggPolylineView *polylineView in _overlayToPolylineMap
583
+ .objectEnumerator) {
584
+ MKPolylineAnimator *renderer = (MKPolylineAnimator *)polylineView.renderer;
585
+ [renderer resume];
586
+ }
587
+ }
588
+
589
+ #pragma mark - Commands
590
+
591
+ - (void)moveCamera:(double)latitude
592
+ longitude:(double)longitude
593
+ zoom:(double)zoom
594
+ duration:(double)duration {
595
+ if (!_mapView)
596
+ return;
597
+
598
+ double targetZoom = zoom > 0 ? zoom : _mapView.zoomLevel;
599
+
600
+ if (duration < 0) {
601
+ [_mapView
602
+ setCenterCoordinate:CLLocationCoordinate2DMake(latitude, longitude)
603
+ zoomLevel:targetZoom
604
+ animated:YES];
605
+ } else if (duration > 0) {
606
+ CLLocationCoordinate2D center =
607
+ CLLocationCoordinate2DMake(latitude, longitude);
608
+ MKCoordinateRegion region = [_mapView regionForCenterCoordinate:center
609
+ zoomLevel:targetZoom];
610
+ [UIView animateWithDuration:duration / 1000.0
611
+ animations:^{
612
+ [self->_mapView setRegion:region animated:NO];
613
+ }];
614
+ } else {
615
+ [_mapView
616
+ setCenterCoordinate:CLLocationCoordinate2DMake(latitude, longitude)
617
+ zoomLevel:targetZoom
618
+ animated:NO];
619
+ }
620
+ }
621
+
622
+ - (void)fitCoordinates:(NSArray *)coordinates
623
+ edgeInsetsTop:(double)edgeInsetsTop
624
+ edgeInsetsLeft:(double)edgeInsetsLeft
625
+ edgeInsetsBottom:(double)edgeInsetsBottom
626
+ edgeInsetsRight:(double)edgeInsetsRight
627
+ duration:(double)duration {
628
+ if (!_mapView || coordinates.count == 0)
629
+ return;
630
+
631
+ CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(
632
+ sizeof(CLLocationCoordinate2D) * coordinates.count);
633
+ for (NSUInteger i = 0; i < coordinates.count; i++) {
634
+ NSDictionary *coord = coordinates[i];
635
+ coords[i] = CLLocationCoordinate2DMake([coord[@"latitude"] doubleValue],
636
+ [coord[@"longitude"] doubleValue]);
637
+ }
638
+
639
+ MKMapRect mapRect = MKMapRectNull;
640
+ for (NSUInteger i = 0; i < coordinates.count; i++) {
641
+ MKMapPoint point = MKMapPointForCoordinate(coords[i]);
642
+ MKMapRect pointRect = MKMapRectMake(point.x, point.y, 0, 0);
643
+ mapRect = MKMapRectUnion(mapRect, pointRect);
644
+ }
645
+ free(coords);
646
+
647
+ UIEdgeInsets insets = UIEdgeInsetsMake(edgeInsetsTop, edgeInsetsLeft,
648
+ edgeInsetsBottom, edgeInsetsRight);
649
+
650
+ if (duration < 0) {
651
+ [_mapView setVisibleMapRect:mapRect edgePadding:insets animated:YES];
652
+ } else if (duration > 0) {
653
+ [UIView animateWithDuration:duration / 1000.0
654
+ animations:^{
655
+ [self->_mapView setVisibleMapRect:mapRect
656
+ edgePadding:insets
657
+ animated:NO];
658
+ }];
659
+ } else {
660
+ [_mapView setVisibleMapRect:mapRect edgePadding:insets animated:NO];
661
+ }
662
+ }
663
+
664
+ @end
@@ -5,7 +5,10 @@
5
5
 
6
6
  @property(nonatomic, weak) GMSPolyline *polyline;
7
7
  @property(nonatomic, assign) BOOL animated;
8
+ @property(nonatomic, strong) PolylineAnimatedOptions *animatedOptions;
8
9
 
9
10
  - (void)update;
11
+ - (void)pause;
12
+ - (void)resume;
10
13
 
11
14
  @end