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
@@ -1,1253 +0,0 @@
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 "AIRMapManager.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 "AIRMap.h"
20
- #import "AIRMapMarker.h"
21
- #import "AIRMapPolyline.h"
22
- #import "AIRMapPolygon.h"
23
- #import "AIRMapCircle.h"
24
- #import "SMCalloutView.h"
25
- #import "AIRMapUrlTile.h"
26
- #import "AIRMapWMSTile.h"
27
- #import "AIRMapLocalTile.h"
28
- #import "AIRMapSnapshot.h"
29
- #import "RCTConvert+AirMap.h"
30
- #import "AIRMapOverlay.h"
31
- #import <MapKit/MapKit.h>
32
-
33
- static NSString *const RCTMapViewKey = @"MapView";
34
-
35
-
36
- @interface AIRMapManager() <MKMapViewDelegate, UIGestureRecognizerDelegate>
37
-
38
- - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
39
-
40
- @end
41
-
42
- @implementation AIRMapManager{
43
- BOOL _hasObserver;
44
- }
45
-
46
- RCT_EXPORT_MODULE()
47
-
48
- - (UIView *)view
49
- {
50
- AIRMap *map = [AIRMap 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, AIRMap)
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, AIRMap)
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, AIRMap)
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*, AIRMap)
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(getMapBoundaries:(nonnull NSNumber *)reactTag
179
- resolver:(RCTPromiseResolveBlock)resolve
180
- rejecter:(RCTPromiseRejectBlock)reject)
181
- {
182
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
183
- id view = viewRegistry[reactTag];
184
- if (![view isKindOfClass:[AIRMap class]]) {
185
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
186
- } else {
187
- NSArray *boundingBox = [view getMapBoundaries];
188
-
189
- resolve(@{
190
- @"northEast" : @{
191
- @"longitude" : boundingBox[0][0],
192
- @"latitude" : boundingBox[0][1]
193
- },
194
- @"southWest" : @{
195
- @"longitude" : boundingBox[1][0],
196
- @"latitude" : boundingBox[1][1]
197
- }
198
- });
199
- }
200
- }];
201
- }
202
-
203
-
204
-
205
- RCT_EXPORT_METHOD(getCamera:(nonnull NSNumber *)reactTag
206
- resolver: (RCTPromiseResolveBlock)resolve
207
- rejecter:(RCTPromiseRejectBlock)reject)
208
- {
209
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
210
- id view = viewRegistry[reactTag];
211
- AIRMap *mapView = (AIRMap *)view;
212
- if (![view isKindOfClass:[AIRMap class]]) {
213
- reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL);
214
- } else {
215
- MKMapCamera *camera = [mapView camera];
216
- resolve(@{
217
- @"center": @{
218
- @"latitude": @(camera.centerCoordinate.latitude),
219
- @"longitude": @(camera.centerCoordinate.longitude),
220
- },
221
- @"pitch": @(camera.pitch),
222
- @"heading": @(camera.heading),
223
- @"altitude": @(camera.altitude),
224
- });
225
- }
226
- }];
227
- }
228
-
229
-
230
- RCT_EXPORT_METHOD(setCamera:(nonnull NSNumber *)reactTag
231
- camera:(id)json)
232
- {
233
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
234
- id view = viewRegistry[reactTag];
235
- if (![view isKindOfClass:[AIRMap class]]) {
236
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
237
- } else {
238
- AIRMap *mapView = (AIRMap *)view;
239
-
240
- // Merge the changes given with the current camera
241
- MKMapCamera *camera = [RCTConvert MKMapCameraWithDefaults:json existingCamera:[mapView camera]];
242
-
243
- // don't emit region change events when we are setting the camera
244
- BOOL originalIgnore = mapView.ignoreRegionChanges;
245
- mapView.ignoreRegionChanges = YES;
246
- [mapView setCamera:camera animated:NO];
247
- mapView.ignoreRegionChanges = originalIgnore;
248
- }
249
- }];
250
- }
251
-
252
-
253
- RCT_EXPORT_METHOD(animateCamera:(nonnull NSNumber *)reactTag
254
- withCamera:(id)json
255
- withDuration:(CGFloat)duration)
256
- {
257
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
258
- id view = viewRegistry[reactTag];
259
- if (![view isKindOfClass:[AIRMap class]]) {
260
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
261
- } else {
262
- AIRMap *mapView = (AIRMap *)view;
263
-
264
- // Merge the changes given with the current camera
265
- MKMapCamera *camera = [RCTConvert MKMapCameraWithDefaults:json existingCamera:[mapView camera]];
266
-
267
- // don't emit region change events when we are setting the camera
268
- BOOL originalIgnore = mapView.ignoreRegionChanges;
269
- mapView.ignoreRegionChanges = YES;
270
- [AIRMap animateWithDuration:duration/1000 animations:^{
271
- [mapView setCamera:camera animated:YES];
272
- } completion:^(BOOL finished){
273
- mapView.ignoreRegionChanges = originalIgnore;
274
- }];
275
- }
276
- }];
277
- }
278
-
279
- RCT_EXPORT_METHOD(animateToRegion:(nonnull NSNumber *)reactTag
280
- withRegion:(MKCoordinateRegion)region
281
- withDuration:(CGFloat)duration)
282
- {
283
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
284
- id view = viewRegistry[reactTag];
285
- if (![view isKindOfClass:[AIRMap class]]) {
286
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
287
- } else {
288
- [AIRMap animateWithDuration:duration/1000 animations:^{
289
- [(AIRMap *)view setRegion:region animated:YES];
290
- }];
291
- }
292
- }];
293
- }
294
-
295
- RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag
296
- edgePadding:(nonnull NSDictionary *)edgePadding
297
- animated:(BOOL)animated)
298
- {
299
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
300
- id view = viewRegistry[reactTag];
301
- if (![view isKindOfClass:[AIRMap class]]) {
302
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
303
- } else {
304
- AIRMap *mapView = (AIRMap *)view;
305
- // TODO(lmr): we potentially want to include overlays here... and could concat the two arrays together.
306
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
307
- [mapView showAnnotations:mapView.annotations animated:animated];
308
- });
309
- }
310
- }];
311
- }
312
-
313
- RCT_EXPORT_METHOD(fitToSuppliedMarkers:(nonnull NSNumber *)reactTag
314
- markers:(nonnull NSArray *)markers
315
- edgePadding:(nonnull NSDictionary *)edgePadding
316
- animated:(BOOL)animated)
317
- {
318
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
319
- id view = viewRegistry[reactTag];
320
- if (![view isKindOfClass:[AIRMap class]]) {
321
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
322
- } else {
323
- AIRMap *mapView = (AIRMap *)view;
324
- // TODO(lmr): we potentially want to include overlays here... and could concat the two arrays together.
325
- // id annotations = mapView.annotations;
326
-
327
- NSPredicate *filterMarkers = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
328
- AIRMapMarker *marker = (AIRMapMarker *)evaluatedObject;
329
- return [marker isKindOfClass:[AIRMapMarker class]] && [markers containsObject:marker.identifier];
330
- }];
331
-
332
- NSArray *filteredMarkers = [mapView.annotations filteredArrayUsingPredicate:filterMarkers];
333
-
334
- [mapView showAnnotations:filteredMarkers animated:animated];
335
-
336
- }
337
- }];
338
- }
339
-
340
- RCT_EXPORT_METHOD(fitToCoordinates:(nonnull NSNumber *)reactTag
341
- coordinates:(nonnull NSArray<AIRMapCoordinate *> *)coordinates
342
- edgePadding:(nonnull NSDictionary *)edgePadding
343
- animated:(BOOL)animated)
344
- {
345
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
346
- id view = viewRegistry[reactTag];
347
- if (![view isKindOfClass:[AIRMap class]]) {
348
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
349
- } else {
350
- AIRMap *mapView = (AIRMap *)view;
351
-
352
- // Create Polyline with coordinates
353
- CLLocationCoordinate2D coords[coordinates.count];
354
- for(int i = 0; i < coordinates.count; i++)
355
- {
356
- coords[i] = coordinates[i].coordinate;
357
- }
358
- MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordinates.count];
359
-
360
- // Set Map viewport
361
- CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
362
- CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
363
- CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
364
- CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
365
-
366
- [mapView setVisibleMapRect:[polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(top, left, bottom, right) animated:animated];
367
-
368
- }
369
- }];
370
- }
371
-
372
- RCT_EXPORT_METHOD(takeSnapshot:(nonnull NSNumber *)reactTag
373
- width:(nonnull NSNumber *)width
374
- height:(nonnull NSNumber *)height
375
- region:(MKCoordinateRegion)region
376
- format:(nonnull NSString *)format
377
- quality:(nonnull NSNumber *)quality
378
- result:(nonnull NSString *)result
379
- callback:(RCTResponseSenderBlock)callback)
380
- {
381
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
382
- id view = viewRegistry[reactTag];
383
- if (![view isKindOfClass:[AIRMap class]]) {
384
- RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
385
- } else {
386
- AIRMap *mapView = (AIRMap *)view;
387
- MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
388
-
389
- options.mapType = mapView.mapType;
390
- options.region = (region.center.latitude && region.center.longitude) ? region : mapView.region;
391
- options.size = CGSizeMake(
392
- ([width floatValue] == 0) ? mapView.bounds.size.width : [width floatValue],
393
- ([height floatValue] == 0) ? mapView.bounds.size.height : [height floatValue]
394
- );
395
- options.scale = [[UIScreen mainScreen] scale];
396
-
397
- MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
398
-
399
- [self takeMapSnapshot:mapView
400
- snapshotter:snapshotter
401
- format:format
402
- quality:quality.floatValue
403
- result:result
404
- callback:callback];
405
- }
406
- }];
407
- }
408
-
409
- RCT_EXPORT_METHOD(pointForCoordinate:(nonnull NSNumber *)reactTag
410
- coordinate: (NSDictionary *)coordinate
411
- resolver: (RCTPromiseResolveBlock)resolve
412
- rejecter:(RCTPromiseRejectBlock)reject)
413
- {
414
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
415
- id view = viewRegistry[reactTag];
416
- AIRMap *mapView = (AIRMap *)view;
417
- if (![view isKindOfClass:[AIRMap class]]) {
418
- reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL);
419
- } else {
420
- CGPoint touchPoint = [mapView convertCoordinate:
421
- CLLocationCoordinate2DMake(
422
- [coordinate[@"latitude"] doubleValue],
423
- [coordinate[@"longitude"] doubleValue]
424
- )
425
- toPointToView:mapView];
426
-
427
- resolve(@{
428
- @"x": @(touchPoint.x),
429
- @"y": @(touchPoint.y),
430
- });
431
- }
432
- }];
433
- }
434
-
435
- RCT_EXPORT_METHOD(getMarkersFrames:(nonnull NSNumber *)reactTag
436
- onlyVisible:(BOOL)onlyVisible
437
- resolver: (RCTPromiseResolveBlock)resolve
438
- rejecter:(RCTPromiseRejectBlock)reject)
439
- {
440
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
441
- id view = viewRegistry[reactTag];
442
- AIRMap *mapView = (AIRMap *)view;
443
- if (![view isKindOfClass:[AIRMap class]]) {
444
- reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL);
445
- } else {
446
- resolve([mapView getMarkersFramesWithOnlyVisible:onlyVisible]);
447
- }
448
- }];
449
- }
450
-
451
-
452
-
453
- RCT_EXPORT_METHOD(coordinateForPoint:(nonnull NSNumber *)reactTag
454
- point:(NSDictionary *)point
455
- resolver: (RCTPromiseResolveBlock)resolve
456
- rejecter:(RCTPromiseRejectBlock)reject)
457
- {
458
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
459
- id view = viewRegistry[reactTag];
460
- AIRMap *mapView = (AIRMap *)view;
461
- if (![view isKindOfClass:[AIRMap class]]) {
462
- reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL);
463
- } else {
464
- CLLocationCoordinate2D coordinate = [mapView convertPoint:
465
- CGPointMake(
466
- [point[@"x"] doubleValue],
467
- [point[@"y"] doubleValue]
468
- )
469
- toCoordinateFromView:mapView];
470
-
471
- resolve(@{
472
- @"latitude": @(coordinate.latitude),
473
- @"longitude": @(coordinate.longitude),
474
- });
475
- }
476
- }];
477
- }
478
-
479
- RCT_EXPORT_METHOD(getAddressFromCoordinates:(nonnull NSNumber *)reactTag
480
- coordinate: (NSDictionary *)coordinate
481
- resolver: (RCTPromiseResolveBlock)resolve
482
- rejecter:(RCTPromiseRejectBlock)reject)
483
- {
484
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
485
- id view = viewRegistry[reactTag];
486
- if (![view isKindOfClass:[AIRMap class]]) {
487
- reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid view returned from registry, expecting AIRMap, got: %@", view], NULL);
488
- } else {
489
- if (coordinate == nil ||
490
- ![[coordinate allKeys] containsObject:@"latitude"] ||
491
- ![[coordinate allKeys] containsObject:@"longitude"]) {
492
- reject(@"Invalid argument", [NSString stringWithFormat:@"Invalid coordinate format"], NULL);
493
- }
494
- CLLocation *location = [[CLLocation alloc] initWithLatitude:[coordinate[@"latitude"] doubleValue]
495
- longitude:[coordinate[@"longitude"] doubleValue]];
496
- CLGeocoder *geoCoder = [[CLGeocoder alloc] init];
497
- [geoCoder reverseGeocodeLocation:location
498
- completionHandler:^(NSArray *placemarks, NSError *error) {
499
- if (error == nil && [placemarks count] > 0){
500
- CLPlacemark *placemark = placemarks[0];
501
- resolve(@{
502
- @"name" : [NSString stringWithFormat:@"%@", placemark.name],
503
- @"thoroughfare" : [NSString stringWithFormat:@"%@", placemark.thoroughfare],
504
- @"subThoroughfare" : [NSString stringWithFormat:@"%@", placemark.subThoroughfare],
505
- @"locality" : [NSString stringWithFormat:@"%@", placemark.locality],
506
- @"subLocality" : [NSString stringWithFormat:@"%@", placemark.subLocality],
507
- @"administrativeArea" : [NSString stringWithFormat:@"%@", placemark.administrativeArea],
508
- @"subAdministrativeArea" : [NSString stringWithFormat:@"%@", placemark.subAdministrativeArea],
509
- @"postalCode" : [NSString stringWithFormat:@"%@", placemark.postalCode],
510
- @"countryCode" : [NSString stringWithFormat:@"%@", placemark.ISOcountryCode],
511
- @"country" : [NSString stringWithFormat:@"%@", placemark.country],
512
- });
513
- } else {
514
- reject(@"Invalid argument", [NSString stringWithFormat:@"Can not get address location"], NULL);
515
- }
516
- }];
517
- }
518
- }];
519
- }
520
-
521
- #pragma mark Take Snapshot
522
- - (void)takeMapSnapshot:(AIRMap *)mapView
523
- snapshotter:(MKMapSnapshotter *) snapshotter
524
- format:(NSString *)format
525
- quality:(CGFloat) quality
526
- result:(NSString *)result
527
- callback:(RCTResponseSenderBlock) callback {
528
- NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
529
- NSString *pathComponent = [NSString stringWithFormat:@"Documents/snapshot-%.20lf.%@", timeStamp, format];
530
- NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent: pathComponent];
531
-
532
- [snapshotter startWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
533
- completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
534
- if (error) {
535
- callback(@[error]);
536
- return;
537
- }
538
- MKAnnotationView *pin = [[MKMarkerAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:nil];
539
-
540
- UIImage *image = snapshot.image;
541
- UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
542
- {
543
- [image drawAtPoint:CGPointMake(0.0f, 0.0f)];
544
-
545
- CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
546
-
547
- for (id <AIRMapSnapshot> overlay in mapView.overlays) {
548
- if ([overlay respondsToSelector:@selector(drawToSnapshot:context:)]) {
549
- [overlay drawToSnapshot:snapshot context:UIGraphicsGetCurrentContext()];
550
- }
551
- }
552
-
553
- for (id <MKAnnotation> annotation in mapView.annotations) {
554
- CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
555
-
556
- MKAnnotationView* anView = [mapView viewForAnnotation: annotation];
557
-
558
- if (anView){
559
- pin = anView;
560
- }
561
-
562
- if (CGRectContainsPoint(rect, point)) {
563
- point.x = point.x + pin.centerOffset.x - (pin.bounds.size.width / 2.0f);
564
- point.y = point.y + pin.centerOffset.y - (pin.bounds.size.height / 2.0f);
565
- if (pin.image) {
566
- [pin.image drawAtPoint:point];
567
- } else {
568
- CGRect pinRect = CGRectMake(point.x, point.y, pin.bounds.size.width, pin.bounds.size.height);
569
- [pin drawViewHierarchyInRect:pinRect afterScreenUpdates:NO];
570
- }
571
- }
572
- }
573
-
574
- UIImage *compositeImage = UIGraphicsGetImageFromCurrentImageContext();
575
-
576
- NSData *data;
577
- if ([format isEqualToString:@"png"]) {
578
- data = UIImagePNGRepresentation(compositeImage);
579
- }
580
- else if([format isEqualToString:@"jpg"]) {
581
- data = UIImageJPEGRepresentation(compositeImage, quality);
582
- }
583
-
584
- if ([result isEqualToString:@"file"]) {
585
- [data writeToFile:filePath atomically:YES];
586
- callback(@[[NSNull null], filePath]);
587
- }
588
- else if ([result isEqualToString:@"base64"]) {
589
- callback(@[[NSNull null], [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]]);
590
- }
591
- }
592
- UIGraphicsEndImageContext();
593
- }];
594
- }
595
-
596
- #pragma mark Gesture Recognizer Handlers
597
-
598
- #define MAX_DISTANCE_PX 10.0f
599
- - (void)handleMapTap:(UITapGestureRecognizer *)recognizer {
600
- AIRMap *map = (AIRMap *)recognizer.view;
601
-
602
- CGPoint tapPoint = [recognizer locationInView:map];
603
- CLLocationCoordinate2D tapCoordinate = [map convertPoint:tapPoint toCoordinateFromView:map];
604
- MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoordinate);
605
- CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
606
-
607
- double maxMeters = [self metersFromPixel:MAX_DISTANCE_PX atPoint:tapPoint forMap:map];
608
- float nearestDistance = MAXFLOAT;
609
- AIRMapPolyline *nearestPolyline = nil;
610
-
611
- for (id<MKOverlay> overlay in map.overlays) {
612
- if([overlay isKindOfClass:[AIRMapPolygon class]]){
613
- AIRMapPolygon *polygon = (AIRMapPolygon*) overlay;
614
- if (polygon.onPress) {
615
- CGMutablePathRef mpr = CGPathCreateMutable();
616
-
617
- for(int i = 0; i < polygon.coordinates.count; i++) {
618
- AIRMapCoordinate *c = polygon.coordinates[i];
619
- MKMapPoint mp = MKMapPointForCoordinate(c.coordinate);
620
- if (i == 0) {
621
- CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
622
- } else {
623
- CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
624
- }
625
- }
626
-
627
- if (CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE)) {
628
- id event = @{
629
- @"action": @"polygon-press",
630
- @"coordinate": @{
631
- @"latitude": @(tapCoordinate.latitude),
632
- @"longitude": @(tapCoordinate.longitude),
633
- },
634
- };
635
- polygon.onPress(event);
636
- }
637
-
638
- CGPathRelease(mpr);
639
- }
640
- }
641
-
642
- if([overlay isKindOfClass:[AIRMapPolyline class]]){
643
- AIRMapPolyline *polyline = (AIRMapPolyline*) overlay;
644
- if (polyline.onPress) {
645
- float distance = [self distanceOfPoint:MKMapPointForCoordinate(tapCoordinate)
646
- toPoly:polyline];
647
- if (distance < nearestDistance) {
648
- nearestDistance = distance;
649
- nearestPolyline = polyline;
650
- }
651
- }
652
- }
653
-
654
- if ([overlay isKindOfClass:[AIRMapOverlay class]]) {
655
- AIRMapOverlay *imageOverlay = (AIRMapOverlay*) overlay;
656
- if (MKMapRectContainsPoint(imageOverlay.boundingMapRect, mapPoint)) {
657
- if (imageOverlay.onPress) {
658
- id event = @{
659
- @"action": @"image-overlay-press",
660
- @"name": imageOverlay.name ?: @"unknown",
661
- @"coordinate": @{
662
- @"latitude": @(imageOverlay.coordinate.latitude),
663
- @"longitude": @(imageOverlay.coordinate.longitude)
664
- }
665
- };
666
- imageOverlay.onPress(event);
667
- }
668
- }
669
- }
670
-
671
- }
672
-
673
- if (nearestDistance <= maxMeters) {
674
- id event = @{
675
- @"action": @"polyline-press",
676
- @"coordinate": @{
677
- @"latitude": @(tapCoordinate.latitude),
678
- @"longitude": @(tapCoordinate.longitude)
679
- }
680
- };
681
- nearestPolyline.onPress(event);
682
- }
683
-
684
- if (!map.onPress) return;
685
- map.onPress(@{
686
- @"coordinate": @{
687
- @"latitude": @(tapCoordinate.latitude),
688
- @"longitude": @(tapCoordinate.longitude),
689
- },
690
- @"position": @{
691
- @"x": @(tapPoint.x),
692
- @"y": @(tapPoint.y),
693
- },
694
- });
695
-
696
- }
697
-
698
- - (void)handleMapDrag:(UIPanGestureRecognizer*)recognizer {
699
- AIRMap *map = (AIRMap *)recognizer.view;
700
- if (!map.onPanDrag) return;
701
-
702
- CGPoint touchPoint = [recognizer locationInView:map];
703
- CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
704
- map.onPanDrag(@{
705
- @"coordinate": @{
706
- @"latitude": @(coord.latitude),
707
- @"longitude": @(coord.longitude),
708
- },
709
- @"position": @{
710
- @"x": @(touchPoint.x),
711
- @"y": @(touchPoint.y),
712
- },
713
- });
714
-
715
- }
716
-
717
- - (void)handleMapDoubleTap:(UIPanGestureRecognizer*)recognizer {
718
- AIRMap *map = (AIRMap *)recognizer.view;
719
- if (!map.onDoublePress) return;
720
-
721
- CGPoint touchPoint = [recognizer locationInView:map];
722
- CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
723
- map.onDoublePress(@{
724
- @"coordinate": @{
725
- @"latitude": @(coord.latitude),
726
- @"longitude": @(coord.longitude),
727
- },
728
- @"position": @{
729
- @"x": @(touchPoint.x),
730
- @"y": @(touchPoint.y),
731
- },
732
- });
733
-
734
- }
735
-
736
-
737
- - (void)handleMapLongPress:(UITapGestureRecognizer *)recognizer {
738
-
739
- // NOTE: android only does the equivalent of "began", so we only send in this case
740
- if (recognizer.state != UIGestureRecognizerStateBegan) return;
741
-
742
- AIRMap *map = (AIRMap *)recognizer.view;
743
- if (!map.onLongPress) return;
744
-
745
- CGPoint touchPoint = [recognizer locationInView:map];
746
- CLLocationCoordinate2D coord = [map convertPoint:touchPoint toCoordinateFromView:map];
747
-
748
- map.onLongPress(@{
749
- @"coordinate": @{
750
- @"latitude": @(coord.latitude),
751
- @"longitude": @(coord.longitude),
752
- },
753
- @"position": @{
754
- @"x": @(touchPoint.x),
755
- @"y": @(touchPoint.y),
756
- },
757
- });
758
- }
759
-
760
- #pragma mark MKMapViewDelegate
761
-
762
- #pragma mark Polyline stuff
763
-
764
- - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay{
765
- if ([overlay isKindOfClass:[AIRMapPolyline class]]) {
766
- return ((AIRMapPolyline *)overlay).renderer;
767
- } else if ([overlay isKindOfClass:[AIRMapPolygon class]]) {
768
- return ((AIRMapPolygon *)overlay).renderer;
769
- } else if ([overlay isKindOfClass:[AIRMapCircle class]]) {
770
- return ((AIRMapCircle *)overlay).renderer;
771
- } else if ([overlay isKindOfClass:[AIRMapUrlTile class]]) {
772
- return ((AIRMapUrlTile *)overlay).renderer;
773
- } else if ([overlay isKindOfClass:[AIRMapWMSTile class]]) {
774
- return ((AIRMapWMSTile *)overlay).renderer;
775
- } else if ([overlay isKindOfClass:[AIRMapLocalTile class]]) {
776
- return ((AIRMapLocalTile *)overlay).renderer;
777
- } else if ([overlay isKindOfClass:[AIRMapOverlay class]]) {
778
- return ((AIRMapOverlay *)overlay).renderer;
779
- } else if([overlay isKindOfClass:[MKTileOverlay class]]) {
780
- return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
781
- } else {
782
- return nil;
783
- }
784
- }
785
-
786
-
787
- #pragma mark Annotation Stuff
788
-
789
- - (void)mapView:(AIRMap *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views
790
- {
791
- if(!mapView.userLocationCalloutEnabled){
792
- for(MKAnnotationView* view in views){
793
- if ([view.annotation isKindOfClass:[MKUserLocation class]]){
794
- [view setEnabled:NO];
795
- [view setCanShowCallout:NO];
796
- break;
797
- }
798
- }
799
- }
800
- }
801
-
802
-
803
- - (void)mapView:(AIRMap *)mapView didSelectAnnotationView:(MKAnnotationView *)view
804
- {
805
- if ([view.annotation isKindOfClass:[AIRMapMarker class]]) {
806
- [(AIRMapMarker *)view.annotation showCalloutView];
807
- } else if ([view.annotation isKindOfClass:[MKUserLocation class]] && mapView.userLocationAnnotationTitle != nil && view.annotation.title != mapView.userLocationAnnotationTitle) {
808
- [(MKUserLocation*)view.annotation setTitle: mapView.userLocationAnnotationTitle];
809
- }
810
-
811
- }
812
-
813
- - (void)mapView:(AIRMap *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
814
- if ([view.annotation isKindOfClass:[AIRMapMarker class]]) {
815
- [(AIRMapMarker *)view.annotation hideCalloutView];
816
- }
817
- }
818
-
819
- - (MKAnnotationView *)mapView:(__unused AIRMap *)mapView viewForAnnotation:(AIRMapMarker *)marker
820
- {
821
- if (![marker isKindOfClass:[AIRMapMarker class]]) {
822
- if ([marker isKindOfClass:[MKUserLocation class]] && mapView.userLocationAnnotationTitle != nil) {
823
- [(MKUserLocation*)marker setTitle: mapView.userLocationAnnotationTitle];
824
- return nil;
825
- }
826
- return nil;
827
- }
828
-
829
- marker.map = mapView;
830
- return [marker getAnnotationView];
831
- }
832
-
833
- static int kDragCenterContext;
834
-
835
- - (void)mapView:(AIRMap *)mapView
836
- annotationView:(MKAnnotationView *)view
837
- didChangeDragState:(MKAnnotationViewDragState)newState
838
- fromOldState:(MKAnnotationViewDragState)oldState
839
- {
840
- if (![view.annotation isKindOfClass:[AIRMapMarker class]]) return;
841
- AIRMapMarker *marker = (AIRMapMarker *)view.annotation;
842
-
843
- BOOL isPinView = [view isKindOfClass:[MKMarkerAnnotationView class]];
844
-
845
- id event = @{
846
- @"id": marker.identifier ?: @"unknown",
847
- @"coordinate": @{
848
- @"latitude": @(marker.coordinate.latitude),
849
- @"longitude": @(marker.coordinate.longitude)
850
- }
851
- };
852
-
853
- if (newState == MKAnnotationViewDragStateEnding || newState == MKAnnotationViewDragStateCanceling) {
854
- if (!isPinView) {
855
- [view setDragState:MKAnnotationViewDragStateNone animated:NO];
856
- }
857
- if (mapView.onMarkerDragEnd) mapView.onMarkerDragEnd(event);
858
- if (marker.onDragEnd) marker.onDragEnd(event);
859
-
860
- if(_hasObserver) [view removeObserver:self forKeyPath:@"center"];
861
- _hasObserver = NO;
862
- } else if (newState == MKAnnotationViewDragStateStarting) {
863
- // MapKit doesn't emit continuous drag events. To get around this, we are going to use KVO.
864
- [view addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:&kDragCenterContext];
865
- _hasObserver = YES;
866
- if (mapView.onMarkerDragStart) mapView.onMarkerDragStart(event);
867
- if (marker.onDragStart) marker.onDragStart(event);
868
- }
869
- }
870
-
871
- - (void)observeValueForKeyPath:(NSString *)keyPath
872
- ofObject:(id)object
873
- change:(NSDictionary *)change
874
- context:(void *)context
875
- {
876
- if ([keyPath isEqualToString:@"center"] && [object isKindOfClass:[MKAnnotationView class]]) {
877
- MKAnnotationView *view = (MKAnnotationView *)object;
878
- AIRMapMarker *marker = (AIRMapMarker *)view.annotation;
879
-
880
- // a marker we don't control might be getting dragged. Check just in case.
881
- if (!marker) return;
882
-
883
- AIRMap *map = marker.map;
884
-
885
- // don't waste time calculating if there are no events to listen to it
886
- if (!map.onMarkerDrag && !marker.onDrag) return;
887
-
888
- CGPoint position = CGPointMake(view.center.x - view.centerOffset.x, view.center.y - view.centerOffset.y);
889
- CLLocationCoordinate2D coordinate = [map convertPoint:position toCoordinateFromView:map];
890
-
891
- id event = @{
892
- @"id": marker.identifier ?: @"unknown",
893
- @"position": @{
894
- @"x": @(position.x),
895
- @"y": @(position.y),
896
- },
897
- @"coordinate": @{
898
- @"latitude": @(coordinate.latitude),
899
- @"longitude": @(coordinate.longitude),
900
- }
901
- };
902
-
903
- if (map.onMarkerDrag) map.onMarkerDrag(event);
904
- if (marker.onDrag) marker.onDrag(event);
905
-
906
- } else {
907
- // This message is not for me; pass it on to super.
908
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
909
- }
910
- }
911
-
912
- - (void)mapView:(AIRMap *)mapView didUpdateUserLocation:(MKUserLocation *)location
913
- {
914
- id event = @{@"coordinate": @{
915
- @"latitude": @(location.coordinate.latitude),
916
- @"longitude": @(location.coordinate.longitude),
917
- @"altitude": @(location.location.altitude),
918
- @"timestamp": @(location.location.timestamp.timeIntervalSinceReferenceDate * 1000),
919
- @"accuracy": @(location.location.horizontalAccuracy),
920
- @"altitudeAccuracy": @(location.location.verticalAccuracy),
921
- @"speed": @(location.location.speed),
922
- @"heading": @(location.location.course),
923
- }
924
- };
925
-
926
- if (mapView.onUserLocationChange) {
927
- mapView.onUserLocationChange(event);
928
- }
929
-
930
- if (mapView.followUserLocation) {
931
- [mapView setCenterCoordinate:location.coordinate animated:YES];
932
- }
933
-
934
- }
935
-
936
- - (void)mapViewDidChangeVisibleRegion:(AIRMap *)mapView
937
- {
938
- [self _regionChanged:mapView];
939
- }
940
-
941
- - (void)mapView:(AIRMap *)mapView regionDidChangeAnimated:(__unused BOOL)animated
942
- {
943
- CGFloat zoomLevel = [self zoomLevel:mapView];
944
-
945
- // Don't send region did change events until map has
946
- // started rendering, as these won't represent the final location
947
- if(mapView.hasStartedRendering){
948
- [self _regionChanged:mapView];
949
- }
950
-
951
- if (zoomLevel < mapView.minZoomLevel) {
952
- [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.minZoomLevel animated:TRUE mapView:mapView];
953
- }
954
- else if (zoomLevel > mapView.maxZoomLevel) {
955
- [self setCenterCoordinate:[mapView centerCoordinate] zoomLevel:mapView.maxZoomLevel animated:TRUE mapView:mapView];
956
- }
957
-
958
- // Don't send region did change events until map has
959
- // started rendering, as these won't represent the final location
960
- if (mapView.hasStartedRendering) {
961
- [self _emitRegionChangeEvent:mapView continuous:NO];
962
- };
963
-
964
- mapView.pendingCenter = mapView.region.center;
965
- mapView.pendingSpan = mapView.region.span;
966
- }
967
-
968
- - (void)mapViewWillStartRenderingMap:(AIRMap *)mapView
969
- {
970
- if (!mapView.hasStartedRendering) {
971
- mapView.onMapReady(@{});
972
- mapView.hasStartedRendering = YES;
973
- }
974
- [mapView beginLoading];
975
- }
976
-
977
- - (void)mapViewDidFinishRenderingMap:(AIRMap *)mapView fullyRendered:(BOOL)fullyRendered
978
- {
979
- [mapView finishLoading];
980
- }
981
-
982
- #pragma mark Private
983
-
984
- - (void)_regionChanged:(AIRMap *)mapView
985
- {
986
- BOOL needZoom = NO;
987
- CGFloat newLongitudeDelta = 0.0f;
988
- MKCoordinateRegion region = mapView.region;
989
- // On iOS 7, it's possible that we observe invalid locations during initialization of the map.
990
- // Filter those out.
991
- if (!CLLocationCoordinate2DIsValid(region.center)) {
992
- return;
993
- }
994
- // 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.
995
- // 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.
996
- if (mapView.maxDelta > FLT_EPSILON && region.span.longitudeDelta > mapView.maxDelta) {
997
- needZoom = YES;
998
- newLongitudeDelta = mapView.maxDelta * (1 - AIRMapZoomBoundBuffer);
999
- } else if (mapView.minDelta > FLT_EPSILON && region.span.longitudeDelta < mapView.minDelta) {
1000
- needZoom = YES;
1001
- newLongitudeDelta = mapView.minDelta * (1 + AIRMapZoomBoundBuffer);
1002
- }
1003
- if (needZoom) {
1004
- region.span.latitudeDelta = region.span.latitudeDelta / region.span.longitudeDelta * newLongitudeDelta;
1005
- region.span.longitudeDelta = newLongitudeDelta;
1006
- mapView.region = region;
1007
- }
1008
-
1009
- // Continuously observe region changes
1010
- [self _emitRegionChangeEvent:mapView continuous:YES];
1011
- }
1012
-
1013
- - (void)_emitRegionChangeEvent:(AIRMap *)mapView continuous:(BOOL)continuous
1014
- {
1015
- if (!mapView.ignoreRegionChanges && mapView.onChange) {
1016
- MKCoordinateRegion region = mapView.region;
1017
- if (!CLLocationCoordinate2DIsValid(region.center)) {
1018
- return;
1019
- }
1020
-
1021
- #define FLUSH_NAN(value) (isnan(value) ? 0 : value)
1022
- mapView.onChange(@{
1023
- @"continuous": @(continuous),
1024
- @"region": @{
1025
- @"latitude": @(FLUSH_NAN(region.center.latitude)),
1026
- @"longitude": @(FLUSH_NAN(region.center.longitude)),
1027
- @"latitudeDelta": @(FLUSH_NAN(region.span.latitudeDelta)),
1028
- @"longitudeDelta": @(FLUSH_NAN(region.span.longitudeDelta)),
1029
- }
1030
- });
1031
- }
1032
- }
1033
-
1034
- /** Returns the distance of |pt| to |poly| in meters
1035
- *
1036
- *
1037
- */
1038
- - (double)distanceOfPoint:(MKMapPoint)pt toPoly:(AIRMapPolyline *)poly
1039
- {
1040
- double distance = MAXFLOAT;
1041
- for (int n = 0; n < poly.coordinates.count - 1; n++) {
1042
-
1043
- MKMapPoint ptA = MKMapPointForCoordinate(poly.coordinates[n].coordinate);
1044
- MKMapPoint ptB = MKMapPointForCoordinate(poly.coordinates[n + 1].coordinate);
1045
-
1046
- double xDelta = ptB.x - ptA.x;
1047
- double yDelta = ptB.y - ptA.y;
1048
-
1049
- if (xDelta == 0.0 && yDelta == 0.0) {
1050
- continue;
1051
- }
1052
-
1053
- double u = ((pt.x - ptA.x) * xDelta + (pt.y - ptA.y) * yDelta) / (xDelta * xDelta + yDelta * yDelta);
1054
- MKMapPoint ptClosest;
1055
- if (u < 0.0) {
1056
- ptClosest = ptA;
1057
- }
1058
- else if (u > 1.0) {
1059
- ptClosest = ptB;
1060
- }
1061
- else {
1062
- ptClosest = MKMapPointMake(ptA.x + u * xDelta, ptA.y + u * yDelta);
1063
- }
1064
-
1065
- distance = MIN(distance, MKMetersBetweenMapPoints(ptClosest, pt));
1066
- }
1067
-
1068
- return distance;
1069
- }
1070
-
1071
-
1072
- /** Converts |px| to meters at location |pt| */
1073
- - (double)metersFromPixel:(NSUInteger)px atPoint:(CGPoint)pt forMap:(AIRMap *)mapView
1074
- {
1075
- CGPoint ptB = CGPointMake(pt.x + px, pt.y);
1076
-
1077
- CLLocationCoordinate2D coordA = [mapView convertPoint:pt toCoordinateFromView:mapView];
1078
- CLLocationCoordinate2D coordB = [mapView convertPoint:ptB toCoordinateFromView:mapView];
1079
-
1080
- return MKMetersBetweenMapPoints(MKMapPointForCoordinate(coordA), MKMapPointForCoordinate(coordB));
1081
- }
1082
-
1083
- + (double)longitudeToPixelSpaceX:(double)longitude
1084
- {
1085
- return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
1086
- }
1087
-
1088
- + (double)latitudeToPixelSpaceY:(double)latitude
1089
- {
1090
- if (latitude == 90.0) {
1091
- return 0;
1092
- } else if (latitude == -90.0) {
1093
- return MERCATOR_OFFSET * 2;
1094
- } else {
1095
- return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
1096
- }
1097
- }
1098
-
1099
- + (double)pixelSpaceXToLongitude:(double)pixelX
1100
- {
1101
- return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
1102
- }
1103
-
1104
- + (double)pixelSpaceYToLatitude:(double)pixelY
1105
- {
1106
- return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
1107
- }
1108
-
1109
- #pragma mark -
1110
- #pragma mark Helper methods
1111
-
1112
- - (MKCoordinateSpan)coordinateSpanWithMapView:(AIRMap *)mapView
1113
- centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
1114
- andZoomLevel:(double)zoomLevel
1115
- {
1116
- // convert center coordiate to pixel space
1117
- double centerPixelX = [AIRMapManager longitudeToPixelSpaceX:centerCoordinate.longitude];
1118
- double centerPixelY = [AIRMapManager latitudeToPixelSpaceY:centerCoordinate.latitude];
1119
-
1120
- // determine the scale value from the zoom level
1121
- double zoomExponent = AIRMapMaxZoomLevel - zoomLevel;
1122
- double zoomScale = pow(2, zoomExponent);
1123
-
1124
- // scale the map’s size in pixel space
1125
- CGSize mapSizeInPixels = mapView.bounds.size;
1126
- double scaledMapWidth = mapSizeInPixels.width * zoomScale;
1127
- double scaledMapHeight = mapSizeInPixels.height * zoomScale;
1128
-
1129
- // figure out the position of the top-left pixel
1130
- double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
1131
- double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
1132
-
1133
- // find delta between left and right longitudes
1134
- CLLocationDegrees minLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX];
1135
- CLLocationDegrees maxLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
1136
- CLLocationDegrees longitudeDelta = maxLng - minLng;
1137
-
1138
- // find delta between top and bottom latitudes
1139
- CLLocationDegrees minLat = [AIRMapManager pixelSpaceYToLatitude:topLeftPixelY];
1140
- CLLocationDegrees maxLat = [AIRMapManager pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
1141
- CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
1142
-
1143
- // create and return the lat/lng span
1144
- MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
1145
- return span;
1146
- }
1147
-
1148
- #pragma mark -
1149
- #pragma mark Public methods
1150
-
1151
- - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
1152
- zoomLevel:(double)zoomLevel
1153
- animated:(BOOL)animated
1154
- mapView:(AIRMap *)mapView
1155
- {
1156
- // clamp large numbers to 28
1157
- zoomLevel = MIN(zoomLevel, AIRMapMaxZoomLevel);
1158
-
1159
- // use the zoom level to compute the region
1160
- MKCoordinateSpan span = [self coordinateSpanWithMapView:mapView centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
1161
- MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
1162
-
1163
- // set the region like normal
1164
- [mapView setRegion:region animated:animated];
1165
- }
1166
-
1167
- //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).
1168
- -(MKCoordinateRegion)coordinateRegionWithMapView:(AIRMap *)mapView
1169
- centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
1170
- andZoomLevel:(double)zoomLevel
1171
- {
1172
- // clamp lat/long values to appropriate ranges
1173
- centerCoordinate.latitude = MIN(MAX(-90.0, centerCoordinate.latitude), 90.0);
1174
- centerCoordinate.longitude = fmod(centerCoordinate.longitude, 180.0);
1175
-
1176
- // convert center coordiate to pixel space
1177
- double centerPixelX = [AIRMapManager longitudeToPixelSpaceX:centerCoordinate.longitude];
1178
- double centerPixelY = [AIRMapManager latitudeToPixelSpaceY:centerCoordinate.latitude];
1179
-
1180
- // determine the scale value from the zoom level
1181
- double zoomExponent = AIRMapMaxZoomLevel - zoomLevel;
1182
- double zoomScale = pow(2, zoomExponent);
1183
-
1184
- // scale the map’s size in pixel space
1185
- CGSize mapSizeInPixels = mapView.bounds.size;
1186
- double scaledMapWidth = mapSizeInPixels.width * zoomScale;
1187
- double scaledMapHeight = mapSizeInPixels.height * zoomScale;
1188
-
1189
- // figure out the position of the left pixel
1190
- double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
1191
-
1192
- // find delta between left and right longitudes
1193
- CLLocationDegrees minLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX];
1194
- CLLocationDegrees maxLng = [AIRMapManager pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
1195
- CLLocationDegrees longitudeDelta = maxLng - minLng;
1196
-
1197
- // if we’re at a pole then calculate the distance from the pole towards the equator
1198
- // as MKMapView doesn’t like drawing boxes over the poles
1199
- double topPixelY = centerPixelY - (scaledMapHeight / 2);
1200
- double bottomPixelY = centerPixelY + (scaledMapHeight / 2);
1201
- BOOL adjustedCenterPoint = NO;
1202
- if (topPixelY > MERCATOR_OFFSET * 2) {
1203
- topPixelY = centerPixelY - scaledMapHeight;
1204
- bottomPixelY = MERCATOR_OFFSET * 2;
1205
- adjustedCenterPoint = YES;
1206
- }
1207
-
1208
- // find delta between top and bottom latitudes
1209
- CLLocationDegrees minLat = [AIRMapManager pixelSpaceYToLatitude:topPixelY];
1210
- CLLocationDegrees maxLat = [AIRMapManager pixelSpaceYToLatitude:bottomPixelY];
1211
- CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
1212
-
1213
- // create and return the lat/lng span
1214
- MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
1215
- MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
1216
- // once again, MKMapView doesn’t like drawing boxes over the poles
1217
- // so adjust the center coordinate to the center of the resulting region
1218
- if (adjustedCenterPoint) {
1219
- region.center.latitude = [AIRMapManager pixelSpaceYToLatitude:((bottomPixelY + topPixelY) / 2.0)];
1220
- }
1221
-
1222
- return region;
1223
- }
1224
-
1225
- - (double) zoomLevel:(AIRMap *)mapView {
1226
- MKCoordinateRegion region = mapView.region;
1227
-
1228
- double centerPixelX = [AIRMapManager longitudeToPixelSpaceX: region.center.longitude];
1229
- double topLeftPixelX = [AIRMapManager longitudeToPixelSpaceX: region.center.longitude - region.span.longitudeDelta / 2];
1230
-
1231
- double scaledMapWidth = (centerPixelX - topLeftPixelX) * 2;
1232
- CGSize mapSizeInPixels = mapView.bounds.size;
1233
- double zoomScale = scaledMapWidth / mapSizeInPixels.width;
1234
- double zoomExponent = log(zoomScale) / log(2);
1235
- double zoomLevel = AIRMapMaxZoomLevel - zoomExponent;
1236
-
1237
- return zoomLevel;
1238
- }
1239
-
1240
- #pragma mark MKMapViewDelegate - Tracking the User Location
1241
-
1242
- - (void)mapView:(AIRMap *)mapView didFailToLocateUserWithError:(NSError *)error {
1243
- id event = @{@"error": @{ @"message": error.localizedDescription }};
1244
- if (mapView.onUserLocationChange) {
1245
- mapView.onUserLocationChange(event);
1246
- }
1247
- }
1248
-
1249
- - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
1250
- return YES;
1251
- }
1252
-
1253
- @end