react-native-maps 0.29.4 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +8 -1
- package/docs/geojson.md +5 -3
- package/docs/installation.md +1 -1
- package/docs/marker.md +1 -0
- package/docs/tiles.md +35 -0
- package/index.d.ts +25 -10
- package/index.js +1 -3
- package/lib/android/build.gradle +3 -1
- package/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapTileProvider.java +515 -0
- package/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapTileWorker.java +122 -0
- package/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTile.java +124 -55
- package/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapUrlTileManager.java +34 -0
- package/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapView.java +6 -1
- package/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapWMSTile.java +31 -87
- package/lib/android/src/main/java/com/airbnb/android/react/maps/AirMapWMSTileManager.java +22 -2
- package/lib/components/AnimatedRegion.js +64 -101
- package/lib/components/Geojson.js +66 -39
- package/lib/components/MapCircle.js +1 -1
- package/lib/components/MapHeatmap.js +2 -2
- package/lib/components/MapMarker.js +4 -2
- package/lib/components/MapPolygon.js +1 -1
- package/lib/components/MapPolyline.js +1 -1
- package/lib/components/MapUrlTile.js +54 -2
- package/lib/components/MapView.js +4 -4
- package/lib/components/MapWMSTile.js +49 -2
- package/lib/components/decorateMapComponent.js +1 -1
- package/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.h +1 -0
- package/lib/ios/AirGoogleMaps/AIRGoogleMapMarker.m +8 -0
- package/lib/ios/AirGoogleMaps/AIRGoogleMapMarkerManager.m +1 -0
- package/lib/ios/AirMaps/AIRMapManager.m +6 -1
- package/lib/ios/AirMaps/AIRMapMarkerManager.m +1 -0
- package/lib/ios/AirMaps/AIRMapUrlTile.h +22 -4
- package/lib/ios/AirMaps/AIRMapUrlTile.m +124 -34
- package/lib/ios/AirMaps/AIRMapUrlTileCachedOverlay.h +17 -0
- package/lib/ios/AirMaps/AIRMapUrlTileCachedOverlay.m +235 -0
- package/lib/ios/AirMaps/AIRMapUrlTileManager.m +6 -1
- package/lib/ios/AirMaps/AIRMapWMSTile.h +10 -16
- package/lib/ios/AirMaps/AIRMapWMSTile.m +68 -101
- package/lib/ios/AirMaps/AIRMapWMSTileManager.m +6 -1
- package/lib/ios/AirMaps.xcodeproj/project.pbxproj +7 -1
- package/package.json +4 -3
- package/react-native-google-maps.podspec +2 -2
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
@property (nonatomic, assign) NSInteger zIndex;
|
|
37
37
|
@property (nonatomic, assign) double opacity;
|
|
38
38
|
@property (nonatomic, assign) BOOL draggable;
|
|
39
|
+
@property (nonatomic, assign) BOOL tappable;
|
|
39
40
|
@property (nonatomic, assign) BOOL tracksViewChanges;
|
|
40
41
|
@property (nonatomic, assign) BOOL tracksInfoWindowChanges;
|
|
41
42
|
|
|
@@ -391,6 +391,14 @@ CGRect unionRect(CGRect a, CGRect b) {
|
|
|
391
391
|
return _realMarker.draggable;
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
+
- (void)setTappable:(BOOL)tappable {
|
|
395
|
+
_realMarker.tappable = tappable;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
- (BOOL)tappable {
|
|
399
|
+
return _realMarker.tappable;
|
|
400
|
+
}
|
|
401
|
+
|
|
394
402
|
- (void)setFlat:(BOOL)flat {
|
|
395
403
|
_realMarker.flat = flat;
|
|
396
404
|
}
|
|
@@ -44,6 +44,7 @@ RCT_EXPORT_VIEW_PROPERTY(anchor, CGPoint)
|
|
|
44
44
|
RCT_EXPORT_VIEW_PROPERTY(calloutAnchor, CGPoint)
|
|
45
45
|
RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger)
|
|
46
46
|
RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL)
|
|
47
|
+
RCT_EXPORT_VIEW_PROPERTY(tappable, BOOL)
|
|
47
48
|
RCT_EXPORT_VIEW_PROPERTY(flat, BOOL)
|
|
48
49
|
RCT_EXPORT_VIEW_PROPERTY(tracksViewChanges, BOOL)
|
|
49
50
|
RCT_EXPORT_VIEW_PROPERTY(tracksInfoWindowChanges, BOOL)
|
|
@@ -734,7 +734,11 @@ RCT_EXPORT_METHOD(getAddressFromCoordinates:(nonnull NSNumber *)reactTag
|
|
|
734
734
|
if (CGPathContainsPoint(mpr, NULL, mapPointAsCGP, FALSE)) {
|
|
735
735
|
id event = @{
|
|
736
736
|
@"action": @"polygon-press",
|
|
737
|
-
|
|
737
|
+
@"coordinate": @{
|
|
738
|
+
@"latitude": @(tapCoordinate.latitude),
|
|
739
|
+
@"longitude": @(tapCoordinate.longitude),
|
|
740
|
+
},
|
|
741
|
+
};
|
|
738
742
|
polygon.onPress(event);
|
|
739
743
|
}
|
|
740
744
|
|
|
@@ -1018,6 +1022,7 @@ static int kDragCenterContext;
|
|
|
1018
1022
|
@"accuracy": @(location.location.horizontalAccuracy),
|
|
1019
1023
|
@"altitudeAccuracy": @(location.location.verticalAccuracy),
|
|
1020
1024
|
@"speed": @(location.location.speed),
|
|
1025
|
+
@"heading": @(location.location.course),
|
|
1021
1026
|
}
|
|
1022
1027
|
};
|
|
1023
1028
|
|
|
@@ -45,6 +45,7 @@ RCT_EXPORT_VIEW_PROPERTY(pinColor, UIColor)
|
|
|
45
45
|
RCT_EXPORT_VIEW_PROPERTY(draggable, BOOL)
|
|
46
46
|
RCT_EXPORT_VIEW_PROPERTY(zIndex, NSInteger)
|
|
47
47
|
RCT_EXPORT_VIEW_PROPERTY(opacity, double)
|
|
48
|
+
RCT_EXPORT_VIEW_PROPERTY(isPreselected, BOOL)
|
|
48
49
|
|
|
49
50
|
RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
|
|
50
51
|
RCT_EXPORT_VIEW_PROPERTY(onSelect, RCTDirectEventBlock)
|
|
@@ -15,19 +15,37 @@
|
|
|
15
15
|
#import "AIRMapCoordinate.h"
|
|
16
16
|
#import "AIRMap.h"
|
|
17
17
|
#import "RCTConvert+AirMap.h"
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
#import "AIRMapUrlTileCachedOverlay.h"
|
|
19
|
+
|
|
20
|
+
@interface AIRMapUrlTile : MKAnnotationView <MKOverlay> {
|
|
21
|
+
BOOL _urlTemplateSet;
|
|
22
|
+
BOOL _tileSizeSet;
|
|
23
|
+
BOOL _flipYSet;
|
|
24
|
+
BOOL _tileCachePathSet;
|
|
25
|
+
BOOL _tileCacheMaxAgeSet;
|
|
26
|
+
BOOL _maximumNativeZSet;
|
|
27
|
+
BOOL _cachedOverlayCreated;
|
|
28
|
+
BOOL _opacitySet;
|
|
29
|
+
}
|
|
20
30
|
|
|
21
31
|
@property (nonatomic, weak) AIRMap *map;
|
|
22
32
|
|
|
23
|
-
@property (nonatomic, strong)
|
|
33
|
+
@property (nonatomic, strong) AIRMapUrlTileCachedOverlay *tileOverlay;
|
|
24
34
|
@property (nonatomic, strong) MKTileOverlayRenderer *renderer;
|
|
25
35
|
@property (nonatomic, copy) NSString *urlTemplate;
|
|
26
36
|
@property NSInteger maximumZ;
|
|
37
|
+
@property NSInteger maximumNativeZ;
|
|
27
38
|
@property NSInteger minimumZ;
|
|
28
39
|
@property BOOL flipY;
|
|
29
40
|
@property BOOL shouldReplaceMapContent;
|
|
30
|
-
@property
|
|
41
|
+
@property NSInteger tileSize;
|
|
42
|
+
@property (nonatomic, copy) NSString *tileCachePath;
|
|
43
|
+
@property NSInteger tileCacheMaxAge;
|
|
44
|
+
@property BOOL offlineMode;
|
|
45
|
+
@property CGFloat opacity;
|
|
46
|
+
|
|
47
|
+
- (void)updateProperties;
|
|
48
|
+
- (void)update;
|
|
31
49
|
|
|
32
50
|
#pragma mark MKOverlay protocol
|
|
33
51
|
|
|
@@ -8,66 +8,151 @@
|
|
|
8
8
|
|
|
9
9
|
#import "AIRMapUrlTile.h"
|
|
10
10
|
#import <React/UIView+React.h>
|
|
11
|
+
#import "AIRMapUrlTileCachedOverlay.h"
|
|
11
12
|
|
|
12
|
-
@implementation AIRMapUrlTile
|
|
13
|
-
BOOL _urlTemplateSet;
|
|
14
|
-
BOOL _tileSizeSet;
|
|
15
|
-
}
|
|
13
|
+
@implementation AIRMapUrlTile
|
|
16
14
|
|
|
17
15
|
- (void)setShouldReplaceMapContent:(BOOL)shouldReplaceMapContent
|
|
18
16
|
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
_shouldReplaceMapContent = shouldReplaceMapContent;
|
|
18
|
+
if (self.tileOverlay) {
|
|
19
|
+
self.tileOverlay.canReplaceMapContent = _shouldReplaceMapContent;
|
|
20
|
+
}
|
|
21
|
+
[self update];
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
- (void)setMaximumZ:(
|
|
24
|
+
- (void)setMaximumZ:(NSInteger)maximumZ
|
|
27
25
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
_maximumZ = maximumZ;
|
|
27
|
+
if (self.tileOverlay) {
|
|
28
|
+
self.tileOverlay.maximumZ = _maximumZ;
|
|
29
|
+
}
|
|
30
|
+
[self update];
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
- (void)
|
|
33
|
+
- (void)setMaximumNativeZ:(NSInteger)maximumNativeZ
|
|
36
34
|
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
_maximumNativeZ = maximumNativeZ;
|
|
36
|
+
_maximumNativeZSet = YES;
|
|
37
|
+
if (_cachedOverlayCreated) {
|
|
38
|
+
self.tileOverlay.maximumNativeZ = _maximumNativeZ;
|
|
39
|
+
} else {
|
|
40
|
+
[self createTileOverlayAndRendererIfPossible];
|
|
41
|
+
}
|
|
42
|
+
[self update];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
- (void)setMinimumZ:(NSInteger)minimumZ
|
|
46
|
+
{
|
|
47
|
+
_minimumZ = minimumZ;
|
|
48
|
+
if (self.tileOverlay) {
|
|
49
|
+
self.tileOverlay.minimumZ = _minimumZ;
|
|
50
|
+
}
|
|
51
|
+
[self update];
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
- (void)setFlipY:(BOOL)flipY
|
|
45
55
|
{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
self.tileOverlay
|
|
49
|
-
|
|
56
|
+
_flipY = flipY;
|
|
57
|
+
_flipYSet = YES;
|
|
58
|
+
if (self.tileOverlay) {
|
|
59
|
+
self.tileOverlay.geometryFlipped = _flipY;
|
|
60
|
+
}
|
|
61
|
+
[self update];
|
|
50
62
|
}
|
|
51
63
|
|
|
52
|
-
- (void)setUrlTemplate:(NSString *)urlTemplate
|
|
64
|
+
- (void)setUrlTemplate:(NSString *)urlTemplate
|
|
65
|
+
{
|
|
53
66
|
_urlTemplate = urlTemplate;
|
|
54
67
|
_urlTemplateSet = YES;
|
|
55
68
|
[self createTileOverlayAndRendererIfPossible];
|
|
56
69
|
[self update];
|
|
57
70
|
}
|
|
58
71
|
|
|
59
|
-
- (void)setTileSize:(
|
|
72
|
+
- (void)setTileSize:(NSInteger)tileSize
|
|
73
|
+
{
|
|
60
74
|
_tileSize = tileSize;
|
|
61
75
|
_tileSizeSet = YES;
|
|
62
76
|
[self createTileOverlayAndRendererIfPossible];
|
|
63
77
|
[self update];
|
|
64
78
|
}
|
|
65
79
|
|
|
66
|
-
- (void)
|
|
80
|
+
- (void)setTileCachePath:(NSString *)tileCachePath{
|
|
81
|
+
if (!tileCachePath) return;
|
|
82
|
+
_tileCachePath = tileCachePath;
|
|
83
|
+
_tileCachePathSet = YES;
|
|
84
|
+
[self createTileOverlayAndRendererIfPossible];
|
|
85
|
+
[self update];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
- (void)setTileCacheMaxAge:(NSInteger)tileCacheMaxAge{
|
|
89
|
+
_tileCacheMaxAge = tileCacheMaxAge;
|
|
90
|
+
_tileCacheMaxAgeSet = YES;
|
|
91
|
+
if (_cachedOverlayCreated) {
|
|
92
|
+
self.tileOverlay.tileCacheMaxAge = _tileCacheMaxAge;
|
|
93
|
+
} else {
|
|
94
|
+
[self createTileOverlayAndRendererIfPossible];
|
|
95
|
+
}
|
|
96
|
+
[self update];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
- (void)setOfflineMode:(BOOL)offlineMode
|
|
100
|
+
{
|
|
101
|
+
_offlineMode = offlineMode;
|
|
102
|
+
if (_cachedOverlayCreated) {
|
|
103
|
+
self.tileOverlay.offlineMode = _offlineMode;
|
|
104
|
+
}
|
|
105
|
+
if (self.renderer) [self.renderer reloadData];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
- (void)setOpacity:(CGFloat)opacity
|
|
109
|
+
{
|
|
110
|
+
_opacity = opacity;
|
|
111
|
+
_opacitySet = YES;
|
|
112
|
+
if (self.renderer) {
|
|
113
|
+
self.renderer.alpha = opacity;
|
|
114
|
+
} else {
|
|
115
|
+
[self createTileOverlayAndRendererIfPossible];
|
|
116
|
+
}
|
|
117
|
+
[self update];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
- (void)createTileOverlayAndRendererIfPossible
|
|
67
121
|
{
|
|
68
122
|
if (!_urlTemplateSet) return;
|
|
69
|
-
|
|
123
|
+
if (_tileCachePathSet || _maximumNativeZSet) {
|
|
124
|
+
NSLog(@"tileCache dir %@", _tileCachePath);
|
|
125
|
+
self.tileOverlay = [[AIRMapUrlTileCachedOverlay alloc] initWithURLTemplate:self.urlTemplate];
|
|
126
|
+
_cachedOverlayCreated = YES;
|
|
127
|
+
if (_tileCachePathSet) {
|
|
128
|
+
NSURL *urlPath = [NSURL URLWithString:[self.tileCachePath stringByAppendingString:@"/"]];
|
|
129
|
+
if (urlPath.fileURL) {
|
|
130
|
+
self.tileOverlay.tileCachePath = urlPath;
|
|
131
|
+
} else {
|
|
132
|
+
NSURL *filePath = [NSURL fileURLWithPath:self.tileCachePath isDirectory:YES];
|
|
133
|
+
self.tileOverlay.tileCachePath = filePath;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (_tileCacheMaxAgeSet) {
|
|
137
|
+
self.tileOverlay.tileCacheMaxAge = self.tileCacheMaxAge;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
NSLog(@"tileCache normal overlay");
|
|
142
|
+
self.tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:self.urlTemplate];
|
|
143
|
+
_cachedOverlayCreated = NO;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
[self updateProperties];
|
|
70
147
|
|
|
148
|
+
self.renderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:self.tileOverlay];
|
|
149
|
+
if (_opacitySet) {
|
|
150
|
+
self.renderer.alpha = self.opacity;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
- (void)updateProperties
|
|
155
|
+
{
|
|
71
156
|
self.tileOverlay.canReplaceMapContent = self.shouldReplaceMapContent;
|
|
72
157
|
|
|
73
158
|
if(self.minimumZ) {
|
|
@@ -76,16 +161,21 @@
|
|
|
76
161
|
if (self.maximumZ) {
|
|
77
162
|
self.tileOverlay.maximumZ = self.maximumZ;
|
|
78
163
|
}
|
|
79
|
-
if (self.
|
|
164
|
+
if (_cachedOverlayCreated && self.maximumNativeZ) {
|
|
165
|
+
self.tileOverlay.maximumNativeZ = self.maximumNativeZ;
|
|
166
|
+
}
|
|
167
|
+
if (_flipYSet) {
|
|
80
168
|
self.tileOverlay.geometryFlipped = self.flipY;
|
|
81
169
|
}
|
|
82
170
|
if (_tileSizeSet) {
|
|
83
171
|
self.tileOverlay.tileSize = CGSizeMake(self.tileSize, self.tileSize);
|
|
84
172
|
}
|
|
85
|
-
|
|
173
|
+
if (_cachedOverlayCreated && self.offlineMode) {
|
|
174
|
+
self.tileOverlay.offlineMode = self.offlineMode;
|
|
175
|
+
}
|
|
86
176
|
}
|
|
87
177
|
|
|
88
|
-
- (void)
|
|
178
|
+
- (void)update
|
|
89
179
|
{
|
|
90
180
|
if (!_renderer) return;
|
|
91
181
|
|
|
@@ -103,12 +193,12 @@
|
|
|
103
193
|
|
|
104
194
|
#pragma mark MKOverlay implementation
|
|
105
195
|
|
|
106
|
-
- (CLLocationCoordinate2D)
|
|
196
|
+
- (CLLocationCoordinate2D)coordinate
|
|
107
197
|
{
|
|
108
198
|
return self.tileOverlay.coordinate;
|
|
109
199
|
}
|
|
110
200
|
|
|
111
|
-
- (MKMapRect)
|
|
201
|
+
- (MKMapRect)boundingMapRect
|
|
112
202
|
{
|
|
113
203
|
return self.tileOverlay.boundingMapRect;
|
|
114
204
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AIRMapUrlTileCachedOverlay.h
|
|
3
|
+
// Airmaps
|
|
4
|
+
//
|
|
5
|
+
// Created by Markus Suomi on 10/04/2021.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <MapKit/MapKit.h>
|
|
9
|
+
|
|
10
|
+
@interface AIRMapUrlTileCachedOverlay : MKTileOverlay
|
|
11
|
+
|
|
12
|
+
@property NSInteger maximumNativeZ;
|
|
13
|
+
@property (nonatomic, copy) NSURL *tileCachePath;
|
|
14
|
+
@property NSInteger tileCacheMaxAge;
|
|
15
|
+
@property BOOL offlineMode;
|
|
16
|
+
|
|
17
|
+
@end
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AIRMapUrlTileCachedOverlay.m
|
|
3
|
+
// Airmaps
|
|
4
|
+
//
|
|
5
|
+
// Created by Markus Suomi on 10/04/2021.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import "AIRMapUrlTileCachedOverlay.h"
|
|
9
|
+
|
|
10
|
+
@interface AIRMapUrlTileCachedOverlay ()
|
|
11
|
+
|
|
12
|
+
@end
|
|
13
|
+
|
|
14
|
+
@implementation AIRMapUrlTileCachedOverlay {
|
|
15
|
+
CIContext *_ciContext;
|
|
16
|
+
CGColorSpaceRef _colorspace;
|
|
17
|
+
NSURLSession *_urlSession;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
- (void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result
|
|
21
|
+
{
|
|
22
|
+
if (!result) return;
|
|
23
|
+
|
|
24
|
+
NSInteger maximumZ = self.maximumNativeZ ? self.maximumNativeZ : path.z;
|
|
25
|
+
[self scaleIfNeededLowerZoomTile:path maximumZ:maximumZ result:^(NSData *image, NSError *error) {
|
|
26
|
+
if (!image && self.offlineMode && self.tileCachePath) {
|
|
27
|
+
NSInteger zoomLevelToStart = (path.z > maximumZ) ? maximumZ - 1 : path.z - 1;
|
|
28
|
+
NSInteger minimumZoomToSearch = self.minimumZ >= zoomLevelToStart - 3 ? self.minimumZ : zoomLevelToStart - 3;
|
|
29
|
+
[self findLowerZoomTileAndScale:path tryZ:zoomLevelToStart minZ:minimumZoomToSearch result:result];
|
|
30
|
+
} else {
|
|
31
|
+
result(image, error);
|
|
32
|
+
}
|
|
33
|
+
}];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
- (void)scaleIfNeededLowerZoomTile:(MKTileOverlayPath)path maximumZ:(NSInteger)maximumZ result:(void (^)(NSData *, NSError *))result
|
|
37
|
+
{
|
|
38
|
+
NSInteger overZoomLevel = path.z - maximumZ;
|
|
39
|
+
if (overZoomLevel <= 0) {
|
|
40
|
+
[self getTileImage:path result:result];
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
NSInteger zoomFactor = 1 << overZoomLevel;
|
|
45
|
+
|
|
46
|
+
MKTileOverlayPath parentTile;
|
|
47
|
+
parentTile.x = path.x >> overZoomLevel;
|
|
48
|
+
parentTile.y = path.y >> overZoomLevel;
|
|
49
|
+
parentTile.z = path.z - overZoomLevel;
|
|
50
|
+
parentTile.contentScaleFactor = path.contentScaleFactor;
|
|
51
|
+
|
|
52
|
+
NSInteger xOffset = path.x % zoomFactor;
|
|
53
|
+
NSInteger yOffset = path.y % zoomFactor;
|
|
54
|
+
NSInteger subTileSize = self.tileSize.width / zoomFactor;
|
|
55
|
+
|
|
56
|
+
if (!_ciContext) _ciContext = [CIContext context];
|
|
57
|
+
if (!_colorspace) _colorspace = CGColorSpaceCreateDeviceRGB();
|
|
58
|
+
|
|
59
|
+
[self getTileImage:parentTile result:^(NSData *image, NSError *error) {
|
|
60
|
+
if (!image) {
|
|
61
|
+
result(nil, nil);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
CIImage* originalCIImage = [CIImage imageWithData:image];
|
|
66
|
+
|
|
67
|
+
CGRect rect;
|
|
68
|
+
rect.origin.x = xOffset * subTileSize;
|
|
69
|
+
rect.origin.y = self.tileSize.width - (yOffset + 1) * subTileSize;
|
|
70
|
+
rect.size.width = subTileSize;
|
|
71
|
+
rect.size.height = subTileSize;
|
|
72
|
+
CIVector *inputRect = [CIVector vectorWithCGRect:rect];
|
|
73
|
+
CIFilter* cropFilter = [CIFilter filterWithName:@"CICrop"];
|
|
74
|
+
[cropFilter setValue:originalCIImage forKey:@"inputImage"];
|
|
75
|
+
[cropFilter setValue:inputRect forKey:@"inputRectangle"];
|
|
76
|
+
|
|
77
|
+
CGAffineTransform trans = CGAffineTransformMakeScale(zoomFactor, zoomFactor);
|
|
78
|
+
CIImage* scaledCIImage = [cropFilter.outputImage imageByApplyingTransform:trans];
|
|
79
|
+
|
|
80
|
+
NSData *finalImage = [_ciContext PNGRepresentationOfImage:scaledCIImage format:kCIFormatABGR8 colorSpace:_colorspace options:nil];
|
|
81
|
+
result(finalImage, nil);
|
|
82
|
+
}];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
- (void)findLowerZoomTileAndScale:(MKTileOverlayPath)path tryZ:(NSInteger)tryZ minZ:(NSInteger)minZ result:(void (^)(NSData *, NSError *))result
|
|
86
|
+
{
|
|
87
|
+
[self scaleIfNeededLowerZoomTile:path maximumZ:tryZ result:^(NSData *image, NSError *error) {
|
|
88
|
+
if (image) {
|
|
89
|
+
result(image, error);
|
|
90
|
+
} else if (tryZ >= minZ) {
|
|
91
|
+
[self findLowerZoomTileAndScale:path tryZ:tryZ - 1 minZ:minZ result:result];
|
|
92
|
+
} else {
|
|
93
|
+
result(nil, nil);
|
|
94
|
+
}
|
|
95
|
+
}];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (void)getTileImage:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result
|
|
99
|
+
{
|
|
100
|
+
NSData *image;
|
|
101
|
+
NSURL *tileCacheFileDirectory = [NSURL URLWithString:[NSString stringWithFormat:@"%d/%d/", (int)path.z, (int)path.x] relativeToURL:self.tileCachePath];
|
|
102
|
+
NSURL *tileCacheFilePath = [NSURL URLWithString:[NSString stringWithFormat:@"%d", (int)path.y] relativeToURL:tileCacheFileDirectory];
|
|
103
|
+
|
|
104
|
+
if (self.tileCachePath) {
|
|
105
|
+
image = [self readTileImage:path fromFilePath:tileCacheFilePath];
|
|
106
|
+
if (image) {
|
|
107
|
+
result(image, nil);
|
|
108
|
+
if (!self.offlineMode && self.tileCacheMaxAge) {
|
|
109
|
+
[self checkForRefresh:path fromFilePath:tileCacheFilePath];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!image) {
|
|
115
|
+
if (!self.offlineMode) {
|
|
116
|
+
[self fetchTile:path result:^(NSData *image, NSError *error) {
|
|
117
|
+
result(image, error);
|
|
118
|
+
if (image && self.tileCachePath) {
|
|
119
|
+
[self writeTileImage:tileCacheFileDirectory withTileCacheFilePath:tileCacheFilePath withTileData:image];
|
|
120
|
+
}
|
|
121
|
+
}];
|
|
122
|
+
} else {
|
|
123
|
+
result(nil, nil);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
- (NSData *)readTileImage:(MKTileOverlayPath)path fromFilePath:(NSURL *)tileCacheFilePath
|
|
129
|
+
{
|
|
130
|
+
NSError *error;
|
|
131
|
+
|
|
132
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:[tileCacheFilePath path]]) {
|
|
133
|
+
if (!self.tileCacheMaxAge) {
|
|
134
|
+
[[NSFileManager defaultManager] setAttributes:@{NSFileModificationDate:[NSDate date]}
|
|
135
|
+
ofItemAtPath:[tileCacheFilePath path]
|
|
136
|
+
error:&error];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
NSData *tile = [NSData dataWithContentsOfFile:[tileCacheFilePath path]];
|
|
140
|
+
NSLog(@"tileCache HIT for %d_%d_%d", (int)path.z, (int)path.x, (int)path.y);
|
|
141
|
+
NSLog(@"tileCache HIT, with max age set at %d", self.tileCacheMaxAge);
|
|
142
|
+
return tile;
|
|
143
|
+
} else {
|
|
144
|
+
NSLog(@"tileCache MISS for %d_%d_%d", (int)path.z, (int)path.x, (int)path.y);
|
|
145
|
+
return nil;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
- (void)fetchTile:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result
|
|
150
|
+
{
|
|
151
|
+
if (!_urlSession) [self createURLSession];
|
|
152
|
+
|
|
153
|
+
[[_urlSession dataTaskWithURL:[self URLForTilePath:path]
|
|
154
|
+
completionHandler:^(NSData *data,
|
|
155
|
+
NSURLResponse *response,
|
|
156
|
+
NSError *error) {
|
|
157
|
+
result(data, error);
|
|
158
|
+
}] resume];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
- (void)writeTileImage:(NSURL *)tileCacheFileDirectory withTileCacheFilePath:(NSURL *)tileCacheFilePath withTileData:(NSData *)data
|
|
162
|
+
{
|
|
163
|
+
NSError *error;
|
|
164
|
+
|
|
165
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:[tileCacheFileDirectory path]]) {
|
|
166
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:[tileCacheFileDirectory path] withIntermediateDirectories:YES attributes:nil error:&error];
|
|
167
|
+
if (error) {
|
|
168
|
+
NSLog(@"Error: %@", error);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
[[NSFileManager defaultManager] createFileAtPath:[tileCacheFilePath path] contents:data attributes:nil];
|
|
174
|
+
NSLog(@"tileCache SAVED tile %@", [tileCacheFilePath path]);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
- (void)createTileCacheDirectory
|
|
178
|
+
{
|
|
179
|
+
NSError *error;
|
|
180
|
+
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
181
|
+
NSString *documentsDirectory = [paths objectAtIndex:0];
|
|
182
|
+
NSString *tileCacheBaseDirectory = [NSString stringWithFormat:@"%@/tileCache", documentsDirectory];
|
|
183
|
+
self.tileCachePath = [NSURL fileURLWithPath:tileCacheBaseDirectory isDirectory:YES];
|
|
184
|
+
|
|
185
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.tileCachePath path]])
|
|
186
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:[self.tileCachePath path] withIntermediateDirectories:NO attributes:nil error:&error];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
- (void)createURLSession
|
|
190
|
+
{
|
|
191
|
+
if (!_urlSession) {
|
|
192
|
+
_urlSession = [NSURLSession sharedSession];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
- (void)checkForRefresh:(MKTileOverlayPath)path fromFilePath:(NSURL *)tileCacheFilePath
|
|
197
|
+
{
|
|
198
|
+
if ([self doesFileNeedRefresh:path fromFilePath:tileCacheFilePath withMaxAge:self.tileCacheMaxAge]) {
|
|
199
|
+
dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^ {
|
|
200
|
+
// This code runs asynchronously!
|
|
201
|
+
if ([self doesFileNeedRefresh:path fromFilePath:tileCacheFilePath withMaxAge:self.tileCacheMaxAge]) {
|
|
202
|
+
if (!_urlSession) [self createURLSession];
|
|
203
|
+
|
|
204
|
+
[[_urlSession dataTaskWithURL:[self URLForTilePath:path]
|
|
205
|
+
completionHandler:^(NSData *data,
|
|
206
|
+
NSURLResponse *response,
|
|
207
|
+
NSError *error) {
|
|
208
|
+
if (!error) {
|
|
209
|
+
[[NSFileManager defaultManager] createFileAtPath:[tileCacheFilePath path] contents:data attributes:nil];
|
|
210
|
+
NSLog(@"tileCache File refreshed at %@", [tileCacheFilePath path]);
|
|
211
|
+
}
|
|
212
|
+
}] resume];
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
- (BOOL)doesFileNeedRefresh:(MKTileOverlayPath)path fromFilePath:(NSURL *)tileCacheFilePath withMaxAge:(NSInteger)tileCacheMaxAge
|
|
219
|
+
{
|
|
220
|
+
NSError *error;
|
|
221
|
+
NSDictionary<NSFileAttributeKey, id> *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[tileCacheFilePath path] error:&error];
|
|
222
|
+
|
|
223
|
+
if (fileAttributes) {
|
|
224
|
+
NSDate *modificationDate = fileAttributes[@"NSFileModificationDate"];
|
|
225
|
+
if (modificationDate) {
|
|
226
|
+
if (-1 * (int)modificationDate.timeIntervalSinceNow > tileCacheMaxAge) {
|
|
227
|
+
return YES;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return NO;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@end
|
|
@@ -34,9 +34,14 @@ RCT_EXPORT_MODULE()
|
|
|
34
34
|
|
|
35
35
|
RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString)
|
|
36
36
|
RCT_EXPORT_VIEW_PROPERTY(maximumZ, NSInteger)
|
|
37
|
+
RCT_EXPORT_VIEW_PROPERTY(maximumNativeZ, NSInteger)
|
|
37
38
|
RCT_EXPORT_VIEW_PROPERTY(minimumZ, NSInteger)
|
|
38
39
|
RCT_EXPORT_VIEW_PROPERTY(flipY, BOOL)
|
|
39
40
|
RCT_EXPORT_VIEW_PROPERTY(shouldReplaceMapContent, BOOL)
|
|
40
|
-
RCT_EXPORT_VIEW_PROPERTY(tileSize,
|
|
41
|
+
RCT_EXPORT_VIEW_PROPERTY(tileSize, NSInteger)
|
|
42
|
+
RCT_EXPORT_VIEW_PROPERTY(tileCachePath, NSString)
|
|
43
|
+
RCT_EXPORT_VIEW_PROPERTY(tileCacheMaxAge, NSInteger)
|
|
44
|
+
RCT_EXPORT_VIEW_PROPERTY(offlineMode, BOOL)
|
|
45
|
+
RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
|
|
41
46
|
|
|
42
47
|
@end
|
|
@@ -16,26 +16,20 @@
|
|
|
16
16
|
#import "AIRMapCoordinate.h"
|
|
17
17
|
#import "AIRMap.h"
|
|
18
18
|
#import "RCTConvert+AirMap.h"
|
|
19
|
+
#import "AIRMapUrlTile.h"
|
|
20
|
+
#import "AIRMapUrlTileCachedOverlay.h"
|
|
19
21
|
|
|
20
|
-
@interface AIRMapWMSTile :
|
|
22
|
+
@interface AIRMapWMSTile : AIRMapUrlTile <MKOverlay>
|
|
23
|
+
@end
|
|
21
24
|
|
|
22
|
-
@
|
|
25
|
+
@interface AIRMapWMSTileOverlay : MKTileOverlay
|
|
26
|
+
@end
|
|
23
27
|
|
|
24
|
-
@
|
|
25
|
-
@
|
|
26
|
-
@property (nonatomic, copy) NSString *urlTemplate;
|
|
27
|
-
@property NSInteger maximumZ;
|
|
28
|
-
@property NSInteger minimumZ;
|
|
29
|
-
@property NSInteger tileSize;
|
|
30
|
-
@property BOOL shouldReplaceMapContent;
|
|
28
|
+
@interface AIRMapWMSTileCachedOverlay : AIRMapUrlTileCachedOverlay
|
|
29
|
+
@end
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
@interface AIRMapWMSTileHelper : NSObject
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
@property(nonatomic, readonly) MKMapRect boundingMapRect;
|
|
36
|
-
- (BOOL)canReplaceMapContent;
|
|
37
|
-
@end
|
|
33
|
+
+ (NSURL *)URLForTilePath:(MKTileOverlayPath)path withURLTemplate:(NSString *)URLTemplate withTileSize:(NSInteger)tileSize;
|
|
38
34
|
|
|
39
|
-
@interface TileOverlay : MKTileOverlay
|
|
40
|
-
@property (nonatomic) double MapX,MapY,FULL;
|
|
41
35
|
@end
|