@lugg/maps 0.2.0-alpha.9 → 1.0.0-beta.1

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 (184) hide show
  1. package/README.md +21 -20
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +74 -0
  4. package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +38 -0
  5. package/android/src/main/java/com/luggmaps/LuggMapView.kt +290 -0
  6. package/android/src/main/java/com/luggmaps/{LuggGoogleMapViewManager.kt → LuggMapViewManager.kt} +99 -36
  7. package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +11 -14
  8. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +187 -21
  9. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +28 -0
  10. package/android/src/main/java/com/luggmaps/LuggPackage.kt +8 -4
  11. package/android/src/main/java/com/luggmaps/LuggPolygonView.kt +85 -0
  12. package/android/src/main/java/com/luggmaps/LuggPolygonViewManager.kt +100 -0
  13. package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
  14. package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
  15. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +874 -0
  16. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +60 -0
  17. package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +89 -24
  18. package/android/src/main/java/com/luggmaps/events/LongPressEvent.kt +29 -0
  19. package/android/src/main/java/com/luggmaps/events/MarkerDragEvent.kt +41 -0
  20. package/android/src/main/java/com/luggmaps/events/MarkerPressEvent.kt +34 -0
  21. package/android/src/main/java/com/luggmaps/events/PolygonPressEvent.kt +12 -0
  22. package/android/src/main/java/com/luggmaps/events/PressEvent.kt +29 -0
  23. package/ios/LuggCalloutView.h +23 -0
  24. package/ios/LuggCalloutView.mm +145 -0
  25. package/ios/LuggMapView.h +9 -0
  26. package/ios/LuggMapView.mm +343 -0
  27. package/ios/LuggMarkerView.h +15 -0
  28. package/ios/LuggMarkerView.mm +136 -2
  29. package/ios/LuggPolygonView.h +31 -0
  30. package/ios/LuggPolygonView.mm +151 -0
  31. package/ios/LuggPolylineView.h +4 -0
  32. package/ios/LuggPolylineView.mm +23 -0
  33. package/ios/core/AppleMapProvider.h +15 -0
  34. package/ios/core/AppleMapProvider.mm +1173 -0
  35. package/ios/core/GMSPolylineAnimator.h +3 -0
  36. package/ios/core/GMSPolylineAnimator.m +101 -15
  37. package/ios/core/GoogleMapProvider.h +13 -0
  38. package/ios/core/GoogleMapProvider.mm +798 -0
  39. package/ios/core/LuggAnnotationView.h +12 -0
  40. package/ios/core/LuggAnnotationView.mm +55 -0
  41. package/ios/core/MKPolylineAnimator.h +4 -0
  42. package/ios/core/MKPolylineAnimator.m +167 -42
  43. package/ios/core/MapProviderDelegate.h +84 -0
  44. package/ios/core/PolylineAnimatorBase.h +24 -1
  45. package/ios/core/PolylineAnimatorBase.m +82 -19
  46. package/ios/events/LongPressEvent.h +29 -0
  47. package/ios/events/MarkerDragEvent.h +69 -0
  48. package/ios/events/MarkerPressEvent.h +29 -0
  49. package/ios/events/PolygonPressEvent.h +20 -0
  50. package/ios/events/PressEvent.h +29 -0
  51. package/ios/extensions/MKMapView+Zoom.h +2 -0
  52. package/ios/extensions/MKMapView+Zoom.m +14 -4
  53. package/lib/module/MapProvider.js +2 -4
  54. package/lib/module/MapProvider.js.map +1 -1
  55. package/lib/module/MapProvider.web.js +14 -7
  56. package/lib/module/MapProvider.web.js.map +1 -1
  57. package/lib/module/MapView.js +33 -16
  58. package/lib/module/MapView.js.map +1 -1
  59. package/lib/module/MapView.web.js +296 -181
  60. package/lib/module/MapView.web.js.map +1 -1
  61. package/lib/module/components/GeoJson.js +159 -0
  62. package/lib/module/components/GeoJson.js.map +1 -0
  63. package/lib/module/components/GeoJson.types.js +4 -0
  64. package/lib/module/components/GeoJson.types.js.map +1 -0
  65. package/lib/module/components/Marker.js +49 -8
  66. package/lib/module/components/Marker.js.map +1 -1
  67. package/lib/module/components/Marker.types.js +4 -0
  68. package/lib/module/components/Marker.types.js.map +1 -0
  69. package/lib/module/components/Marker.web.js +159 -24
  70. package/lib/module/components/Marker.web.js.map +1 -1
  71. package/lib/module/components/Polygon.js +46 -0
  72. package/lib/module/components/Polygon.js.map +1 -0
  73. package/lib/module/components/Polygon.types.js +4 -0
  74. package/lib/module/components/Polygon.types.js.map +1 -0
  75. package/lib/module/components/Polygon.web.js +87 -0
  76. package/lib/module/components/Polygon.web.js.map +1 -0
  77. package/lib/module/components/Polyline.js +17 -4
  78. package/lib/module/components/Polyline.js.map +1 -1
  79. package/lib/module/components/Polyline.types.js +4 -0
  80. package/lib/module/components/Polyline.types.js.map +1 -0
  81. package/lib/module/components/Polyline.web.js +108 -31
  82. package/lib/module/components/Polyline.web.js.map +1 -1
  83. package/lib/module/components/index.js +4 -2
  84. package/lib/module/components/index.js.map +1 -1
  85. package/lib/module/components/index.web.js +2 -0
  86. package/lib/module/components/index.web.js.map +1 -1
  87. package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +20 -0
  88. package/lib/module/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
  89. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +49 -1
  90. package/lib/module/fabric/LuggPolygonViewNativeComponent.ts +25 -0
  91. package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  92. package/lib/module/index.js +4 -1
  93. package/lib/module/index.js.map +1 -1
  94. package/lib/module/index.web.js +4 -1
  95. package/lib/module/index.web.js.map +1 -1
  96. package/lib/typescript/src/MapProvider.d.ts +1 -1
  97. package/lib/typescript/src/MapProvider.d.ts.map +1 -1
  98. package/lib/typescript/src/MapProvider.web.d.ts +23 -1
  99. package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
  100. package/lib/typescript/src/MapView.d.ts +4 -4
  101. package/lib/typescript/src/MapView.d.ts.map +1 -1
  102. package/lib/typescript/src/MapView.types.d.ts +35 -9
  103. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  104. package/lib/typescript/src/MapView.web.d.ts +2 -11
  105. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  106. package/lib/typescript/src/components/GeoJson.d.ts +4 -0
  107. package/lib/typescript/src/components/GeoJson.d.ts.map +1 -0
  108. package/lib/typescript/src/components/GeoJson.types.d.ts +89 -0
  109. package/lib/typescript/src/components/GeoJson.types.d.ts.map +1 -0
  110. package/lib/typescript/src/components/Marker.d.ts +6 -33
  111. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  112. package/lib/typescript/src/components/Marker.types.d.ts +100 -0
  113. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -0
  114. package/lib/typescript/src/components/Marker.web.d.ts +2 -5
  115. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
  116. package/lib/typescript/src/components/Polygon.d.ts +10 -0
  117. package/lib/typescript/src/components/Polygon.d.ts.map +1 -0
  118. package/lib/typescript/src/components/Polygon.types.d.ts +33 -0
  119. package/lib/typescript/src/components/Polygon.types.d.ts.map +1 -0
  120. package/lib/typescript/src/components/Polygon.web.d.ts +3 -0
  121. package/lib/typescript/src/components/Polygon.web.d.ts.map +1 -0
  122. package/lib/typescript/src/components/Polyline.d.ts +6 -21
  123. package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
  124. package/lib/typescript/src/components/Polyline.types.d.ts +53 -0
  125. package/lib/typescript/src/components/Polyline.types.d.ts.map +1 -0
  126. package/lib/typescript/src/components/Polyline.web.d.ts +2 -5
  127. package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -1
  128. package/lib/typescript/src/components/index.d.ts +8 -2
  129. package/lib/typescript/src/components/index.d.ts.map +1 -1
  130. package/lib/typescript/src/components/index.web.d.ts +6 -2
  131. package/lib/typescript/src/components/index.web.d.ts.map +1 -1
  132. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +13 -0
  133. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts.map +1 -0
  134. package/lib/typescript/src/fabric/{LuggGoogleMapViewNativeComponent.d.ts → LuggMapViewNativeComponent.d.ts} +30 -4
  135. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -0
  136. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +45 -1
  137. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  138. package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts +18 -0
  139. package/lib/typescript/src/fabric/LuggPolygonViewNativeComponent.d.ts.map +1 -0
  140. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
  141. package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
  142. package/lib/typescript/src/index.d.ts +11 -3
  143. package/lib/typescript/src/index.d.ts.map +1 -1
  144. package/lib/typescript/src/index.web.d.ts +9 -1
  145. package/lib/typescript/src/index.web.d.ts.map +1 -1
  146. package/lib/typescript/src/types.d.ts +11 -0
  147. package/lib/typescript/src/types.d.ts.map +1 -1
  148. package/package.json +11 -9
  149. package/src/MapProvider.tsx +1 -3
  150. package/src/MapProvider.web.tsx +22 -3
  151. package/src/MapView.tsx +32 -26
  152. package/src/MapView.types.ts +43 -9
  153. package/src/MapView.web.tsx +368 -210
  154. package/src/components/GeoJson.tsx +221 -0
  155. package/src/components/GeoJson.types.ts +118 -0
  156. package/src/components/Marker.tsx +75 -38
  157. package/src/components/Marker.types.ts +102 -0
  158. package/src/components/Marker.web.tsx +197 -19
  159. package/src/components/Polygon.tsx +52 -0
  160. package/src/components/Polygon.types.ts +33 -0
  161. package/src/components/Polygon.web.tsx +104 -0
  162. package/src/components/Polyline.tsx +23 -22
  163. package/src/components/Polyline.types.ts +55 -0
  164. package/src/components/Polyline.web.tsx +151 -37
  165. package/src/components/index.ts +17 -2
  166. package/src/components/index.web.ts +6 -2
  167. package/src/fabric/LuggCalloutViewNativeComponent.ts +20 -0
  168. package/src/fabric/{LuggGoogleMapViewNativeComponent.ts → LuggMapViewNativeComponent.ts} +43 -7
  169. package/src/fabric/LuggMarkerViewNativeComponent.ts +49 -1
  170. package/src/fabric/LuggPolygonViewNativeComponent.ts +25 -0
  171. package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
  172. package/src/index.ts +30 -1
  173. package/src/index.web.ts +16 -1
  174. package/src/types.ts +13 -0
  175. package/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +0 -511
  176. package/ios/LuggAppleMapView.h +0 -16
  177. package/ios/LuggAppleMapView.mm +0 -592
  178. package/ios/LuggGoogleMapView.h +0 -13
  179. package/ios/LuggGoogleMapView.mm +0 -455
  180. package/lib/module/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
  181. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts +0 -54
  182. package/lib/typescript/src/fabric/LuggAppleMapViewNativeComponent.d.ts.map +0 -1
  183. package/lib/typescript/src/fabric/LuggGoogleMapViewNativeComponent.d.ts.map +0 -1
  184. package/src/fabric/LuggAppleMapViewNativeComponent.ts +0 -83
@@ -0,0 +1,798 @@
1
+ #import "GoogleMapProvider.h"
2
+ #import "../LuggCalloutView.h"
3
+ #import "../LuggMarkerView.h"
4
+ #import "../LuggPolygonView.h"
5
+ #import "../LuggPolylineView.h"
6
+ #import "GMSPolylineAnimator.h"
7
+ #import "PolylineAnimatorBase.h"
8
+
9
+ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
10
+
11
+ @interface GoogleMapProvider () <
12
+ LuggMarkerViewDelegate, LuggCalloutViewDelegate, LuggPolylineViewDelegate,
13
+ LuggPolygonViewDelegate>
14
+ @end
15
+
16
+ @implementation GoogleMapProvider {
17
+ UIView *_wrapperView;
18
+ GMSMapView *_mapView;
19
+ BOOL _isMapReady;
20
+ BOOL _isDragging;
21
+ NSInteger _theme;
22
+ UIEdgeInsets _edgeInsets;
23
+ NSMutableArray<LuggMarkerView *> *_pendingMarkerViews;
24
+ NSMutableArray<LuggPolylineView *> *_pendingPolylineViews;
25
+ NSMutableArray<LuggPolygonView *> *_pendingPolygonViews;
26
+ NSMapTable<LuggPolylineView *, GMSPolylineAnimator *> *_polylineAnimators;
27
+ NSMapTable<GMSPolygon *, LuggPolygonView *> *_polygonToViewMap;
28
+ NSMapTable<GMSMarker *, LuggMarkerView *> *_markerToViewMap;
29
+ LuggMarkerView *_activeNonBubbledMarker;
30
+
31
+ // Edge insets animation
32
+ CADisplayLink *_edgeInsetsDisplayLink;
33
+ UIEdgeInsets _edgeInsetsFrom;
34
+ UIEdgeInsets _edgeInsetsTo;
35
+ CFTimeInterval _edgeInsetsAnimationStart;
36
+ CFTimeInterval _edgeInsetsAnimationDuration;
37
+ }
38
+
39
+ @synthesize delegate = _delegate;
40
+
41
+ - (instancetype)init {
42
+ if (self = [super init]) {
43
+ _isMapReady = NO;
44
+ _mapId = kDemoMapId;
45
+ _pendingMarkerViews = [NSMutableArray array];
46
+ _pendingPolylineViews = [NSMutableArray array];
47
+ _pendingPolygonViews = [NSMutableArray array];
48
+ _polylineAnimators = [NSMapTable weakToStrongObjectsMapTable];
49
+ _polygonToViewMap = [NSMapTable strongToWeakObjectsMapTable];
50
+ _markerToViewMap = [NSMapTable strongToWeakObjectsMapTable];
51
+ }
52
+ return self;
53
+ }
54
+
55
+ - (BOOL)isMapReady {
56
+ return _isMapReady;
57
+ }
58
+
59
+ - (GMSMapView *)mapView {
60
+ return _mapView;
61
+ }
62
+
63
+ #pragma mark - MapProvider
64
+
65
+ - (void)initializeMapInView:(UIView *)wrapperView
66
+ initialCoordinate:(CLLocationCoordinate2D)coordinate
67
+ initialZoom:(double)zoom {
68
+ if (_mapView)
69
+ return;
70
+
71
+ GMSMapID *gmsMapId;
72
+ if ([_mapId isEqualToString:kDemoMapId] || _mapId.length == 0) {
73
+ gmsMapId = [GMSMapID demoMapID];
74
+ } else {
75
+ gmsMapId = [GMSMapID mapIDWithIdentifier:_mapId];
76
+ }
77
+
78
+ GMSCameraPosition *camera =
79
+ [GMSCameraPosition cameraWithLatitude:coordinate.latitude
80
+ longitude:coordinate.longitude
81
+ zoom:zoom];
82
+
83
+ GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init];
84
+ options.frame = wrapperView.bounds;
85
+ options.camera = camera;
86
+ options.mapID = gmsMapId;
87
+
88
+ _mapView = [[GMSMapView alloc] initWithOptions:options];
89
+ _mapView.autoresizingMask =
90
+ UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
91
+ _mapView.delegate = self;
92
+ _mapView.paddingAdjustmentBehavior =
93
+ kGMSMapViewPaddingAdjustmentBehaviorNever;
94
+
95
+ _wrapperView = wrapperView;
96
+ [wrapperView addSubview:_mapView];
97
+
98
+ [self applyTheme];
99
+
100
+ _isMapReady = YES;
101
+ [self processPendingMarkers];
102
+ [self processPendingPolylines];
103
+ [self processPendingPolygons];
104
+
105
+ [_delegate mapProviderDidReady];
106
+ }
107
+
108
+ - (void)destroy {
109
+ [self stopEdgeInsetsAnimation];
110
+ [_pendingMarkerViews removeAllObjects];
111
+ [_pendingPolylineViews removeAllObjects];
112
+ [_pendingPolygonViews removeAllObjects];
113
+ [_polylineAnimators removeAllObjects];
114
+ [_polygonToViewMap removeAllObjects];
115
+ [_markerToViewMap removeAllObjects];
116
+ [_mapView clear];
117
+ [_mapView removeFromSuperview];
118
+ _mapView = nil;
119
+ _isMapReady = NO;
120
+ }
121
+
122
+ #pragma mark - Props
123
+
124
+ - (void)setZoomEnabled:(BOOL)enabled {
125
+ _mapView.settings.zoomGestures = enabled;
126
+ }
127
+
128
+ - (void)setScrollEnabled:(BOOL)enabled {
129
+ _mapView.settings.scrollGestures = enabled;
130
+ }
131
+
132
+ - (void)setRotateEnabled:(BOOL)enabled {
133
+ _mapView.settings.rotateGestures = enabled;
134
+ }
135
+
136
+ - (void)setPitchEnabled:(BOOL)enabled {
137
+ _mapView.settings.tiltGestures = enabled;
138
+ }
139
+
140
+ - (void)setUserLocationEnabled:(BOOL)enabled {
141
+ _mapView.myLocationEnabled = enabled;
142
+ }
143
+
144
+ - (void)setTheme:(NSInteger)theme {
145
+ _theme = theme;
146
+ [self applyTheme];
147
+ }
148
+
149
+ - (void)applyTheme {
150
+ if (!_mapView)
151
+ return;
152
+
153
+ switch (_theme) {
154
+ case 1: // Dark
155
+ _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
156
+ break;
157
+ case 0: // Light
158
+ _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
159
+ break;
160
+ default: // System
161
+ _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
162
+ break;
163
+ }
164
+ }
165
+
166
+ - (void)setMinZoom:(double)minZoom {
167
+ if (!_mapView)
168
+ return;
169
+ float min = minZoom > 0 ? (float)minZoom : _mapView.minZoom;
170
+ [_mapView setMinZoom:min maxZoom:_mapView.maxZoom];
171
+ }
172
+
173
+ - (void)setMaxZoom:(double)maxZoom {
174
+ if (!_mapView)
175
+ return;
176
+ float max = maxZoom > 0 ? (float)maxZoom : _mapView.maxZoom;
177
+ [_mapView setMinZoom:_mapView.minZoom maxZoom:max];
178
+ }
179
+
180
+ - (void)setEdgeInsets:(UIEdgeInsets)edgeInsets
181
+ oldEdgeInsets:(UIEdgeInsets)oldEdgeInsets {
182
+ [self setEdgeInsets:edgeInsets oldEdgeInsets:oldEdgeInsets duration:0];
183
+ }
184
+
185
+ - (void)setEdgeInsets:(UIEdgeInsets)edgeInsets
186
+ oldEdgeInsets:(UIEdgeInsets)oldEdgeInsets
187
+ duration:(double)duration {
188
+ if (UIEdgeInsetsEqualToEdgeInsets(_edgeInsets, edgeInsets))
189
+ return;
190
+
191
+ [self stopEdgeInsetsAnimation];
192
+
193
+ if (duration != 0 && _mapView) {
194
+ double actualDuration = duration < 0 ? 0.3 : duration / 1000.0;
195
+ _edgeInsetsFrom = _edgeInsets;
196
+ _edgeInsetsTo = edgeInsets;
197
+ _edgeInsets = edgeInsets;
198
+ _edgeInsetsAnimationDuration = actualDuration;
199
+ _edgeInsetsAnimationStart = CACurrentMediaTime();
200
+
201
+ _edgeInsetsDisplayLink = [CADisplayLink
202
+ displayLinkWithTarget:self
203
+ selector:@selector(edgeInsetsAnimationTick:)];
204
+ [_edgeInsetsDisplayLink addToRunLoop:[NSRunLoop mainRunLoop]
205
+ forMode:NSRunLoopCommonModes];
206
+ } else {
207
+ _edgeInsets = edgeInsets;
208
+ _mapView.padding = edgeInsets;
209
+ }
210
+ }
211
+
212
+ - (void)edgeInsetsAnimationTick:(CADisplayLink *)displayLink {
213
+ CFTimeInterval elapsed = CACurrentMediaTime() - _edgeInsetsAnimationStart;
214
+ CGFloat progress = MIN(elapsed / _edgeInsetsAnimationDuration, 1.0);
215
+
216
+ // Ease out cubic
217
+ CGFloat t = 1.0 - (1.0 - progress) * (1.0 - progress) * (1.0 - progress);
218
+
219
+ UIEdgeInsets current = UIEdgeInsetsMake(
220
+ _edgeInsetsFrom.top + (_edgeInsetsTo.top - _edgeInsetsFrom.top) * t,
221
+ _edgeInsetsFrom.left + (_edgeInsetsTo.left - _edgeInsetsFrom.left) * t,
222
+ _edgeInsetsFrom.bottom +
223
+ (_edgeInsetsTo.bottom - _edgeInsetsFrom.bottom) * t,
224
+ _edgeInsetsFrom.right +
225
+ (_edgeInsetsTo.right - _edgeInsetsFrom.right) * t);
226
+
227
+ _mapView.padding = current;
228
+
229
+ if (progress >= 1.0) {
230
+ [self stopEdgeInsetsAnimation];
231
+ }
232
+ }
233
+
234
+ - (void)stopEdgeInsetsAnimation {
235
+ [_edgeInsetsDisplayLink invalidate];
236
+ _edgeInsetsDisplayLink = nil;
237
+ }
238
+
239
+ #pragma mark - GMSMapViewDelegate
240
+
241
+ - (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture {
242
+ _isDragging = gesture;
243
+ if (_isDragging) {
244
+ for (GMSPolylineAnimator *animator in _polylineAnimators.objectEnumerator) {
245
+ [animator pause];
246
+ }
247
+ }
248
+ }
249
+
250
+ - (void)mapView:(GMSMapView *)mapView
251
+ didChangeCameraPosition:(GMSCameraPosition *)position {
252
+ [_delegate mapProviderDidMoveCamera:position.target.latitude
253
+ longitude:position.target.longitude
254
+ zoom:position.zoom
255
+ gesture:_isDragging];
256
+ [self positionNonBubbledCallout];
257
+ }
258
+
259
+ - (void)mapView:(GMSMapView *)mapView
260
+ idleAtCameraPosition:(GMSCameraPosition *)position {
261
+ BOOL wasDragging = _isDragging;
262
+ _isDragging = NO;
263
+ if (wasDragging) {
264
+ for (GMSPolylineAnimator *animator in _polylineAnimators.objectEnumerator) {
265
+ [animator resume];
266
+ }
267
+ }
268
+ [_delegate mapProviderDidIdleCamera:position.target.latitude
269
+ longitude:position.target.longitude
270
+ zoom:position.zoom
271
+ gesture:wasDragging];
272
+ }
273
+
274
+ - (void)mapView:(GMSMapView *)mapView
275
+ didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
276
+ [self dismissNonBubbledCallout];
277
+ CGPoint point = [mapView.projection pointForCoordinate:coordinate];
278
+ [_delegate mapProviderDidPress:coordinate.latitude
279
+ longitude:coordinate.longitude
280
+ x:point.x
281
+ y:point.y];
282
+ }
283
+
284
+ - (void)mapView:(GMSMapView *)mapView
285
+ didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate {
286
+ CGPoint point = [mapView.projection pointForCoordinate:coordinate];
287
+ [_delegate mapProviderDidLongPress:coordinate.latitude
288
+ longitude:coordinate.longitude
289
+ x:point.x
290
+ y:point.y];
291
+ }
292
+
293
+ - (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay {
294
+ if (![overlay isKindOfClass:[GMSPolygon class]])
295
+ return;
296
+
297
+ GMSPolygon *polygon = (GMSPolygon *)overlay;
298
+ LuggPolygonView *polygonView = [_polygonToViewMap objectForKey:polygon];
299
+ if (!polygonView || !polygonView.tappable)
300
+ return;
301
+
302
+ [polygonView emitPressEvent];
303
+ }
304
+
305
+ - (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
306
+ [self dismissNonBubbledCallout];
307
+
308
+ LuggMarkerView *markerView = [_markerToViewMap objectForKey:marker];
309
+ if (markerView) {
310
+ CGPoint point = [_mapView.projection pointForCoordinate:marker.position];
311
+ [markerView emitPressEventWithPoint:point];
312
+
313
+ LuggCalloutView *calloutView = markerView.calloutView;
314
+ if (calloutView && !calloutView.bubbled && calloutView.hasCustomContent) {
315
+ [mapView animateToLocation:marker.position];
316
+ [self showNonBubbledCallout:markerView];
317
+ return YES;
318
+ }
319
+ }
320
+ return NO;
321
+ }
322
+
323
+ - (void)mapView:(GMSMapView *)mapView
324
+ didBeginDraggingMarker:(GMSMarker *)marker {
325
+ LuggMarkerView *markerView = [_markerToViewMap objectForKey:marker];
326
+ if (markerView) {
327
+ [markerView updateCoordinate:marker.position];
328
+ CGPoint point = [_mapView.projection pointForCoordinate:marker.position];
329
+ [markerView emitDragStartEventWithPoint:point];
330
+ }
331
+ }
332
+
333
+ - (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker {
334
+ LuggMarkerView *markerView = [_markerToViewMap objectForKey:marker];
335
+ if (markerView) {
336
+ [markerView updateCoordinate:marker.position];
337
+ CGPoint point = [_mapView.projection pointForCoordinate:marker.position];
338
+ [markerView emitDragChangeEventWithPoint:point];
339
+ }
340
+ }
341
+
342
+ - (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker {
343
+ LuggMarkerView *markerView = [_markerToViewMap objectForKey:marker];
344
+ if (markerView) {
345
+ [markerView updateCoordinate:marker.position];
346
+ CGPoint point = [_mapView.projection pointForCoordinate:marker.position];
347
+ [markerView emitDragEndEventWithPoint:point];
348
+ }
349
+ }
350
+
351
+ - (UIView *)rasterizedCalloutView:(LuggCalloutView *)calloutView {
352
+ UIView *contentView = calloutView.contentView;
353
+ [contentView layoutIfNeeded];
354
+
355
+ CGSize size = contentView.bounds.size;
356
+ if (size.width <= 0 || size.height <= 0)
357
+ return nil;
358
+
359
+ UIGraphicsImageRendererFormat *format =
360
+ [UIGraphicsImageRendererFormat defaultFormat];
361
+ format.scale = [UIScreen mainScreen].scale;
362
+ UIGraphicsImageRenderer *renderer =
363
+ [[UIGraphicsImageRenderer alloc] initWithSize:size format:format];
364
+ UIImage *image =
365
+ [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
366
+ [contentView.layer renderInContext:context.CGContext];
367
+ }];
368
+
369
+ return [[UIImageView alloc] initWithImage:image];
370
+ }
371
+
372
+ - (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
373
+ // Non-bubbled callouts are rendered as live views, not info windows
374
+ return nil;
375
+ }
376
+
377
+ - (UIView *)mapView:(GMSMapView *)mapView
378
+ markerInfoContents:(GMSMarker *)marker {
379
+ LuggMarkerView *markerView = [_markerToViewMap objectForKey:marker];
380
+ if (!markerView || !markerView.calloutView ||
381
+ !markerView.calloutView.hasCustomContent)
382
+ return nil;
383
+
384
+ if (markerView.calloutView.bubbled) {
385
+ return [self rasterizedCalloutView:markerView.calloutView];
386
+ }
387
+
388
+ return nil;
389
+ }
390
+
391
+ - (void)showNonBubbledCallout:(LuggMarkerView *)markerView {
392
+ [self dismissNonBubbledCallout];
393
+ _mapView.selectedMarker = nil;
394
+
395
+ LuggCalloutView *calloutView = markerView.calloutView;
396
+ UIView *contentView = calloutView.contentView;
397
+ [contentView removeFromSuperview];
398
+
399
+ contentView.userInteractionEnabled = YES;
400
+ calloutView.delegate = self;
401
+ [_wrapperView addSubview:contentView];
402
+
403
+ _activeNonBubbledMarker = markerView;
404
+ [self positionNonBubbledCallout];
405
+ }
406
+
407
+ - (void)calloutViewDidUpdate:(LuggCalloutView *)calloutView {
408
+ [self positionNonBubbledCallout];
409
+ }
410
+
411
+ - (void)dismissNonBubbledCallout {
412
+ if (!_activeNonBubbledMarker)
413
+ return;
414
+
415
+ LuggCalloutView *calloutView = _activeNonBubbledMarker.calloutView;
416
+ calloutView.delegate = nil;
417
+ [calloutView.contentView removeFromSuperview];
418
+ _activeNonBubbledMarker = nil;
419
+ }
420
+
421
+ - (void)positionNonBubbledCallout {
422
+ if (!_activeNonBubbledMarker)
423
+ return;
424
+
425
+ LuggCalloutView *calloutView = _activeNonBubbledMarker.calloutView;
426
+ UIView *contentView = calloutView.contentView;
427
+ CGSize contentSize = contentView.bounds.size;
428
+ if (contentSize.width <= 0 || contentSize.height <= 0)
429
+ return;
430
+
431
+ CGPoint anchor = calloutView.anchor;
432
+ CGPoint point = [_mapView.projection
433
+ pointForCoordinate:_activeNonBubbledMarker.coordinate];
434
+
435
+ contentView.center =
436
+ CGPointMake(point.x + contentSize.width * (0.5 - anchor.x),
437
+ point.y + contentSize.height * (0.5 - anchor.y));
438
+ }
439
+
440
+ #pragma mark - MarkerViewDelegate
441
+
442
+ - (void)markerViewDidLayout:(LuggMarkerView *)markerView {
443
+ [self syncMarkerView:markerView];
444
+ }
445
+
446
+ - (void)markerViewDidUpdate:(LuggMarkerView *)markerView {
447
+ [self syncMarkerView:markerView];
448
+ }
449
+
450
+ #pragma mark - PolylineViewDelegate
451
+
452
+ - (void)polylineViewDidUpdate:(LuggPolylineView *)polylineView {
453
+ [self syncPolylineView:polylineView];
454
+ }
455
+
456
+ #pragma mark - PolygonViewDelegate
457
+
458
+ - (void)polygonViewDidUpdate:(LuggPolygonView *)polygonView {
459
+ [self syncPolygonView:polygonView];
460
+ }
461
+
462
+ #pragma mark - Marker Management
463
+
464
+ - (void)addMarkerView:(LuggMarkerView *)markerView {
465
+ markerView.delegate = self;
466
+ [self syncMarkerView:markerView];
467
+ }
468
+
469
+ - (void)removeMarkerView:(LuggMarkerView *)markerView {
470
+ GMSAdvancedMarker *marker = (GMSAdvancedMarker *)markerView.marker;
471
+ if (marker) {
472
+ [_markerToViewMap removeObjectForKey:marker];
473
+ marker.iconView = nil;
474
+ marker.map = nil;
475
+ markerView.marker = nil;
476
+ }
477
+ [markerView resetIconViewTransform];
478
+ }
479
+
480
+ - (void)syncMarkerView:(LuggMarkerView *)markerView {
481
+ if (!_mapView) {
482
+ if (![_pendingMarkerViews containsObject:markerView]) {
483
+ [_pendingMarkerViews addObject:markerView];
484
+ }
485
+ return;
486
+ }
487
+
488
+ if (!markerView.marker) {
489
+ [self addMarkerViewToMap:markerView];
490
+ return;
491
+ }
492
+
493
+ GMSAdvancedMarker *marker = (GMSAdvancedMarker *)markerView.marker;
494
+ marker.position = markerView.coordinate;
495
+ marker.title = markerView.title.length > 0 ? markerView.title : nil;
496
+ marker.snippet = markerView.markerDescription.length > 0
497
+ ? markerView.markerDescription
498
+ : nil;
499
+ marker.zIndex = (int)markerView.zIndex;
500
+ marker.draggable = markerView.draggable;
501
+ [self applyMarkerStyle:markerView marker:marker];
502
+ }
503
+
504
+ - (void)processPendingMarkers {
505
+ if (!_mapView)
506
+ return;
507
+
508
+ for (LuggMarkerView *markerView in _pendingMarkerViews) {
509
+ [self addMarkerViewToMap:markerView];
510
+ }
511
+ [_pendingMarkerViews removeAllObjects];
512
+ }
513
+
514
+ - (void)addMarkerViewToMap:(LuggMarkerView *)markerView {
515
+ if (!_mapView)
516
+ return;
517
+
518
+ GMSAdvancedMarker *marker = [[GMSAdvancedMarker alloc] init];
519
+ marker.position = markerView.coordinate;
520
+ marker.title = markerView.title.length > 0 ? markerView.title : nil;
521
+ marker.snippet = markerView.markerDescription.length > 0
522
+ ? markerView.markerDescription
523
+ : nil;
524
+ marker.zIndex = (int)markerView.zIndex;
525
+ marker.draggable = markerView.draggable;
526
+
527
+ [self applyMarkerStyle:markerView marker:marker];
528
+
529
+ marker.map = _mapView;
530
+ markerView.marker = marker;
531
+ [_markerToViewMap setObject:markerView forKey:marker];
532
+ }
533
+
534
+ - (void)applyMarkerStyle:(LuggMarkerView *)markerView
535
+ marker:(GMSAdvancedMarker *)marker {
536
+ if (markerView.hasCustomView) {
537
+ if (markerView.rasterize) {
538
+ marker.iconView = nil;
539
+ marker.icon = [markerView createScaledIconImage];
540
+ marker.rotation = markerView.rotate;
541
+ } else {
542
+ UIView *iconView = markerView.iconView;
543
+ if (marker.iconView != iconView) {
544
+ [iconView removeFromSuperview];
545
+ marker.iconView = iconView;
546
+ }
547
+ CGFloat scale = markerView.scale;
548
+ CGFloat radians = markerView.rotate * M_PI / 180.0;
549
+ iconView.transform =
550
+ CGAffineTransformConcat(CGAffineTransformMakeScale(scale, scale),
551
+ CGAffineTransformMakeRotation(radians));
552
+ marker.rotation = 0;
553
+ }
554
+ marker.groundAnchor = markerView.anchor;
555
+ } else {
556
+ marker.iconView = nil;
557
+ marker.icon = nil;
558
+ marker.rotation = markerView.rotate;
559
+ marker.groundAnchor = CGPointMake(0.5, 1);
560
+ }
561
+ }
562
+
563
+ #pragma mark - Polyline Management
564
+
565
+ - (void)addPolylineView:(LuggPolylineView *)polylineView {
566
+ polylineView.delegate = self;
567
+ [self syncPolylineView:polylineView];
568
+ }
569
+
570
+ - (void)removePolylineView:(LuggPolylineView *)polylineView {
571
+ [_polylineAnimators removeObjectForKey:polylineView];
572
+ GMSPolyline *polyline = (GMSPolyline *)polylineView.polyline;
573
+ if (polyline) {
574
+ polyline.map = nil;
575
+ polylineView.polyline = nil;
576
+ }
577
+ }
578
+
579
+ - (void)syncPolylineView:(LuggPolylineView *)polylineView {
580
+ if (!_mapView) {
581
+ if (![_pendingPolylineViews containsObject:polylineView]) {
582
+ [_pendingPolylineViews addObject:polylineView];
583
+ }
584
+ return;
585
+ }
586
+
587
+ if (!polylineView.polyline) {
588
+ [self addPolylineViewToMap:polylineView];
589
+ return;
590
+ }
591
+
592
+ GMSPolyline *polyline = (GMSPolyline *)polylineView.polyline;
593
+ polyline.strokeWidth = polylineView.strokeWidth;
594
+ polyline.zIndex = (int)polylineView.zIndex;
595
+
596
+ GMSPolylineAnimator *animator =
597
+ [_polylineAnimators objectForKey:polylineView];
598
+ if (animator) {
599
+ animator.coordinates = polylineView.coordinates;
600
+ animator.strokeColors = polylineView.strokeColors;
601
+ animator.animatedOptions = polylineView.animatedOptions;
602
+ animator.animated = polylineView.animated;
603
+ [animator update];
604
+ }
605
+ }
606
+
607
+ - (void)processPendingPolylines {
608
+ if (!_mapView)
609
+ return;
610
+
611
+ for (LuggPolylineView *polylineView in _pendingPolylineViews) {
612
+ [self addPolylineViewToMap:polylineView];
613
+ }
614
+ [_pendingPolylineViews removeAllObjects];
615
+ }
616
+
617
+ - (void)addPolylineViewToMap:(LuggPolylineView *)polylineView {
618
+ if (!_mapView)
619
+ return;
620
+
621
+ GMSPolyline *polyline = [GMSPolyline polylineWithPath:[GMSMutablePath path]];
622
+ polyline.strokeWidth = polylineView.strokeWidth;
623
+ polyline.zIndex = (int)polylineView.zIndex;
624
+ polyline.map = _mapView;
625
+ polylineView.polyline = polyline;
626
+
627
+ GMSPolylineAnimator *animator = [[GMSPolylineAnimator alloc] init];
628
+ animator.polyline = polyline;
629
+ animator.coordinates = polylineView.coordinates;
630
+ animator.strokeColors = polylineView.strokeColors;
631
+ animator.animatedOptions = polylineView.animatedOptions;
632
+ animator.animated = polylineView.animated;
633
+ [animator update];
634
+
635
+ [_polylineAnimators setObject:animator forKey:polylineView];
636
+ }
637
+
638
+ #pragma mark - Polygon Management
639
+
640
+ - (void)addPolygonView:(LuggPolygonView *)polygonView {
641
+ polygonView.delegate = self;
642
+ [self syncPolygonView:polygonView];
643
+ }
644
+
645
+ - (void)removePolygonView:(LuggPolygonView *)polygonView {
646
+ GMSPolygon *polygon = (GMSPolygon *)polygonView.polygon;
647
+ if (polygon) {
648
+ [_polygonToViewMap removeObjectForKey:polygon];
649
+ polygon.map = nil;
650
+ polygonView.polygon = nil;
651
+ }
652
+ }
653
+
654
+ - (void)syncPolygonView:(LuggPolygonView *)polygonView {
655
+ if (!_mapView) {
656
+ if (![_pendingPolygonViews containsObject:polygonView]) {
657
+ [_pendingPolygonViews addObject:polygonView];
658
+ }
659
+ return;
660
+ }
661
+
662
+ if (!polygonView.polygon) {
663
+ [self addPolygonViewToMap:polygonView];
664
+ return;
665
+ }
666
+
667
+ GMSPolygon *polygon = (GMSPolygon *)polygonView.polygon;
668
+
669
+ GMSMutablePath *path = [GMSMutablePath path];
670
+ for (CLLocation *location in polygonView.coordinates) {
671
+ [path addCoordinate:location.coordinate];
672
+ }
673
+ polygon.path = path;
674
+ polygon.holes = [self holesPathsFromPolygonView:polygonView];
675
+ polygon.fillColor = polygonView.fillColor;
676
+ polygon.strokeColor = polygonView.strokeColor;
677
+ polygon.strokeWidth = polygonView.strokeWidth;
678
+ polygon.zIndex = (int)polygonView.zIndex;
679
+ polygon.tappable = polygonView.tappable;
680
+ }
681
+
682
+ - (NSArray<GMSPath *> *)holesPathsFromPolygonView:
683
+ (LuggPolygonView *)polygonView {
684
+ NSMutableArray<GMSPath *> *holePaths = [NSMutableArray array];
685
+ for (NSArray<CLLocation *> *hole in polygonView.holes) {
686
+ GMSMutablePath *holePath = [GMSMutablePath path];
687
+ for (CLLocation *location in hole) {
688
+ [holePath addCoordinate:location.coordinate];
689
+ }
690
+ [holePaths addObject:holePath];
691
+ }
692
+ return [holePaths copy];
693
+ }
694
+
695
+ - (void)processPendingPolygons {
696
+ if (!_mapView)
697
+ return;
698
+
699
+ for (LuggPolygonView *polygonView in _pendingPolygonViews) {
700
+ [self addPolygonViewToMap:polygonView];
701
+ }
702
+ [_pendingPolygonViews removeAllObjects];
703
+ }
704
+
705
+ - (void)addPolygonViewToMap:(LuggPolygonView *)polygonView {
706
+ if (!_mapView)
707
+ return;
708
+
709
+ GMSMutablePath *path = [GMSMutablePath path];
710
+ for (CLLocation *location in polygonView.coordinates) {
711
+ [path addCoordinate:location.coordinate];
712
+ }
713
+
714
+ GMSPolygon *polygon = [GMSPolygon polygonWithPath:path];
715
+ polygon.holes = [self holesPathsFromPolygonView:polygonView];
716
+ polygon.fillColor = polygonView.fillColor;
717
+ polygon.strokeColor = polygonView.strokeColor;
718
+ polygon.strokeWidth = polygonView.strokeWidth;
719
+ polygon.zIndex = (int)polygonView.zIndex;
720
+ polygon.tappable = polygonView.tappable;
721
+ polygon.map = _mapView;
722
+ polygonView.polygon = polygon;
723
+ [_polygonToViewMap setObject:polygonView forKey:polygon];
724
+ }
725
+
726
+ #pragma mark - Lifecycle
727
+
728
+ - (void)pauseAnimations {
729
+ for (GMSPolylineAnimator *animator in _polylineAnimators.objectEnumerator) {
730
+ [animator pause];
731
+ }
732
+ }
733
+
734
+ - (void)resumeAnimations {
735
+ for (GMSPolylineAnimator *animator in _polylineAnimators.objectEnumerator) {
736
+ [animator resume];
737
+ }
738
+ }
739
+
740
+ #pragma mark - Commands
741
+
742
+ - (void)moveCamera:(double)latitude
743
+ longitude:(double)longitude
744
+ zoom:(double)zoom
745
+ duration:(double)duration {
746
+ if (!_mapView)
747
+ return;
748
+
749
+ float targetZoom = zoom > 0 ? (float)zoom : _mapView.camera.zoom;
750
+ GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:latitude
751
+ longitude:longitude
752
+ zoom:targetZoom];
753
+ if (duration < 0) {
754
+ [_mapView animateToCameraPosition:camera];
755
+ } else if (duration > 0) {
756
+ [CATransaction begin];
757
+ [CATransaction setAnimationDuration:duration / 1000.0];
758
+ [_mapView animateToCameraPosition:camera];
759
+ [CATransaction commit];
760
+ } else {
761
+ [_mapView setCamera:camera];
762
+ }
763
+ }
764
+
765
+ - (void)fitCoordinates:(NSArray *)coordinates
766
+ edgeInsetsTop:(double)edgeInsetsTop
767
+ edgeInsetsLeft:(double)edgeInsetsLeft
768
+ edgeInsetsBottom:(double)edgeInsetsBottom
769
+ edgeInsetsRight:(double)edgeInsetsRight
770
+ duration:(double)duration {
771
+ if (!_mapView || coordinates.count == 0)
772
+ return;
773
+
774
+ GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] init];
775
+ for (NSDictionary *coord in coordinates) {
776
+ double lat = [coord[@"latitude"] doubleValue];
777
+ double lng = [coord[@"longitude"] doubleValue];
778
+ bounds = [bounds includingCoordinate:CLLocationCoordinate2DMake(lat, lng)];
779
+ }
780
+
781
+ UIEdgeInsets insets = UIEdgeInsetsMake(edgeInsetsTop, edgeInsetsLeft,
782
+ edgeInsetsBottom, edgeInsetsRight);
783
+ GMSCameraUpdate *cameraUpdate = [GMSCameraUpdate fitBounds:bounds
784
+ withEdgeInsets:insets];
785
+
786
+ if (duration < 0) {
787
+ [_mapView animateWithCameraUpdate:cameraUpdate];
788
+ } else if (duration > 0) {
789
+ [CATransaction begin];
790
+ [CATransaction setAnimationDuration:duration / 1000.0];
791
+ [_mapView animateWithCameraUpdate:cameraUpdate];
792
+ [CATransaction commit];
793
+ } else {
794
+ [_mapView moveCamera:cameraUpdate];
795
+ }
796
+ }
797
+
798
+ @end