react-native-maps 2.0.0-beta.5 → 2.0.0-beta.7

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 (178) hide show
  1. package/android/src/main/java/com/rnmaps/maps/MapCalloutManager.java +1 -1
  2. package/android/src/main/java/com/rnmaps/maps/MapCircleManager.java +1 -1
  3. package/android/src/main/java/com/rnmaps/maps/MapGradientPolyline.java +4 -4
  4. package/android/src/main/java/com/rnmaps/maps/MapGradientPolylineManager.java +1 -1
  5. package/android/src/main/java/com/rnmaps/maps/MapHeatmapManager.java +1 -1
  6. package/android/src/main/java/com/rnmaps/maps/MapLiteManager.java +1 -1
  7. package/android/src/main/java/com/rnmaps/maps/MapLocalTile.java +4 -4
  8. package/android/src/main/java/com/rnmaps/maps/MapLocalTileManager.java +1 -1
  9. package/android/src/main/java/com/rnmaps/maps/MapManager.java +1 -56
  10. package/android/src/main/java/com/rnmaps/maps/MapMarker.java +1 -1
  11. package/android/src/main/java/com/rnmaps/maps/MapMarkerManager.java +9 -26
  12. package/android/src/main/java/com/rnmaps/maps/MapOverlayManager.java +1 -1
  13. package/android/src/main/java/com/rnmaps/maps/MapPolygonManager.java +1 -1
  14. package/android/src/main/java/com/rnmaps/maps/MapPolylineManager.java +1 -1
  15. package/android/src/main/java/com/rnmaps/maps/MapTileProvider.java +4 -4
  16. package/android/src/main/java/com/rnmaps/maps/MapUrlTileManager.java +1 -1
  17. package/android/src/main/java/com/rnmaps/maps/MapView.java +24 -131
  18. package/android/src/main/java/com/rnmaps/maps/MapViewModule.java +598 -0
  19. package/android/src/main/java/com/rnmaps/maps/MapWMSTile.java +6 -6
  20. package/android/src/main/java/com/rnmaps/maps/MapWMSTileManager.java +1 -1
  21. package/android/src/main/java/com/rnmaps/maps/MapsPackage.java +1 -1
  22. package/android/src/main/java/com/rnmaps/maps/SizeReportingShadowNode.java +1 -1
  23. package/ios/{AirGoogleMaps/AIRDummyView.h → GoogleMaps/RNMDummyView.h} +3 -3
  24. package/ios/{AirGoogleMaps/AIRDummyView.m → GoogleMaps/RNMDummyView.m} +4 -4
  25. package/ios/{AirGoogleMaps/AIRGMSMarker.h → GoogleMaps/RNMGMSMarker.h} +6 -6
  26. package/ios/{AirGoogleMaps/AIRGMSMarker.m → GoogleMaps/RNMGMSMarker.m} +4 -4
  27. package/ios/{AirGoogleMaps/AIRGMSPolygon.h → GoogleMaps/RNMGMSPolygon.h} +4 -4
  28. package/ios/{AirGoogleMaps/AIRGMSPolygon.m → GoogleMaps/RNMGMSPolygon.m} +4 -4
  29. package/ios/{AirGoogleMaps/AIRGMSPolyline.h → GoogleMaps/RNMGMSPolyline.h} +4 -4
  30. package/ios/{AirGoogleMaps/AIRGMSPolyline.m → GoogleMaps/RNMGMSPolyline.m} +4 -4
  31. package/ios/{AirGoogleMaps/AIRGoogleMap.h → GoogleMaps/RNMGoogleMap.h} +5 -5
  32. package/ios/{AirGoogleMaps/AIRGoogleMap.m → GoogleMaps/RNMGoogleMap.m} +77 -77
  33. package/ios/{AirGoogleMaps/AIRGoogleMapCallout.h → GoogleMaps/RNMGoogleMapCallout.h} +3 -3
  34. package/ios/{AirGoogleMaps/AIRGoogleMapCallout.m → GoogleMaps/RNMGoogleMapCallout.m} +4 -4
  35. package/ios/{AirGoogleMaps/AIRGoogleMapCalloutManager.h → GoogleMaps/RNMGoogleMapCalloutManager.h} +3 -3
  36. package/ios/{AirGoogleMaps/AIRGoogleMapCalloutManager.m → GoogleMaps/RNMGoogleMapCalloutManager.m} +7 -7
  37. package/ios/{AirGoogleMaps/AIRGoogleMapCalloutSubview.h → GoogleMaps/RNMGoogleMapCalloutSubview.h} +3 -3
  38. package/ios/{AirGoogleMaps/AIRGoogleMapCalloutSubview.m → GoogleMaps/RNMGoogleMapCalloutSubview.m} +4 -4
  39. package/ios/{AirGoogleMaps/AIRGoogleMapCalloutSubviewManager.h → GoogleMaps/RNMGoogleMapCalloutSubviewManager.h} +3 -3
  40. package/ios/GoogleMaps/RNMGoogleMapCalloutSubviewManager.m +28 -0
  41. package/ios/{AirGoogleMaps/AIRGoogleMapCircle.h → GoogleMaps/RNMGoogleMapCircle.h} +3 -3
  42. package/ios/{AirGoogleMaps/AIRGoogleMapCircle.m → GoogleMaps/RNMGoogleMapCircle.m} +3 -3
  43. package/ios/{AirGoogleMaps/AIRGoogleMapCircleManager.h → GoogleMaps/RNMGoogleMapCircleManager.h} +2 -2
  44. package/ios/{AirGoogleMaps/AIRGoogleMapCircleManager.m → GoogleMaps/RNMGoogleMapCircleManager.m} +7 -7
  45. package/ios/{AirGoogleMaps/AIRGoogleMapHeatmap.h → GoogleMaps/RNMGoogleMapHeatmap.h} +3 -3
  46. package/ios/{AirGoogleMaps/AIRGoogleMapHeatmap.m → GoogleMaps/RNMGoogleMapHeatmap.m} +4 -4
  47. package/ios/GoogleMaps/RNMGoogleMapHeatmapManager.h +11 -0
  48. package/ios/{AirGoogleMaps/AIRGoogleMapHeatmapManager.m → GoogleMaps/RNMGoogleMapHeatmapManager.m} +9 -9
  49. package/ios/{AirGoogleMaps/AIRGoogleMapManager.h → GoogleMaps/RNMGoogleMapManager.h} +3 -3
  50. package/ios/GoogleMaps/RNMGoogleMapManager.m +274 -0
  51. package/ios/{AirGoogleMaps/AIRGoogleMapMarker.h → GoogleMaps/RNMGoogleMapMarker.h} +15 -15
  52. package/ios/{AirGoogleMaps/AIRGoogleMapMarker.m → GoogleMaps/RNMGoogleMapMarker.m} +22 -22
  53. package/ios/{AirGoogleMaps/AIRGoogleMapMarkerManager.h → GoogleMaps/RNMGoogleMapMarkerManager.h} +3 -3
  54. package/ios/{AirGoogleMaps/AIRGoogleMapMarkerManager.m → GoogleMaps/RNMGoogleMapMarkerManager.m} +20 -20
  55. package/ios/{AirGoogleMaps/AIRGoogleMapOverlay.h → GoogleMaps/RNMGoogleMapOverlay.h} +4 -4
  56. package/ios/{AirGoogleMaps/AIRGoogleMapOverlay.m → GoogleMaps/RNMGoogleMapOverlay.m} +4 -4
  57. package/ios/{AirGoogleMaps/AIRGoogleMapOverlayManager.h → GoogleMaps/RNMGoogleMapOverlayManager.h} +2 -2
  58. package/ios/{AirGoogleMaps/AIRGoogleMapOverlayManager.m → GoogleMaps/RNMGoogleMapOverlayManager.m} +6 -6
  59. package/ios/{AirGoogleMaps/AIRGoogleMapPolygon.h → GoogleMaps/RNMGoogleMapPolygon.h} +7 -7
  60. package/ios/{AirGoogleMaps/AIRGoogleMapPolygon.m → GoogleMaps/RNMGoogleMapPolygon.m} +7 -7
  61. package/ios/{AirGoogleMaps/AIRGoogleMapPolylineManager.h → GoogleMaps/RNMGoogleMapPolygonManager.h} +2 -2
  62. package/ios/{AirGoogleMaps/AIRGoogleMapPolygonManager.m → GoogleMaps/RNMGoogleMapPolygonManager.m} +10 -10
  63. package/ios/{AirGoogleMaps/AIRGoogleMapPolyline.h → GoogleMaps/RNMGoogleMapPolyline.h} +7 -7
  64. package/ios/{AirGoogleMaps/AIRGoogleMapPolyline.m → GoogleMaps/RNMGoogleMapPolyline.m} +9 -9
  65. package/ios/{AirGoogleMaps/AIRGoogleMapPolygonManager.h → GoogleMaps/RNMGoogleMapPolylineManager.h} +2 -2
  66. package/ios/{AirGoogleMaps/AIRGoogleMapPolylineManager.m → GoogleMaps/RNMGoogleMapPolylineManager.m} +9 -9
  67. package/ios/{AirGoogleMaps/AIRGoogleMapUrlTile.h → GoogleMaps/RNMGoogleMapUrlTile.h} +2 -2
  68. package/ios/{AirGoogleMaps/AIRGoogleMapUrlTile.m → GoogleMaps/RNMGoogleMapUrlTile.m} +3 -3
  69. package/ios/{AirGoogleMaps/AIRGoogleMapUrlTileManager.h → GoogleMaps/RNMGoogleMapUrlTileManager.h} +2 -2
  70. package/ios/{AirGoogleMaps/AIRGoogleMapURLTileManager.m → GoogleMaps/RNMGoogleMapUrlTileManager.m} +7 -7
  71. package/ios/GoogleMaps/RNMGoogleMapViewModule.h +5 -0
  72. package/ios/GoogleMaps/RNMGoogleMapViewModule.m +380 -0
  73. package/ios/{AirGoogleMaps/AIRGoogleMapWMSTile.h → GoogleMaps/RNMGoogleMapWMSTile.h} +3 -3
  74. package/ios/{AirGoogleMaps/AIRGoogleMapWMSTile.m → GoogleMaps/RNMGoogleMapWMSTile.m} +4 -4
  75. package/ios/{AirGoogleMaps/AIRGoogleMapWMSTileManager.h → GoogleMaps/RNMGoogleMapWMSTileManager.h} +3 -3
  76. package/ios/{AirGoogleMaps/AIRGoogleMapWMSTileManager.m → GoogleMaps/RNMGoogleMapWMSTileManager.m} +8 -8
  77. package/ios/{AirMaps → Maps}/Callout/SMCalloutView.h +4 -4
  78. package/ios/{AirMaps/RCTConvert+AirMap.h → Maps/RCTConvert+RNMMap.h} +1 -1
  79. package/ios/{AirMaps/RCTConvert+AirMap.m → Maps/RCTConvert+RNMMap.m} +8 -8
  80. package/ios/{AirMaps/AIRMap.h → Maps/RNMMap.h} +8 -8
  81. package/ios/{AirMaps/AIRMap.m → Maps/RNMMap.m} +56 -56
  82. package/ios/{AirMaps/AIRMapCallout.h → Maps/RNMMapCallout.h} +1 -1
  83. package/ios/{AirMaps/AIRMapCallout.m → Maps/RNMMapCallout.m} +2 -2
  84. package/ios/{AirMaps/AIRMapCircleManager.h → Maps/RNMMapCalloutManager.h} +2 -2
  85. package/ios/{AirMaps/AIRMapCalloutManager.m → Maps/RNMMapCalloutManager.m} +7 -7
  86. package/ios/{AirMaps/AIRMapCalloutSubview.h → Maps/RNMMapCalloutSubview.h} +3 -3
  87. package/ios/{AirMaps/AIRMapCalloutSubview.m → Maps/RNMMapCalloutSubview.m} +4 -4
  88. package/ios/Maps/RNMMapCalloutSubviewManager.h +14 -0
  89. package/ios/Maps/RNMMapCalloutSubviewManager.m +24 -0
  90. package/ios/{AirMaps/AIRMapCircle.h → Maps/RNMMapCircle.h} +5 -5
  91. package/ios/{AirMaps/AIRMapCircle.m → Maps/RNMMapCircle.m} +3 -3
  92. package/ios/{AirMaps/AIRMapCalloutManager.h → Maps/RNMMapCircleManager.h} +2 -2
  93. package/ios/{AirMaps/AIRMapCircleManager.m → Maps/RNMMapCircleManager.m} +7 -7
  94. package/ios/{AirMaps/AIRMapCoordinate.h → Maps/RNMMapCoordinate.h} +2 -2
  95. package/ios/{AirMaps/AIRMapCoordinate.m → Maps/RNMMapCoordinate.m} +3 -3
  96. package/ios/{AirMaps/AIRMapLocalTile.h → Maps/RNMMapLocalTile.h} +7 -7
  97. package/ios/{AirMaps/AIRMapLocalTile.m → Maps/RNMMapLocalTile.m} +6 -6
  98. package/ios/{AirMaps/AIRMapLocalTileManager.h → Maps/RNMMapLocalTileManager.h} +3 -3
  99. package/ios/{AirMaps/AIRMapLocalTileManager.m → Maps/RNMMapLocalTileManager.m} +9 -9
  100. package/ios/{AirMaps/AIRMapLocalTileOverlay.h → Maps/RNMMapLocalTileOverlay.h} +2 -2
  101. package/ios/{AirMaps/AIRMapLocalTileOverlay.m → Maps/RNMMapLocalTileOverlay.m} +5 -5
  102. package/ios/{AirMaps/AIRMapManager.h → Maps/RNMMapManager.h} +6 -6
  103. package/ios/Maps/RNMMapManager.m +857 -0
  104. package/ios/{AirMaps/AIRMapMarker.h → Maps/RNMMapMarker.h} +8 -8
  105. package/ios/{AirMaps/AIRMapMarker.m → Maps/RNMMapMarker.m} +13 -13
  106. package/ios/{AirMaps/AIRMapMarkerManager.h → Maps/RNMMapMarkerManager.h} +1 -1
  107. package/ios/{AirMaps/AIRMapMarkerManager.m → Maps/RNMMapMarkerManager.m} +14 -14
  108. package/ios/{AirMaps/AIRMapOverlay.h → Maps/RNMMapOverlay.h} +7 -7
  109. package/ios/{AirMaps/AIRMapOverlay.m → Maps/RNMMapOverlay.m} +4 -4
  110. package/ios/Maps/RNMMapOverlayManager.h +5 -0
  111. package/ios/{AirMaps/AIRMapOverlayManager.m → Maps/RNMMapOverlayManager.m} +6 -6
  112. package/ios/{AirMaps/AIRMapOverlayRenderer.h → Maps/RNMMapOverlayRenderer.h} +1 -1
  113. package/ios/{AirMaps/AIRMapOverlayRenderer.m → Maps/RNMMapOverlayRenderer.m} +5 -5
  114. package/ios/{AirMaps/AIRMapPolygon.h → Maps/RNMMapPolygon.h} +7 -7
  115. package/ios/{AirMaps/AIRMapPolygon.m → Maps/RNMMapPolygon.m} +4 -4
  116. package/ios/{AirMaps/AIRMapPolygonManager.h → Maps/RNMMapPolygonManager.h} +2 -2
  117. package/ios/{AirMaps/AIRMapPolygonManager.m → Maps/RNMMapPolygonManager.m} +10 -10
  118. package/ios/{AirMaps/AIRMapPolyline.h → Maps/RNMMapPolyline.h} +6 -6
  119. package/ios/{AirMaps/AIRMapPolyline.m → Maps/RNMMapPolyline.m} +11 -11
  120. package/ios/{AirMaps/AIRMapPolylineManager.h → Maps/RNMMapPolylineManager.h} +2 -2
  121. package/ios/{AirMaps/AIRMapPolylineManager.m → Maps/RNMMapPolylineManager.m} +9 -9
  122. package/ios/{AirMaps/AIRMapPolylineRenderer.h → Maps/RNMMapPolylineRenderer.h} +2 -2
  123. package/ios/{AirMaps/AIRMapPolylineRenderer.m → Maps/RNMMapPolylineRenderer.m} +10 -10
  124. package/ios/{AirMaps/AIRMapSnapshot.h → Maps/RNMMapSnapshot.h} +6 -6
  125. package/ios/{AirMaps/AIRMapUrlTile.h → Maps/RNMMapUrlTile.h} +18 -18
  126. package/ios/{AirMaps/AIRMapUrlTile.m → Maps/RNMMapUrlTile.m} +7 -7
  127. package/ios/{AirMaps/AIRMapUrlTileCachedOverlay.h → Maps/RNMMapUrlTileCachedOverlay.h} +3 -3
  128. package/ios/{AirMaps/AIRMapUrlTileCachedOverlay.m → Maps/RNMMapUrlTileCachedOverlay.m} +10 -10
  129. package/ios/{AirMaps/AIRMapUrlTileManager.h → Maps/RNMMapUrlTileManager.h} +3 -3
  130. package/ios/{AirMaps/AIRMapUrlTileManager.m → Maps/RNMMapUrlTileManager.m} +9 -9
  131. package/ios/Maps/RNMMapViewModule.h +5 -0
  132. package/ios/Maps/RNMMapViewModule.m +459 -0
  133. package/ios/{AirMaps/AIRMapWMSTile.h → Maps/RNMMapWMSTile.h} +11 -11
  134. package/ios/{AirMaps/AIRMapWMSTile.m → Maps/RNMMapWMSTile.m} +15 -15
  135. package/ios/{AirMaps/AIRMapWMSTileManager.h → Maps/RNMMapWMSTileManager.h} +3 -3
  136. package/ios/{AirMaps/AIRMapWMSTileManager.m → Maps/RNMMapWMSTileManager.m} +9 -9
  137. package/ios/RNMaps.xcodeproj/project.pbxproj +647 -0
  138. package/lib/MapCallout.js +2 -2
  139. package/lib/MapCalloutSubview.js +2 -2
  140. package/lib/MapCircle.js +2 -2
  141. package/lib/MapHeatmap.js +2 -2
  142. package/lib/MapLocalTile.js +2 -2
  143. package/lib/MapMarker.js +2 -2
  144. package/lib/MapOverlay.js +2 -2
  145. package/lib/MapPolygon.js +2 -2
  146. package/lib/MapPolyline.js +2 -2
  147. package/lib/MapUrlTile.js +2 -2
  148. package/lib/MapView.d.ts +7 -8
  149. package/lib/MapView.js +89 -97
  150. package/lib/MapView.types.d.ts +8 -2
  151. package/lib/MapViewNativeComponent.d.ts +2 -7
  152. package/lib/MapViewNativeComponent.js +0 -5
  153. package/lib/MapWMSTile.js +2 -2
  154. package/lib/NativeGoogleMapViewModule.d.ts +25 -0
  155. package/lib/NativeGoogleMapViewModule.js +4 -0
  156. package/lib/NativeMapViewModule.d.ts +29 -0
  157. package/lib/NativeMapViewModule.js +4 -0
  158. package/lib/decorateMapComponent.d.ts +1 -1
  159. package/lib/decorateMapComponent.js +3 -3
  160. package/package.json +1 -1
  161. package/react-native-google-maps.podspec +1 -1
  162. package/react-native-maps.podspec +1 -1
  163. package/android/src/main/java/com/rnmaps/maps/MapModule.java +0 -380
  164. package/ios/AirGoogleMaps/AIRGoogleMapCalloutSubviewManager.m +0 -28
  165. package/ios/AirGoogleMaps/AIRGoogleMapHeatmapManager.h +0 -11
  166. package/ios/AirGoogleMaps/AIRGoogleMapManager.m +0 -597
  167. package/ios/AirMaps/AIRMapCalloutSubviewManager.h +0 -14
  168. package/ios/AirMaps/AIRMapCalloutSubviewManager.m +0 -24
  169. package/ios/AirMaps/AIRMapManager.m +0 -1253
  170. package/ios/AirMaps/AIRMapOverlayManager.h +0 -5
  171. package/ios/AirMaps/AIRWeakMapReference.h +0 -24
  172. package/ios/AirMaps/AIRWeakMapReference.m +0 -23
  173. package/ios/AirMaps/AIRWeakTimerReference.h +0 -21
  174. package/ios/AirMaps/AIRWeakTimerReference.m +0 -42
  175. package/ios/AirMaps.xcodeproj/project.pbxproj +0 -587
  176. /package/ios/{AirGoogleMaps → GoogleMaps}/RCTConvert+GMSMapViewType.h +0 -0
  177. /package/ios/{AirGoogleMaps → GoogleMaps}/RCTConvert+GMSMapViewType.m +0 -0
  178. /package/ios/{AirMaps → Maps}/Callout/SMCalloutView.m +0 -0
@@ -0,0 +1,857 @@
1
+ /**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ */
9
+
10
+ #import "RNMMapManager.h"
11
+
12
+ #import <React/RCTBridge.h>
13
+ #import <React/RCTUIManager.h>
14
+ #import <React/RCTConvert.h>
15
+ #import <React/RCTConvert+CoreLocation.h>
16
+ #import <React/RCTEventDispatcher.h>
17
+ #import <React/RCTViewManager.h>
18
+ #import <React/UIView+React.h>
19
+ #import "RNMMap.h"
20
+ #import "RNMMapMarker.h"
21
+ #import "RNMMapPolyline.h"
22
+ #import "RNMMapPolygon.h"
23
+ #import "RNMMapCircle.h"
24
+ #import "SMCalloutView.h"
25
+ #import "RNMMapUrlTile.h"
26
+ #import "RNMMapWMSTile.h"
27
+ #import "RNMMapLocalTile.h"
28
+ #import "RNMMapSnapshot.h"
29
+ #import "RCTConvert+RNMMap.h"
30
+ #import "RNMMapOverlay.h"
31
+ #import <MapKit/MapKit.h>
32
+
33
+ static NSString *const RCTMapViewKey = @"MapView";
34
+
35
+
36
+ @interface RNMMapManager() <MKMapViewDelegate, UIGestureRecognizerDelegate>
37
+
38
+ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
39
+
40
+ @end
41
+
42
+ @implementation RNMMapManager{
43
+ BOOL _hasObserver;
44
+ }
45
+
46
+ RCT_EXPORT_MODULE(RNMMap)
47
+
48
+ - (UIView *)view
49
+ {
50
+ RNMMap *map = [RNMMap new];
51
+ map.delegate = self;
52
+
53
+ map.isAccessibilityElement = NO;
54
+ map.accessibilityElementsHidden = NO;
55
+
56
+ // MKMapView doesn't report tap events, so we attach gesture recognizers to it
57
+ UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapTap:)];
58
+ UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapDoubleTap:)];
59
+ [doubleTap setNumberOfTapsRequired:2];
60
+ [tap requireGestureRecognizerToFail:doubleTap];
61
+
62
+ UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapLongPress:)];
63
+ UIPanGestureRecognizer *drag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleMapDrag:)];
64
+ [drag setMinimumNumberOfTouches:1];
65
+ // setting this to NO allows the parent MapView to continue receiving marker selection events
66
+ tap.cancelsTouchesInView = NO;
67
+ doubleTap.cancelsTouchesInView = NO;
68
+ longPress.cancelsTouchesInView = NO;
69
+
70
+ doubleTap.delegate = self;
71
+
72
+ // disable drag by default
73
+ drag.enabled = NO;
74
+ drag.delegate = self;
75
+
76
+ [map addGestureRecognizer:tap];
77
+ [map addGestureRecognizer:doubleTap];
78
+ [map addGestureRecognizer:longPress];
79
+ [map addGestureRecognizer:drag];
80
+
81
+ return map;
82
+ }
83
+
84
+ RCT_EXPORT_VIEW_PROPERTY(isAccessibilityElement, BOOL)
85
+ RCT_REMAP_VIEW_PROPERTY(testID, accessibilityIdentifier, NSString)
86
+ RCT_EXPORT_VIEW_PROPERTY(showsUserLocation, BOOL)
87
+ RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
88
+ RCT_EXPORT_VIEW_PROPERTY(userLocationAnnotationTitle, NSString)
89
+ RCT_EXPORT_VIEW_PROPERTY(userInterfaceStyle, NSString)
90
+ RCT_EXPORT_VIEW_PROPERTY(followsUserLocation, BOOL)
91
+ RCT_EXPORT_VIEW_PROPERTY(userLocationCalloutEnabled, BOOL)
92
+ RCT_EXPORT_VIEW_PROPERTY(showsPointsOfInterest, BOOL)
93
+ RCT_EXPORT_VIEW_PROPERTY(showsBuildings, BOOL)
94
+ RCT_EXPORT_VIEW_PROPERTY(showsCompass, BOOL)
95
+ RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL)
96
+ RCT_EXPORT_VIEW_PROPERTY(showsTraffic, BOOL)
97
+ RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)
98
+ RCT_EXPORT_VIEW_PROPERTY(kmlSrc, NSString)
99
+ RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL)
100
+ RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL)
101
+ RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL)
102
+ RCT_EXPORT_VIEW_PROPERTY(cacheEnabled, BOOL)
103
+ RCT_EXPORT_VIEW_PROPERTY(loadingEnabled, BOOL)
104
+ RCT_EXPORT_VIEW_PROPERTY(loadingBackgroundColor, UIColor)
105
+ RCT_EXPORT_VIEW_PROPERTY(loadingIndicatorColor, UIColor)
106
+ RCT_EXPORT_VIEW_PROPERTY(handlePanDrag, BOOL)
107
+ RCT_EXPORT_VIEW_PROPERTY(maxDelta, CGFloat)
108
+ RCT_EXPORT_VIEW_PROPERTY(minDelta, CGFloat)
109
+ RCT_EXPORT_VIEW_PROPERTY(compassOffset, CGPoint)
110
+ RCT_EXPORT_VIEW_PROPERTY(legalLabelInsets, UIEdgeInsets)
111
+ RCT_EXPORT_VIEW_PROPERTY(mapPadding, UIEdgeInsets)
112
+ RCT_EXPORT_VIEW_PROPERTY(mapType, MKMapType)
113
+ RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock)
114
+ RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
115
+ RCT_EXPORT_VIEW_PROPERTY(onPanDrag, RCTBubblingEventBlock)
116
+ RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
117
+ RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock)
118
+ RCT_EXPORT_VIEW_PROPERTY(onDoublePress, RCTBubblingEventBlock)
119
+ RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock)
120
+ RCT_EXPORT_VIEW_PROPERTY(onMarkerSelect, RCTDirectEventBlock)
121
+ RCT_EXPORT_VIEW_PROPERTY(onMarkerDeselect, RCTDirectEventBlock)
122
+ RCT_EXPORT_VIEW_PROPERTY(onMarkerDragStart, RCTDirectEventBlock)
123
+ RCT_EXPORT_VIEW_PROPERTY(onMarkerDrag, RCTDirectEventBlock)
124
+ RCT_EXPORT_VIEW_PROPERTY(onMarkerDragEnd, RCTDirectEventBlock)
125
+ RCT_EXPORT_VIEW_PROPERTY(onCalloutPress, RCTDirectEventBlock)
126
+ RCT_EXPORT_VIEW_PROPERTY(onUserLocationChange, RCTBubblingEventBlock)
127
+ RCT_CUSTOM_VIEW_PROPERTY(initialRegion, MKCoordinateRegion, RNMMap)
128
+ {
129
+ if (json == nil) return;
130
+
131
+ // don't emit region change events when we are setting the initialRegion
132
+ BOOL originalIgnore = view.ignoreRegionChanges;
133
+ view.ignoreRegionChanges = YES;
134
+ [view setInitialRegion:[RCTConvert MKCoordinateRegion:json]];
135
+ view.ignoreRegionChanges = originalIgnore;
136
+ }
137
+ RCT_CUSTOM_VIEW_PROPERTY(initialCamera, MKMapCamera, RNMMap)
138
+ {
139
+ if (json == nil) return;
140
+
141
+ // don't emit region change events when we are setting the initialCamera
142
+ BOOL originalIgnore = view.ignoreRegionChanges;
143
+ view.ignoreRegionChanges = YES;
144
+ [view setInitialCamera:[RCTConvert MKMapCamera:json]];
145
+ view.ignoreRegionChanges = originalIgnore;
146
+ }
147
+
148
+
149
+ RCT_EXPORT_VIEW_PROPERTY(minZoomLevel, CGFloat)
150
+ RCT_EXPORT_VIEW_PROPERTY(maxZoomLevel, CGFloat)
151
+
152
+
153
+ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RNMMap)
154
+ {
155
+ if (json == nil) return;
156
+
157
+ // don't emit region change events when we are setting the region
158
+ BOOL originalIgnore = view.ignoreRegionChanges;
159
+ view.ignoreRegionChanges = YES;
160
+ [view setRegion:[RCTConvert MKCoordinateRegion:json] animated:NO];
161
+ view.ignoreRegionChanges = originalIgnore;
162
+ }
163
+
164
+ RCT_CUSTOM_VIEW_PROPERTY(camera, MKMapCamera*, RNMMap)
165
+ {
166
+ if (json == nil) return;
167
+
168
+ // don't emit region change events when we are setting the camera
169
+ BOOL originalIgnore = view.ignoreRegionChanges;
170
+ view.ignoreRegionChanges = YES;
171
+ [view setCamera:[RCTConvert MKMapCamera:json] animated:NO];
172
+ view.ignoreRegionChanges = originalIgnore;
173
+ }
174
+
175
+
176
+ #pragma mark exported MapView methods
177
+
178
+ RCT_EXPORT_METHOD(setCamera:(nonnull NSNumber *)reactTag
179
+ camera:(id)json)
180
+ {
181
+ [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
182
+ id view = viewRegistry[reactTag];
183
+ if (![view isKindOfClass:[RNMMap class]]) {
184
+ RCTLogError(@"Invalid view returned from registry, expecting RNMMap, got: %@", view);
185
+ } else {
186
+ RNMMap *mapView = (RNMMap *)view;
187
+
188
+ // Merge the changes given with the current camera
189
+ MKMapCamera *camera = [RCTConvert MKMapCameraWithDefaults:json existingCamera:[mapView camera]];
190
+
191
+ // don't emit region change events when we are setting the camera
192
+ BOOL originalIgnore = mapView.ignoreRegionChanges;
193
+ mapView.ignoreRegionChanges = YES;
194
+ [mapView setCamera:camera animated:NO];
195
+ mapView.ignoreRegionChanges = originalIgnore;
196
+ }
197
+ }];
198
+ }
199
+
200
+ #pragma mark Gesture Recognizer Handlers
201
+
202
+ #define MAX_DISTANCE_PX 10.0f
203
+ - (void)handleMapTap:(UITapGestureRecognizer *)recognizer {
204
+ RNMMap *map = (RNMMap *)recognizer.view;
205
+
206
+ CGPoint tapPoint = [recognizer locationInView:map];
207
+ CLLocationCoordinate2D tapCoordinate = [map convertPoint:tapPoint toCoordinateFromView:map];
208
+ MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoordinate);
209
+ CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
210
+
211
+ double maxMeters = [self metersFromPixel:MAX_DISTANCE_PX atPoint:tapPoint forMap:map];
212
+ float nearestDistance = MAXFLOAT;
213
+ RNMMapPolyline *nearestPolyline = nil;
214
+
215
+ for (id<MKOverlay> overlay in map.overlays) {
216
+ if([overlay isKindOfClass:[RNMMapPolygon class]]){
217
+ RNMMapPolygon *polygon = (RNMMapPolygon*) overlay;
218
+ if (polygon.onPress) {
219
+ CGMutablePathRef mpr = CGPathCreateMutable();
220
+
221
+ for(int i = 0; i < polygon.coordinates.count; i++) {
222
+ RNMMapCoordinate *c = polygon.coordinates[i];
223
+ MKMapPoint mp = MKMapPointForCoordinate(c.coordinate);
224
+ if (i == 0) {
225
+ CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
226
+ } else {
227
+ CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
228
+ }
229
+ }
230
+
231
+ if (CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE)) {
232
+ id event = @{
233
+ @"action": @"polygon-press",
234
+ @"coordinate": @{
235
+ @"latitude": @(tapCoordinate.latitude),
236
+ @"longitude": @(tapCoordinate.longitude),
237
+ },
238
+ };
239
+ polygon.onPress(event);
240
+ }
241
+
242
+ CGPathRelease(mpr);
243
+ }
244
+ }
245
+
246
+ if([overlay isKindOfClass:[RNMMapPolyline class]]){
247
+ RNMMapPolyline *polyline = (RNMMapPolyline*) overlay;
248
+ if (polyline.onPress) {
249
+ float distance = [self distanceOfPoint:MKMapPointForCoordinate(tapCoordinate)
250
+ toPoly:polyline];
251
+ if (distance < nearestDistance) {
252
+ nearestDistance = distance;
253
+ nearestPolyline = polyline;
254
+ }
255
+ }
256
+ }
257
+
258
+ if ([overlay isKindOfClass:[RNMMapOverlay class]]) {
259
+ RNMMapOverlay *imageOverlay = (RNMMapOverlay*) overlay;
260
+ if (MKMapRectContainsPoint(imageOverlay.boundingMapRect, mapPoint)) {
261
+ if (imageOverlay.onPress) {
262
+ id event = @{
263
+ @"action": @"image-overlay-press",
264
+ @"name": imageOverlay.name ?: @"unknown",
265
+ @"coordinate": @{
266
+ @"latitude": @(imageOverlay.coordinate.latitude),
267
+ @"longitude": @(imageOverlay.coordinate.longitude)
268
+ }
269
+ };
270
+ imageOverlay.onPress(event);
271
+ }
272
+ }
273
+ }
274
+
275
+ }
276
+
277
+ if (nearestDistance <= maxMeters) {
278
+ id event = @{
279
+ @"action": @"polyline-press",
280
+ @"coordinate": @{
281
+ @"latitude": @(tapCoordinate.latitude),
282
+ @"longitude": @(tapCoordinate.longitude)
283
+ }
284
+ };
285
+ nearestPolyline.onPress(event);
286
+ }
287
+
288
+ if (!map.onPress) return;
289
+ map.onPress(@{
290
+ @"coordinate": @{
291
+ @"latitude": @(tapCoordinate.latitude),
292
+ @"longitude": @(tapCoordinate.longitude),
293
+ },
294
+ @"position": @{
295
+ @"x": @(tapPoint.x),
296
+ @"y": @(tapPoint.y),
297
+ },
298
+ });
299
+
300
+ }
301
+
302
+ - (void)handleMapDrag:(UIPanGestureRecognizer*)recognizer {
303
+ RNMMap *map = (RNMMap *)recognizer.view;
304
+ if (!map.onPanDrag) return;
305
+
306
+ CGPoint touchPoint = [recognizer locationInView:map];
307
+ CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
308
+ map.onPanDrag(@{
309
+ @"coordinate": @{
310
+ @"latitude": @(coord.latitude),
311
+ @"longitude": @(coord.longitude),
312
+ },
313
+ @"position": @{
314
+ @"x": @(touchPoint.x),
315
+ @"y": @(touchPoint.y),
316
+ },
317
+ });
318
+
319
+ }
320
+
321
+ - (void)handleMapDoubleTap:(UIPanGestureRecognizer*)recognizer {
322
+ RNMMap *map = (RNMMap *)recognizer.view;
323
+ if (!map.onDoublePress) return;
324
+
325
+ CGPoint touchPoint = [recognizer locationInView:map];
326
+ CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
327
+ map.onDoublePress(@{
328
+ @"coordinate": @{
329
+ @"latitude": @(coord.latitude),
330
+ @"longitude": @(coord.longitude),
331
+ },
332
+ @"position": @{
333
+ @"x": @(touchPoint.x),
334
+ @"y": @(touchPoint.y),
335
+ },
336
+ });
337
+
338
+ }
339
+
340
+
341
+ - (void)handleMapLongPress:(UITapGestureRecognizer *)recognizer {
342
+
343
+ // NOTE: android only does the equivalent of "began", so we only send in this case
344
+ if (recognizer.state != UIGestureRecognizerStateBegan) return;
345
+
346
+ RNMMap *map = (RNMMap *)recognizer.view;
347
+ if (!map.onLongPress) return;
348
+
349
+ CGPoint touchPoint = [recognizer locationInView:map];
350
+ CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
351
+
352
+ map.onLongPress(@{
353
+ @"coordinate": @{
354
+ @"latitude": @(coord.latitude),
355
+ @"longitude": @(coord.longitude),
356
+ },
357
+ @"position": @{
358
+ @"x": @(touchPoint.x),
359
+ @"y": @(touchPoint.y),
360
+ },
361
+ });
362
+ }
363
+
364
+ #pragma mark MKMapViewDelegate
365
+
366
+ #pragma mark Polyline stuff
367
+
368
+ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay{
369
+ if ([overlay isKindOfClass:[RNMMapPolyline class]]) {
370
+ return ((RNMMapPolyline *)overlay).renderer;
371
+ } else if ([overlay isKindOfClass:[RNMMapPolygon class]]) {
372
+ return ((RNMMapPolygon *)overlay).renderer;
373
+ } else if ([overlay isKindOfClass:[RNMMapCircle class]]) {
374
+ return ((RNMMapCircle *)overlay).renderer;
375
+ } else if ([overlay isKindOfClass:[RNMMapUrlTile class]]) {
376
+ return ((RNMMapUrlTile *)overlay).renderer;
377
+ } else if ([overlay isKindOfClass:[RNMMapWMSTile class]]) {
378
+ return ((RNMMapWMSTile *)overlay).renderer;
379
+ } else if ([overlay isKindOfClass:[RNMMapLocalTile class]]) {
380
+ return ((RNMMapLocalTile *)overlay).renderer;
381
+ } else if ([overlay isKindOfClass:[RNMMapOverlay class]]) {
382
+ return ((RNMMapOverlay *)overlay).renderer;
383
+ } else if([overlay isKindOfClass:[MKTileOverlay class]]) {
384
+ return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
385
+ } else {
386
+ return nil;
387
+ }
388
+ }
389
+
390
+
391
+ #pragma mark Annotation Stuff
392
+
393
+ - (void)mapView:(RNMMap *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views
394
+ {
395
+ if(!mapView.userLocationCalloutEnabled){
396
+ for(MKAnnotationView* view in views){
397
+ if ([view.annotation isKindOfClass:[MKUserLocation class]]){
398
+ [view setEnabled:NO];
399
+ [view setCanShowCallout:NO];
400
+ break;
401
+ }
402
+ }
403
+ }
404
+ }
405
+
406
+
407
+ - (void)mapView:(RNMMap *)mapView didSelectAnnotationView:(MKAnnotationView *)view
408
+ {
409
+ if ([view.annotation isKindOfClass:[RNMMapMarker class]]) {
410
+ [(RNMMapMarker *)view.annotation showCalloutView];
411
+ } else if ([view.annotation isKindOfClass:[MKUserLocation class]] && mapView.userLocationAnnotationTitle != nil && view.annotation.title != mapView.userLocationAnnotationTitle) {
412
+ [(MKUserLocation*)view.annotation setTitle: mapView.userLocationAnnotationTitle];
413
+ }
414
+
415
+ }
416
+
417
+ - (void)mapView:(RNMMap *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
418
+ if ([view.annotation isKindOfClass:[RNMMapMarker class]]) {
419
+ [(RNMMapMarker *)view.annotation hideCalloutView];
420
+ }
421
+ }
422
+
423
+ - (MKAnnotationView *)mapView:(__unused RNMMap *)mapView viewForAnnotation:(RNMMapMarker *)marker
424
+ {
425
+ if (![marker isKindOfClass:[RNMMapMarker class]]) {
426
+ if ([marker isKindOfClass:[MKUserLocation class]] && mapView.userLocationAnnotationTitle != nil) {
427
+ [(MKUserLocation*)marker setTitle: mapView.userLocationAnnotationTitle];
428
+ return nil;
429
+ }
430
+ return nil;
431
+ }
432
+
433
+ marker.map = mapView;
434
+ return [marker getAnnotationView];
435
+ }
436
+
437
+ static int kDragCenterContext;
438
+
439
+ - (void)mapView:(RNMMap *)mapView
440
+ annotationView:(MKAnnotationView *)view
441
+ didChangeDragState:(MKAnnotationViewDragState)newState
442
+ fromOldState:(MKAnnotationViewDragState)oldState
443
+ {
444
+ if (![view.annotation isKindOfClass:[RNMMapMarker class]]) return;
445
+ RNMMapMarker *marker = (RNMMapMarker *)view.annotation;
446
+
447
+ BOOL isPinView = [view isKindOfClass:[MKMarkerAnnotationView class]];
448
+
449
+ id event = @{
450
+ @"id": marker.identifier ?: @"unknown",
451
+ @"coordinate": @{
452
+ @"latitude": @(marker.coordinate.latitude),
453
+ @"longitude": @(marker.coordinate.longitude)
454
+ }
455
+ };
456
+
457
+ if (newState == MKAnnotationViewDragStateEnding || newState == MKAnnotationViewDragStateCanceling) {
458
+ if (!isPinView) {
459
+ [view setDragState:MKAnnotationViewDragStateNone animated:NO];
460
+ }
461
+ if (mapView.onMarkerDragEnd) mapView.onMarkerDragEnd(event);
462
+ if (marker.onDragEnd) marker.onDragEnd(event);
463
+
464
+ if(_hasObserver) [view removeObserver:self forKeyPath:@"center"];
465
+ _hasObserver = NO;
466
+ } else if (newState == MKAnnotationViewDragStateStarting) {
467
+ // MapKit doesn't emit continuous drag events. To get around this, we are going to use KVO.
468
+ [view addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:&kDragCenterContext];
469
+ _hasObserver = YES;
470
+ if (mapView.onMarkerDragStart) mapView.onMarkerDragStart(event);
471
+ if (marker.onDragStart) marker.onDragStart(event);
472
+ }
473
+ }
474
+
475
+ - (void)observeValueForKeyPath:(NSString *)keyPath
476
+ ofObject:(id)object
477
+ change:(NSDictionary *)change
478
+ context:(void *)context
479
+ {
480
+ if ([keyPath isEqualToString:@"center"] && [object isKindOfClass:[MKAnnotationView class]]) {
481
+ MKAnnotationView *view = (MKAnnotationView *)object;
482
+ RNMMapMarker *marker = (RNMMapMarker *)view.annotation;
483
+
484
+ // a marker we don't control might be getting dragged. Check just in case.
485
+ if (!marker) return;
486
+
487
+ RNMMap *map = marker.map;
488
+
489
+ // don't waste time calculating if there are no events to listen to it
490
+ if (!map.onMarkerDrag && !marker.onDrag) return;
491
+
492
+ CGPoint position = CGPointMake(view.center.x - view.centerOffset.x, view.center.y - view.centerOffset.y);
493
+ CLLocationCoordinate2D coordinate = [map convertPoint:position toCoordinateFromView:map];
494
+
495
+ id event = @{
496
+ @"id": marker.identifier ?: @"unknown",
497
+ @"position": @{
498
+ @"x": @(position.x),
499
+ @"y": @(position.y),
500
+ },
501
+ @"coordinate": @{
502
+ @"latitude": @(coordinate.latitude),
503
+ @"longitude": @(coordinate.longitude),
504
+ }
505
+ };
506
+
507
+ if (map.onMarkerDrag) map.onMarkerDrag(event);
508
+ if (marker.onDrag) marker.onDrag(event);
509
+
510
+ } else {
511
+ // This message is not for me; pass it on to super.
512
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
513
+ }
514
+ }
515
+
516
+ - (void)mapView:(RNMMap *)mapView didUpdateUserLocation:(MKUserLocation *)location
517
+ {
518
+ id event = @{@"coordinate": @{
519
+ @"latitude": @(location.coordinate.latitude),
520
+ @"longitude": @(location.coordinate.longitude),
521
+ @"altitude": @(location.location.altitude),
522
+ @"timestamp": @(location.location.timestamp.timeIntervalSinceReferenceDate * 1000),
523
+ @"accuracy": @(location.location.horizontalAccuracy),
524
+ @"altitudeAccuracy": @(location.location.verticalAccuracy),
525
+ @"speed": @(location.location.speed),
526
+ @"heading": @(location.location.course),
527
+ }
528
+ };
529
+
530
+ if (mapView.onUserLocationChange) {
531
+ mapView.onUserLocationChange(event);
532
+ }
533
+
534
+ if (mapView.followUserLocation) {
535
+ [mapView setCenterCoordinate:location.coordinate animated:YES];
536
+ }
537
+
538
+ }
539
+
540
+ - (void)mapViewDidChangeVisibleRegion:(RNMMap *)mapView
541
+ {
542
+ [self _regionChanged:mapView];
543
+ }
544
+
545
+ - (void)mapView:(RNMMap *)mapView regionDidChangeAnimated:(__unused BOOL)animated
546
+ {
547
+ CGFloat zoomLevel = [self zoomLevel:mapView];
548
+
549
+ // Don't send region did change events until map has
550
+ // started rendering, as these won't represent the final location
551
+ if(mapView.hasStartedRendering){
552
+ [self _regionChanged:mapView];
553
+ }
554
+
555
+ if (zoomLevel < mapView.minZoomLevel) {
556
+ [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.minZoomLevel animated:TRUE mapView:mapView];
557
+ }
558
+ else if (zoomLevel > mapView.maxZoomLevel) {
559
+ [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.maxZoomLevel animated:TRUE mapView:mapView];
560
+ }
561
+
562
+ // Don't send region did change events until map has
563
+ // started rendering, as these won't represent the final location
564
+ if (mapView.hasStartedRendering) {
565
+ [self _emitRegionChangeEvent:mapView continuous:NO];
566
+ };
567
+
568
+ mapView.pendingCenter = mapView.region.center;
569
+ mapView.pendingSpan = mapView.region.span;
570
+ }
571
+
572
+ - (void)mapViewWillStartRenderingMap:(RNMMap *)mapView
573
+ {
574
+ if (!mapView.hasStartedRendering) {
575
+ mapView.onMapReady(@{});
576
+ mapView.hasStartedRendering = YES;
577
+ }
578
+ [mapView beginLoading];
579
+ }
580
+
581
+ - (void)mapViewDidFinishRenderingMap:(RNMMap *)mapView fullyRendered:(BOOL)fullyRendered
582
+ {
583
+ [mapView finishLoading];
584
+ }
585
+
586
+ #pragma mark Private
587
+
588
+ - (void)_regionChanged:(RNMMap *)mapView
589
+ {
590
+ BOOL needZoom = NO;
591
+ CGFloat newLongitudeDelta = 0.0f;
592
+ MKCoordinateRegion region = mapView.region;
593
+ // On iOS 7, it's possible that we observe invalid locations during initialization of the map.
594
+ // Filter those out.
595
+ if (!CLLocationCoordinate2DIsValid(region.center)) {
596
+ return;
597
+ }
598
+ // Calculation on float is not 100% accurate. If user zoom to max/min and then move, it's likely the map will auto zoom to max/min from time to time.
599
+ // So let's try to make map zoom back to 99% max or 101% min so that there are some buffer that moving the map won't constantly hitting the max/min bound.
600
+ if (mapView.maxDelta > FLT_EPSILON && region.span.longitudeDelta > mapView.maxDelta) {
601
+ needZoom = YES;
602
+ newLongitudeDelta = mapView.maxDelta * (1 - RNMMapZoomBoundBuffer);
603
+ } else if (mapView.minDelta > FLT_EPSILON && region.span.longitudeDelta < mapView.minDelta) {
604
+ needZoom = YES;
605
+ newLongitudeDelta = mapView.minDelta * (1 + RNMMapZoomBoundBuffer);
606
+ }
607
+ if (needZoom) {
608
+ region.span.latitudeDelta = region.span.latitudeDelta / region.span.longitudeDelta * newLongitudeDelta;
609
+ region.span.longitudeDelta = newLongitudeDelta;
610
+ mapView.region = region;
611
+ }
612
+
613
+ // Continuously observe region changes
614
+ [self _emitRegionChangeEvent:mapView continuous:YES];
615
+ }
616
+
617
+ - (void)_emitRegionChangeEvent:(RNMMap *)mapView continuous:(BOOL)continuous
618
+ {
619
+ if (!mapView.ignoreRegionChanges && mapView.onChange) {
620
+ MKCoordinateRegion region = mapView.region;
621
+ if (!CLLocationCoordinate2DIsValid(region.center)) {
622
+ return;
623
+ }
624
+
625
+ #define FLUSH_NAN(value) (isnan(value) ? 0 : value)
626
+ mapView.onChange(@{
627
+ @"continuous": @(continuous),
628
+ @"region": @{
629
+ @"latitude": @(FLUSH_NAN(region.center.latitude)),
630
+ @"longitude": @(FLUSH_NAN(region.center.longitude)),
631
+ @"latitudeDelta": @(FLUSH_NAN(region.span.latitudeDelta)),
632
+ @"longitudeDelta": @(FLUSH_NAN(region.span.longitudeDelta)),
633
+ }
634
+ });
635
+ }
636
+ }
637
+
638
+ /** Returns the distance of |pt| to |poly| in meters
639
+ *
640
+ *
641
+ */
642
+ - (double)distanceOfPoint:(MKMapPoint)pt toPoly:(RNMMapPolyline *)poly
643
+ {
644
+ double distance = MAXFLOAT;
645
+ for (int n = 0; n < poly.coordinates.count - 1; n++) {
646
+
647
+ MKMapPoint ptA = MKMapPointForCoordinate(poly.coordinates[n].coordinate);
648
+ MKMapPoint ptB = MKMapPointForCoordinate(poly.coordinates[n + 1].coordinate);
649
+
650
+ double xDelta = ptB.x - ptA.x;
651
+ double yDelta = ptB.y - ptA.y;
652
+
653
+ if (xDelta == 0.0 && yDelta == 0.0) {
654
+ continue;
655
+ }
656
+
657
+ double u = ((pt.x - ptA.x) * xDelta + (pt.y - ptA.y) * yDelta) / (xDelta * xDelta + yDelta * yDelta);
658
+ MKMapPoint ptClosest;
659
+ if (u < 0.0) {
660
+ ptClosest = ptA;
661
+ }
662
+ else if (u > 1.0) {
663
+ ptClosest = ptB;
664
+ }
665
+ else {
666
+ ptClosest = MKMapPointMake(ptA.x + u * xDelta, ptA.y + u * yDelta);
667
+ }
668
+
669
+ distance = MIN(distance, MKMetersBetweenMapPoints(ptClosest, pt));
670
+ }
671
+
672
+ return distance;
673
+ }
674
+
675
+
676
+ /** Converts |px| to meters at location |pt| */
677
+ - (double)metersFromPixel:(NSUInteger)px atPoint:(CGPoint)pt forMap:(RNMMap *)mapView
678
+ {
679
+ CGPoint ptB = CGPointMake(pt.x + px, pt.y);
680
+
681
+ CLLocationCoordinate2D coordA = [mapView convertPoint:pt toCoordinateFromView:mapView];
682
+ CLLocationCoordinate2D coordB = [mapView convertPoint:ptB toCoordinateFromView:mapView];
683
+
684
+ return MKMetersBetweenMapPoints(MKMapPointForCoordinate(coordA), MKMapPointForCoordinate(coordB));
685
+ }
686
+
687
+ + (double)longitudeToPixelSpaceX:(double)longitude
688
+ {
689
+ return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
690
+ }
691
+
692
+ + (double)latitudeToPixelSpaceY:(double)latitude
693
+ {
694
+ if (latitude == 90.0) {
695
+ return 0;
696
+ } else if (latitude == -90.0) {
697
+ return MERCATOR_OFFSET * 2;
698
+ } else {
699
+ return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
700
+ }
701
+ }
702
+
703
+ + (double)pixelSpaceXToLongitude:(double)pixelX
704
+ {
705
+ return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
706
+ }
707
+
708
+ + (double)pixelSpaceYToLatitude:(double)pixelY
709
+ {
710
+ return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
711
+ }
712
+
713
+ #pragma mark -
714
+ #pragma mark Helper methods
715
+
716
+ - (MKCoordinateSpan)coordinateSpanWithMapView:(RNMMap *)mapView
717
+ centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
718
+ andZoomLevel:(double)zoomLevel
719
+ {
720
+ // convert center coordiate to pixel space
721
+ double centerPixelX = [RNMMapManager longitudeToPixelSpaceX:centerCoordinate.longitude];
722
+ double centerPixelY = [RNMMapManager latitudeToPixelSpaceY:centerCoordinate.latitude];
723
+
724
+ // determine the scale value from the zoom level
725
+ double zoomExponent = RNMMapMaxZoomLevel - zoomLevel;
726
+ double zoomScale = pow(2, zoomExponent);
727
+
728
+ // scale the map’s size in pixel space
729
+ CGSize mapSizeInPixels = mapView.bounds.size;
730
+ double scaledMapWidth = mapSizeInPixels.width * zoomScale;
731
+ double scaledMapHeight = mapSizeInPixels.height * zoomScale;
732
+
733
+ // figure out the position of the top-left pixel
734
+ double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
735
+ double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
736
+
737
+ // find delta between left and right longitudes
738
+ CLLocationDegrees minLng = [RNMMapManager pixelSpaceXToLongitude:topLeftPixelX];
739
+ CLLocationDegrees maxLng = [RNMMapManager pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
740
+ CLLocationDegrees longitudeDelta = maxLng - minLng;
741
+
742
+ // find delta between top and bottom latitudes
743
+ CLLocationDegrees minLat = [RNMMapManager pixelSpaceYToLatitude:topLeftPixelY];
744
+ CLLocationDegrees maxLat = [RNMMapManager pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
745
+ CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
746
+
747
+ // create and return the lat/lng span
748
+ MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
749
+ return span;
750
+ }
751
+
752
+ #pragma mark -
753
+ #pragma mark Public methods
754
+
755
+ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
756
+ zoomLevel:(double)zoomLevel
757
+ animated:(BOOL)animated
758
+ mapView:(RNMMap *)mapView
759
+ {
760
+ // clamp large numbers to 28
761
+ zoomLevel = MIN(zoomLevel, RNMMapMaxZoomLevel);
762
+
763
+ // use the zoom level to compute the region
764
+ MKCoordinateSpan span = [self coordinateSpanWithMapView:mapView centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
765
+ MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
766
+
767
+ // set the region like normal
768
+ [mapView setRegion:region animated:animated];
769
+ }
770
+
771
+ //KMapView cannot display tiles that cross the pole (as these would involve wrapping the map from top to bottom, something that a Mercator projection just cannot do).
772
+ -(MKCoordinateRegion)coordinateRegionWithMapView:(RNMMap *)mapView
773
+ centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
774
+ andZoomLevel:(double)zoomLevel
775
+ {
776
+ // clamp lat/long values to appropriate ranges
777
+ centerCoordinate.latitude = MIN(MAX(-90.0, centerCoordinate.latitude), 90.0);
778
+ centerCoordinate.longitude = fmod(centerCoordinate.longitude, 180.0);
779
+
780
+ // convert center coordiate to pixel space
781
+ double centerPixelX = [RNMMapManager longitudeToPixelSpaceX:centerCoordinate.longitude];
782
+ double centerPixelY = [RNMMapManager latitudeToPixelSpaceY:centerCoordinate.latitude];
783
+
784
+ // determine the scale value from the zoom level
785
+ double zoomExponent = RNMMapMaxZoomLevel - zoomLevel;
786
+ double zoomScale = pow(2, zoomExponent);
787
+
788
+ // scale the map’s size in pixel space
789
+ CGSize mapSizeInPixels = mapView.bounds.size;
790
+ double scaledMapWidth = mapSizeInPixels.width * zoomScale;
791
+ double scaledMapHeight = mapSizeInPixels.height * zoomScale;
792
+
793
+ // figure out the position of the left pixel
794
+ double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
795
+
796
+ // find delta between left and right longitudes
797
+ CLLocationDegrees minLng = [RNMMapManager pixelSpaceXToLongitude:topLeftPixelX];
798
+ CLLocationDegrees maxLng = [RNMMapManager pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
799
+ CLLocationDegrees longitudeDelta = maxLng - minLng;
800
+
801
+ // if we’re at a pole then calculate the distance from the pole towards the equator
802
+ // as MKMapView doesn’t like drawing boxes over the poles
803
+ double topPixelY = centerPixelY - (scaledMapHeight / 2);
804
+ double bottomPixelY = centerPixelY + (scaledMapHeight / 2);
805
+ BOOL adjustedCenterPoint = NO;
806
+ if (topPixelY > MERCATOR_OFFSET * 2) {
807
+ topPixelY = centerPixelY - scaledMapHeight;
808
+ bottomPixelY = MERCATOR_OFFSET * 2;
809
+ adjustedCenterPoint = YES;
810
+ }
811
+
812
+ // find delta between top and bottom latitudes
813
+ CLLocationDegrees minLat = [RNMMapManager pixelSpaceYToLatitude:topPixelY];
814
+ CLLocationDegrees maxLat = [RNMMapManager pixelSpaceYToLatitude:bottomPixelY];
815
+ CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
816
+
817
+ // create and return the lat/lng span
818
+ MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
819
+ MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
820
+ // once again, MKMapView doesn’t like drawing boxes over the poles
821
+ // so adjust the center coordinate to the center of the resulting region
822
+ if (adjustedCenterPoint) {
823
+ region.center.latitude = [RNMMapManager pixelSpaceYToLatitude:((bottomPixelY + topPixelY) / 2.0)];
824
+ }
825
+
826
+ return region;
827
+ }
828
+
829
+ - (double) zoomLevel:(RNMMap *)mapView {
830
+ MKCoordinateRegion region = mapView.region;
831
+
832
+ double centerPixelX = [RNMMapManager longitudeToPixelSpaceX: region.center.longitude];
833
+ double topLeftPixelX = [RNMMapManager longitudeToPixelSpaceX: region.center.longitude - region.span.longitudeDelta / 2];
834
+
835
+ double scaledMapWidth = (centerPixelX - topLeftPixelX) * 2;
836
+ CGSize mapSizeInPixels = mapView.bounds.size;
837
+ double zoomScale = scaledMapWidth / mapSizeInPixels.width;
838
+ double zoomExponent = log(zoomScale) / log(2);
839
+ double zoomLevel = RNMMapMaxZoomLevel - zoomExponent;
840
+
841
+ return zoomLevel;
842
+ }
843
+
844
+ #pragma mark MKMapViewDelegate - Tracking the User Location
845
+
846
+ - (void)mapView:(RNMMap *)mapView didFailToLocateUserWithError:(NSError *)error {
847
+ id event = @{@"error": @{ @"message": error.localizedDescription }};
848
+ if (mapView.onUserLocationChange) {
849
+ mapView.onUserLocationChange(event);
850
+ }
851
+ }
852
+
853
+ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
854
+ return YES;
855
+ }
856
+
857
+ @end