@nativescript-community/ui-mapbox 6.2.10 → 6.2.11
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 +12 -0
- package/README.md +199 -99
- package/{mapbox.common.d.ts → common.d.ts} +17 -3
- package/{mapbox.common.js → common.js} +18 -1
- package/filter/filter-parser.d.ts +4 -0
- package/{mapbox.android.d.ts → index.android.d.ts} +5 -14
- package/{mapbox.android.js → index.android.js} +129 -63
- package/index.d.ts +98 -6
- package/{mapbox.ios.d.ts → index.ios.d.ts} +3 -30
- package/{mapbox.ios.js → index.ios.js} +1302 -1270
- package/layers/layer-factory.android.d.ts +14 -1
- package/layers/layer-factory.android.js +33 -2
- package/layers/layer-factory.d.ts +15 -1
- package/layers/layer-factory.ios.d.ts +14 -1
- package/layers/layer-factory.ios.js +42 -2
- package/layers/parser/property-parser.android.d.ts +1 -0
- package/layers/parser/property-parser.android.js +25 -0
- package/layers/parser/property-parser.d.ts +4 -0
- package/layers/parser/property-parser.ios.d.ts +1 -0
- package/layers/parser/property-parser.ios.js +21 -0
- package/package.json +55 -49
- package/platforms/android/include.gradle +3 -0
- package/platforms/android/ui_mapbox.aar +0 -0
- package/platforms/ios/Podfile +2 -2
- package/LICENSE +0 -21
|
@@ -1,10 +1,416 @@
|
|
|
1
|
-
import { Color, File, ImageSource, Trace, knownFolders, path } from '@nativescript/core';
|
|
2
|
-
import { CLog, CLogTypes, MapStyle, MapboxCommon,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { Color, File, Http, ImageSource, Trace, Utils, knownFolders, path } from '@nativescript/core';
|
|
2
|
+
import { CLog, CLogTypes, MapStyle, MapboxCommon, MapboxViewBase, telemetryProperty } from './common';
|
|
3
|
+
import { Layer, LayerFactory } from './layers/layer-factory';
|
|
4
|
+
import { FilterParser } from './filter/filter-parser';
|
|
5
|
+
var MGLMapViewDelegateImpl = /** @class */ (function (_super) {
|
|
6
|
+
__extends(MGLMapViewDelegateImpl, _super);
|
|
7
|
+
function MGLMapViewDelegateImpl() {
|
|
8
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
9
|
+
}
|
|
10
|
+
MGLMapViewDelegateImpl.new = function () {
|
|
11
|
+
return _super.new.call(this);
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* initialize with the mapReady callback
|
|
15
|
+
*/
|
|
16
|
+
MGLMapViewDelegateImpl.prototype.initWithCallback = function (mapLoadedCallback) {
|
|
17
|
+
if (Trace.isEnabled()) {
|
|
18
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::initWithCallback()');
|
|
19
|
+
}
|
|
20
|
+
this.mapLoadedCallback = mapLoadedCallback;
|
|
21
|
+
return this;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* set a reference to the mapboxAPI instance
|
|
25
|
+
*/
|
|
26
|
+
MGLMapViewDelegateImpl.prototype.setMapboxApi = function (api) {
|
|
27
|
+
this.mapboxApi = api;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* set the user location click listener callback
|
|
31
|
+
*/
|
|
32
|
+
MGLMapViewDelegateImpl.prototype.setUserLocationClickListener = function (callback) {
|
|
33
|
+
this.userLocationClickListener = callback;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* set the user location click listener callback
|
|
37
|
+
*/
|
|
38
|
+
MGLMapViewDelegateImpl.prototype.setUserLocationChangedistener = function (callback) {
|
|
39
|
+
this.userLocationChangedListener = callback;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* set user location marker modes
|
|
43
|
+
*/
|
|
44
|
+
MGLMapViewDelegateImpl.prototype.changeUserLocationRenderMode = function (userLocationRenderMode) {
|
|
45
|
+
this.userLocationAnnotationView.changeUserLocationRenderMode(userLocationRenderMode);
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* set the camera changd listener callback
|
|
49
|
+
*/
|
|
50
|
+
MGLMapViewDelegateImpl.prototype.setCameraChangedListener = function (callback) {
|
|
51
|
+
this.cameraChangedListener = callback;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* set the camera idled listener callback
|
|
55
|
+
*/
|
|
56
|
+
MGLMapViewDelegateImpl.prototype.setCameraIdledListener = function (callback) {
|
|
57
|
+
this.cameraIdledListener = callback;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* set style loaded callback.
|
|
61
|
+
*
|
|
62
|
+
* set an optional callback to be invoked when a style set with
|
|
63
|
+
* setMapStyle() is finished loading
|
|
64
|
+
*
|
|
65
|
+
* @param {function} callback function with loaded style as parameter.
|
|
66
|
+
*
|
|
67
|
+
* @see Mapbox:setMapStyle()
|
|
68
|
+
*/
|
|
69
|
+
MGLMapViewDelegateImpl.prototype.setStyleLoadedCallback = function (callback) {
|
|
70
|
+
this.styleLoadedCallback = callback;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* map ready callback
|
|
74
|
+
*/
|
|
75
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingMap = function (mapView) {
|
|
76
|
+
if (Trace.isEnabled()) {
|
|
77
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingMap(): top');
|
|
78
|
+
}
|
|
79
|
+
if (this.mapLoadedCallback !== undefined) {
|
|
80
|
+
this.mapLoadedCallback(mapView);
|
|
81
|
+
// this should be fired only once, but it's also fired when the style changes, so just remove the callback
|
|
82
|
+
this.mapLoadedCallback = undefined;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidFinishRenderingMapFullyRendered = function (mapView, fullyRendered) {
|
|
86
|
+
if (Trace.isEnabled()) {
|
|
87
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishRenderingMapFullyRendered(): rendered is:', fullyRendered);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Callback when the style has been loaded.
|
|
92
|
+
*
|
|
93
|
+
* Based on my testing, it looks like this callback is invoked multiple times.
|
|
94
|
+
*
|
|
95
|
+
* @see Mapbox:setMapStyle()
|
|
96
|
+
*
|
|
97
|
+
* @link https://mapbox.github.io/mapbox-gl-native/macos/0.3.0/Protocols/MGLMapViewDelegate.html#/c:objc(pl)MGLMapViewDelegate(im)mapView:didFinishLoadingStyle:
|
|
98
|
+
*/
|
|
99
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingStyle = function (mapView, style) {
|
|
100
|
+
if (Trace.isEnabled()) {
|
|
101
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingStyle(): callback called.');
|
|
102
|
+
}
|
|
103
|
+
if (this.styleLoadedCallback !== undefined) {
|
|
104
|
+
this.styleLoadedCallback(mapView, style);
|
|
105
|
+
// to avoid multiple calls. This is only invoked from setMapStyle().
|
|
106
|
+
this.styleLoadedCallback = undefined;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* disable the default user location callout
|
|
111
|
+
*
|
|
112
|
+
* This took forever to find. The default iOS click handler for the user location
|
|
113
|
+
* marker is about useless. It just displays "You Are Here". The examples do not
|
|
114
|
+
* show how to disable it.
|
|
115
|
+
*/
|
|
116
|
+
MGLMapViewDelegateImpl.prototype.mapViewAnnotationCanShowCallout = function (mapView, annotation) {
|
|
117
|
+
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidFailLoadingMapWithError = function (mapView, error) {
|
|
125
|
+
if (Trace.isEnabled()) {
|
|
126
|
+
CLog(CLogTypes.info, 'mapViewDidFailLoadingMapWithError: ' + error);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidChangeUserTrackingModeAnimated = function (mapView, mode, animated) {
|
|
130
|
+
if (Trace.isEnabled()) {
|
|
131
|
+
CLog(CLogTypes.info, 'mapViewDidChangeUserTrackingModeAnimated: ' + mode);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* fired when the marker icon is about to be rendered - return null for the default icon
|
|
136
|
+
*/
|
|
137
|
+
MGLMapViewDelegateImpl.prototype.mapViewImageForAnnotation = function (mapView, annotation) {
|
|
138
|
+
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
139
|
+
if (cachedMarker) {
|
|
140
|
+
if (cachedMarker.reuseIdentifier) {
|
|
141
|
+
var reusedImage = mapView.dequeueReusableAnnotationImageWithIdentifier(cachedMarker.reuseIdentifier);
|
|
142
|
+
if (reusedImage) {
|
|
143
|
+
return reusedImage;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// TODO try adding .rotatesToMatchCamera = true;
|
|
147
|
+
// .. for instance in the mapViewDidDeselectAnnotationView / mapViewDidSelectAnnotationView / mapViewViewForAnnotation delegate
|
|
148
|
+
if (cachedMarker.icon) {
|
|
149
|
+
if (cachedMarker.icon.startsWith('res://')) {
|
|
150
|
+
var resourceName = cachedMarker.icon.substring('res://'.length);
|
|
151
|
+
var imageSource = ImageSource.fromResourceSync(resourceName);
|
|
152
|
+
if (imageSource === null) {
|
|
153
|
+
console.log("Unable to locate ".concat(resourceName));
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
cachedMarker.reuseIdentifier = cachedMarker.icon;
|
|
157
|
+
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(imageSource.ios, cachedMarker.reuseIdentifier);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else if (cachedMarker.icon.startsWith('http')) {
|
|
161
|
+
if (cachedMarker.iconDownloaded !== null) {
|
|
162
|
+
cachedMarker.reuseIdentifier = cachedMarker.icon;
|
|
163
|
+
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(cachedMarker.iconDownloaded, cachedMarker.reuseIdentifier);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
if (Trace.isEnabled()) {
|
|
168
|
+
CLog(CLogTypes.info, 'Please use res://resourceName, http(s)://imageUrl or iconPath to use a local path');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (cachedMarker.iconPath) {
|
|
173
|
+
var appPath = knownFolders.currentApp().path;
|
|
174
|
+
var iconFullPath = appPath + '/' + cachedMarker.iconPath.replace('~/', '');
|
|
175
|
+
if (File.exists(iconFullPath)) {
|
|
176
|
+
var image = ImageSource.fromFileSync(iconFullPath).ios;
|
|
177
|
+
// perhaps add resize options for nice retina rendering (although you can now use the 'icon' param instead)
|
|
178
|
+
cachedMarker.reuseIdentifier = cachedMarker.iconPath;
|
|
179
|
+
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(image, cachedMarker.reuseIdentifier);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* fired when one of the callout's accessoryviews is tapped (not currently used)
|
|
187
|
+
*/
|
|
188
|
+
MGLMapViewDelegateImpl.prototype.mapViewAnnotationCalloutAccessoryControlTapped = function (mapView, annotation, control) { };
|
|
189
|
+
/**
|
|
190
|
+
* fired when a marker is tapped
|
|
191
|
+
*/
|
|
192
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidSelectAnnotation = function (mapView, annotation) {
|
|
193
|
+
if (Trace.isEnabled()) {
|
|
194
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidSelectAnntation()');
|
|
195
|
+
}
|
|
196
|
+
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
197
|
+
if (Trace.isEnabled()) {
|
|
198
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidSelectAnnotation(): tapped the user location button');
|
|
199
|
+
}
|
|
200
|
+
if (typeof this.userLocationClickListener != 'undefined') {
|
|
201
|
+
this.userLocationClickListener(annotation);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
mapView.deselectAnnotationAnimated(annotation, false);
|
|
205
|
+
}
|
|
206
|
+
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
207
|
+
if (cachedMarker && cachedMarker.onTap) {
|
|
208
|
+
cachedMarker.onTap(cachedMarker);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* fired when a callout is tapped
|
|
213
|
+
*/
|
|
214
|
+
MGLMapViewDelegateImpl.prototype.mapViewTapOnCalloutForAnnotation = function (mapView, annotation) {
|
|
215
|
+
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
216
|
+
if (cachedMarker && cachedMarker.onCalloutTap) {
|
|
217
|
+
cachedMarker.onCalloutTap(cachedMarker);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
MGLMapViewDelegateImpl.prototype.getTappedMarkerDetails = function (tapped) {
|
|
221
|
+
for (var m in _markers) {
|
|
222
|
+
var cached = _markers[m];
|
|
223
|
+
// don't compare lat/lng types as they're not the same (same for (sub)title, they may be null vs undefined)
|
|
224
|
+
if (
|
|
225
|
+
// eslint-disable-next-line eqeqeq
|
|
226
|
+
cached.lat == tapped.coordinate.latitude &&
|
|
227
|
+
// eslint-disable-next-line eqeqeq
|
|
228
|
+
cached.lng == tapped.coordinate.longitude &&
|
|
229
|
+
// eslint-disable-next-line eqeqeq
|
|
230
|
+
cached.title == tapped.title &&
|
|
231
|
+
// eslint-disable-next-line eqeqeq
|
|
232
|
+
cached.subtitle == tapped.subtitle) {
|
|
233
|
+
return cached;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* override the standard location marker
|
|
239
|
+
*/
|
|
240
|
+
MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
|
|
241
|
+
if (Trace.isEnabled()) {
|
|
242
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewViewForAnnotation() top');
|
|
243
|
+
}
|
|
244
|
+
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
245
|
+
this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init();
|
|
246
|
+
return this.userLocationAnnotationView;
|
|
247
|
+
}
|
|
248
|
+
return null;
|
|
249
|
+
};
|
|
250
|
+
MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
|
|
251
|
+
if (Trace.isEnabled()) {
|
|
252
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionIsChanging()');
|
|
253
|
+
}
|
|
254
|
+
if (this.cameraChangedListener) {
|
|
255
|
+
this.cameraChangedListener(reason);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
|
|
259
|
+
if (Trace.isEnabled()) {
|
|
260
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionDidChangeAnimated()');
|
|
261
|
+
}
|
|
262
|
+
if (this.cameraChangedListener) {
|
|
263
|
+
this.cameraChangedListener(reason, animated);
|
|
264
|
+
}
|
|
265
|
+
if (this.cameraIdledListener) {
|
|
266
|
+
this.cameraIdledListener();
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidUpdateUserLocation = function (mapView, userLocation) {
|
|
270
|
+
if (Trace.isEnabled()) {
|
|
271
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidUpdateUserLocation()');
|
|
272
|
+
}
|
|
273
|
+
if (this.userLocationChangedListener) {
|
|
274
|
+
this.userLocationChangedListener(_getLocation(userLocation));
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
MGLMapViewDelegateImpl.ObjCProtocols = [MGLMapViewDelegate];
|
|
278
|
+
return MGLMapViewDelegateImpl;
|
|
279
|
+
}(NSObject));
|
|
280
|
+
var MapTapHandlerImpl = /** @class */ (function (_super) {
|
|
281
|
+
__extends(MapTapHandlerImpl, _super);
|
|
282
|
+
function MapTapHandlerImpl() {
|
|
283
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
284
|
+
}
|
|
285
|
+
MapTapHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
|
|
286
|
+
var handler = MapTapHandlerImpl.new();
|
|
287
|
+
handler._owner = owner;
|
|
288
|
+
handler._listener = listener;
|
|
289
|
+
handler._mapView = mapView;
|
|
290
|
+
return handler;
|
|
291
|
+
};
|
|
292
|
+
MapTapHandlerImpl.prototype.tap = function (recognizer) {
|
|
293
|
+
var tapPoint = recognizer.locationInView(this._mapView);
|
|
294
|
+
var tapCoordinate = this._mapView.convertPointToCoordinateFromView(tapPoint, this._mapView);
|
|
295
|
+
this._listener({
|
|
296
|
+
lat: tapCoordinate.latitude,
|
|
297
|
+
lng: tapCoordinate.longitude
|
|
298
|
+
});
|
|
299
|
+
};
|
|
300
|
+
MapTapHandlerImpl.ObjCExposedMethods = {
|
|
301
|
+
tap: { returns: interop.types.void, params: [interop.types.id] }
|
|
302
|
+
};
|
|
303
|
+
return MapTapHandlerImpl;
|
|
304
|
+
}(NSObject));
|
|
305
|
+
var MapLongPressHandlerImpl = /** @class */ (function (_super) {
|
|
306
|
+
__extends(MapLongPressHandlerImpl, _super);
|
|
307
|
+
function MapLongPressHandlerImpl() {
|
|
308
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
309
|
+
}
|
|
310
|
+
MapLongPressHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
|
|
311
|
+
var handler = MapLongPressHandlerImpl.new();
|
|
312
|
+
handler._owner = owner;
|
|
313
|
+
handler._listener = listener;
|
|
314
|
+
handler._mapView = mapView;
|
|
315
|
+
return handler;
|
|
316
|
+
};
|
|
317
|
+
MapLongPressHandlerImpl.prototype.longPress = function (recognizer) {
|
|
318
|
+
var longPressPoint = recognizer.locationInView(this._mapView);
|
|
319
|
+
var longPressCoordinate = this._mapView.convertPointToCoordinateFromView(longPressPoint, this._mapView);
|
|
320
|
+
this._listener({
|
|
321
|
+
lat: longPressCoordinate.latitude,
|
|
322
|
+
lng: longPressCoordinate.longitude
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
MapLongPressHandlerImpl.ObjCExposedMethods = {
|
|
326
|
+
longPress: { returns: interop.types.void, params: [interop.types.id] }
|
|
327
|
+
};
|
|
328
|
+
return MapLongPressHandlerImpl;
|
|
329
|
+
}(NSObject));
|
|
330
|
+
var MapPanHandlerImpl = /** @class */ (function (_super) {
|
|
331
|
+
__extends(MapPanHandlerImpl, _super);
|
|
332
|
+
function MapPanHandlerImpl() {
|
|
333
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
334
|
+
}
|
|
335
|
+
MapPanHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, panState, mapView) {
|
|
336
|
+
var handler = MapPanHandlerImpl.new();
|
|
337
|
+
handler._owner = owner;
|
|
338
|
+
handler._listener = new Map([[panState, listener]]);
|
|
339
|
+
handler._mapView = mapView;
|
|
340
|
+
return handler;
|
|
341
|
+
};
|
|
342
|
+
MapPanHandlerImpl.prototype.addListener = function (panState, listener) {
|
|
343
|
+
this._listener.set(panState, listener);
|
|
344
|
+
};
|
|
345
|
+
MapPanHandlerImpl.prototype.pan = function (recognizer) {
|
|
346
|
+
var panCoordinate = this.getCoordinates(recognizer);
|
|
347
|
+
if (Trace.isEnabled()) {
|
|
348
|
+
CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): top with state:', recognizer.state);
|
|
349
|
+
}
|
|
350
|
+
if (recognizer.state === UIGestureRecognizerState.Changed) {
|
|
351
|
+
this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
MapPanHandlerImpl.prototype.panEnd = function (recognizer) {
|
|
355
|
+
var panCoordinate = this.getCoordinates(recognizer);
|
|
356
|
+
if (Trace.isEnabled()) {
|
|
357
|
+
CLog(CLogTypes.info, 'MapPanHandlerImpl::panEnd(): top with state:', recognizer.state);
|
|
358
|
+
}
|
|
359
|
+
if (recognizer.state === UIGestureRecognizerState.Ended) {
|
|
360
|
+
this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
MapPanHandlerImpl.prototype.panBegin = function (recognizer) {
|
|
364
|
+
var panCoordinate = this.getCoordinates(recognizer);
|
|
365
|
+
if (Trace.isEnabled()) {
|
|
366
|
+
CLog(CLogTypes.info, 'MapPanHandlerImpl::panBegin(): top with state:', recognizer.state);
|
|
367
|
+
}
|
|
368
|
+
if (recognizer.state === UIGestureRecognizerState.Began) {
|
|
369
|
+
this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
MapPanHandlerImpl.prototype.getCoordinates = function (recognizer) {
|
|
373
|
+
var panPoint = recognizer.locationInView(this._mapView);
|
|
374
|
+
return this._mapView.convertPointToCoordinateFromView(panPoint, this._mapView);
|
|
375
|
+
};
|
|
376
|
+
MapPanHandlerImpl.prototype.notifyListener = function (panState, latitude, longitude) {
|
|
377
|
+
if (this._listener.has(panState)) {
|
|
378
|
+
this._listener.get(panState)({ lat: latitude, lng: longitude });
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
MapPanHandlerImpl.ObjCExposedMethods = {
|
|
382
|
+
pan: { returns: interop.types.void, params: [interop.types.id] },
|
|
383
|
+
panEnd: { returns: interop.types.void, params: [interop.types.id] },
|
|
384
|
+
panBegin: { returns: interop.types.void, params: [interop.types.id] }
|
|
385
|
+
};
|
|
386
|
+
return MapPanHandlerImpl;
|
|
387
|
+
}(NSObject));
|
|
388
|
+
var MapSwipeHandlerImpl = /** @class */ (function (_super) {
|
|
389
|
+
__extends(MapSwipeHandlerImpl, _super);
|
|
390
|
+
function MapSwipeHandlerImpl() {
|
|
391
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
392
|
+
}
|
|
393
|
+
MapSwipeHandlerImpl.initWithOwnerAndListenerForMap = function (owner, listener, mapView) {
|
|
394
|
+
var handler = MapSwipeHandlerImpl.new();
|
|
395
|
+
handler._owner = owner;
|
|
396
|
+
handler._listener = listener;
|
|
397
|
+
handler._mapView = mapView;
|
|
398
|
+
return handler;
|
|
399
|
+
};
|
|
400
|
+
MapSwipeHandlerImpl.prototype.swipe = function (recognizer) {
|
|
401
|
+
var swipePoint = recognizer.locationInView(this._mapView);
|
|
402
|
+
var swipeCoordinate = this._mapView.convertPointToCoordinateFromView(swipePoint, this._mapView);
|
|
403
|
+
this._listener({
|
|
404
|
+
lat: swipeCoordinate.latitude,
|
|
405
|
+
lng: swipeCoordinate.longitude
|
|
406
|
+
});
|
|
407
|
+
};
|
|
408
|
+
MapSwipeHandlerImpl.ObjCExposedMethods = {
|
|
409
|
+
swipe: { returns: interop.types.void, params: [interop.types.id] }
|
|
410
|
+
};
|
|
411
|
+
return MapSwipeHandlerImpl;
|
|
412
|
+
}(NSObject));
|
|
413
|
+
export * from './common';
|
|
8
414
|
let _markers = [];
|
|
9
415
|
const _markerIconDownloadCache = [];
|
|
10
416
|
const _setMapboxMapOptions = (mapView, settings) => {
|
|
@@ -210,10 +616,32 @@ export class MapboxView extends MapboxViewBase {
|
|
|
210
616
|
this.nativeView.addSubview(this.nativeMapView);
|
|
211
617
|
this.mapbox.setOnMoveBeginListener((data) => {
|
|
212
618
|
if (Trace.isEnabled()) {
|
|
213
|
-
CLog(CLogTypes.info, 'initMap(): onMoveBegin listener');
|
|
619
|
+
CLog(CLogTypes.info, 'initMap(): onMoveBegin listener');
|
|
620
|
+
}
|
|
621
|
+
this.notify({
|
|
622
|
+
eventName: MapboxViewBase.moveBeginEvent,
|
|
623
|
+
object: this,
|
|
624
|
+
map: this,
|
|
625
|
+
ios: this.nativeMapView
|
|
626
|
+
});
|
|
627
|
+
}, this.nativeMapView);
|
|
628
|
+
this.mapbox.setOnMoveEndListener((data) => {
|
|
629
|
+
if (Trace.isEnabled()) {
|
|
630
|
+
CLog(CLogTypes.info, 'initMap(): onMoveEnd listener');
|
|
631
|
+
}
|
|
632
|
+
this.notify({
|
|
633
|
+
eventName: MapboxViewBase.moveEndEvent,
|
|
634
|
+
object: this,
|
|
635
|
+
map: this,
|
|
636
|
+
ios: this.nativeMapView
|
|
637
|
+
});
|
|
638
|
+
}, this.nativeMapView);
|
|
639
|
+
this.mapbox.setOnScrollListener((data) => {
|
|
640
|
+
if (Trace.isEnabled()) {
|
|
641
|
+
CLog(CLogTypes.info, 'initMap(): onScroll listener');
|
|
214
642
|
}
|
|
215
643
|
this.notify({
|
|
216
|
-
eventName: MapboxViewBase.
|
|
644
|
+
eventName: MapboxViewBase.scrollEvent,
|
|
217
645
|
object: this,
|
|
218
646
|
map: this,
|
|
219
647
|
ios: this.nativeMapView
|
|
@@ -233,9 +661,6 @@ export class MapboxView extends MapboxViewBase {
|
|
|
233
661
|
NSUserDefaults.standardUserDefaults.setBoolForKey(false, 'MGLMapboxMetricsEnabled');
|
|
234
662
|
}
|
|
235
663
|
}
|
|
236
|
-
"use strict";
|
|
237
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
238
|
-
exports.CustomUserLocationAnnotationView = void 0;
|
|
239
664
|
var CustomUserLocationAnnotationView = /** @class */ (function (_super) {
|
|
240
665
|
__extends(CustomUserLocationAnnotationView, _super);
|
|
241
666
|
function CustomUserLocationAnnotationView() {
|
|
@@ -444,7 +869,6 @@ var CustomUserLocationAnnotationView = /** @class */ (function (_super) {
|
|
|
444
869
|
};
|
|
445
870
|
return CustomUserLocationAnnotationView;
|
|
446
871
|
}(MGLUserLocationAnnotationView));
|
|
447
|
-
exports.CustomUserLocationAnnotationView = CustomUserLocationAnnotationView;
|
|
448
872
|
export class Mapbox extends MapboxCommon {
|
|
449
873
|
constructor() {
|
|
450
874
|
super(...arguments);
|
|
@@ -806,422 +1230,60 @@ export class Mapbox extends MapboxCommon {
|
|
|
806
1230
|
const coordinate = theMap.centerCoordinate;
|
|
807
1231
|
resolve({
|
|
808
1232
|
lat: coordinate.latitude,
|
|
809
|
-
lng: coordinate.longitude
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
catch (ex) {
|
|
813
|
-
if (Trace.isEnabled()) {
|
|
814
|
-
CLog(CLogTypes.info, 'Error in mapbox.getCenter: ' + ex);
|
|
815
|
-
}
|
|
816
|
-
reject(ex);
|
|
817
|
-
}
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
setZoomLevel(options, nativeMap) {
|
|
821
|
-
return new Promise((resolve, reject) => {
|
|
822
|
-
try {
|
|
823
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
824
|
-
const animated = options.animated === undefined || options.animated;
|
|
825
|
-
const level = options.level;
|
|
826
|
-
if (level >= 0 && level <= 20) {
|
|
827
|
-
theMap.setZoomLevelAnimated(level, animated);
|
|
828
|
-
resolve();
|
|
829
|
-
}
|
|
830
|
-
else {
|
|
831
|
-
reject('invalid ZoomLevel, use any double value from 0 to 20 (like 8.3)');
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
catch (ex) {
|
|
835
|
-
if (Trace.isEnabled()) {
|
|
836
|
-
CLog(CLogTypes.info, 'Error in mapbox.setZoomLevel: ' + ex);
|
|
837
|
-
}
|
|
838
|
-
reject(ex);
|
|
839
|
-
}
|
|
840
|
-
});
|
|
841
|
-
}
|
|
842
|
-
getZoomLevel(nativeMap) {
|
|
843
|
-
return new Promise((resolve, reject) => {
|
|
844
|
-
try {
|
|
845
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
846
|
-
resolve(theMap.zoomLevel);
|
|
847
|
-
}
|
|
848
|
-
catch (ex) {
|
|
849
|
-
if (Trace.isEnabled()) {
|
|
850
|
-
CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
|
|
851
|
-
}
|
|
852
|
-
reject(ex);
|
|
853
|
-
}
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
setTilt(options, nativeMap) {
|
|
857
|
-
return new Promise((resolve, reject) => {
|
|
858
|
-
try {
|
|
859
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
860
|
-
const cam = theMap.camera;
|
|
861
|
-
cam.pitch = options.tilt;
|
|
862
|
-
const durationMs = options.duration ? options.duration : 5000;
|
|
863
|
-
theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
|
|
864
|
-
setTimeout(() => {
|
|
865
|
-
resolve();
|
|
866
|
-
}, durationMs);
|
|
867
|
-
}
|
|
868
|
-
catch (ex) {
|
|
869
|
-
if (Trace.isEnabled()) {
|
|
870
|
-
CLog(CLogTypes.info, 'Error in mapbox.setTilt: ' + ex);
|
|
871
|
-
}
|
|
872
|
-
reject(ex);
|
|
873
|
-
}
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
getTilt(nativeMap) {
|
|
877
|
-
return new Promise((resolve, reject) => {
|
|
878
|
-
try {
|
|
879
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
880
|
-
resolve(theMap.camera.pitch);
|
|
881
|
-
}
|
|
882
|
-
catch (ex) {
|
|
883
|
-
if (Trace.isEnabled()) {
|
|
884
|
-
CLog(CLogTypes.info, 'Error in mapbox.getTilt: ' + ex);
|
|
885
|
-
}
|
|
886
|
-
reject(ex);
|
|
887
|
-
}
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
getUserLocation(nativeMap) {
|
|
891
|
-
return new Promise((resolve, reject) => {
|
|
892
|
-
try {
|
|
893
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
894
|
-
const loc = theMap.userLocation;
|
|
895
|
-
if (loc === null) {
|
|
896
|
-
reject('Location not available');
|
|
897
|
-
}
|
|
898
|
-
else {
|
|
899
|
-
resolve(_getLocation(loc));
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
catch (ex) {
|
|
903
|
-
if (Trace.isEnabled()) {
|
|
904
|
-
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
905
|
-
}
|
|
906
|
-
reject(ex);
|
|
907
|
-
}
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
_stringToCameraMode(mode) {
|
|
911
|
-
switch (mode) {
|
|
912
|
-
case 'NONE':
|
|
913
|
-
return 0;
|
|
914
|
-
case 'NONE_COMPASS':
|
|
915
|
-
if (Trace.isEnabled()) {
|
|
916
|
-
CLog(CLogTypes.info, '_stringToCameraMode(): NONE_COMPASS unsupported on iOS');
|
|
917
|
-
}
|
|
918
|
-
return 0;
|
|
919
|
-
case 'NONE_GPS':
|
|
920
|
-
if (Trace.isEnabled()) {
|
|
921
|
-
CLog(CLogTypes.info, '_stringToCameraMode(): NONE_GPS unsupported on iOS');
|
|
922
|
-
}
|
|
923
|
-
return 0;
|
|
924
|
-
case 'TRACKING':
|
|
925
|
-
return 1;
|
|
926
|
-
case 'TRACK_COMPASS':
|
|
927
|
-
return 2;
|
|
928
|
-
case 'TRACKING_GPS':
|
|
929
|
-
return 1;
|
|
930
|
-
case 'TRACK_GPS_NORTH':
|
|
931
|
-
return 3;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
_stringToRenderMode(mode) {
|
|
935
|
-
let renderMode;
|
|
936
|
-
switch (mode) {
|
|
937
|
-
case 'NORMAL':
|
|
938
|
-
return 'NORMAL';
|
|
939
|
-
case 'COMPASS':
|
|
940
|
-
return 'COMPASS';
|
|
941
|
-
case 'GPS':
|
|
942
|
-
return 'GPS';
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
showUserLocationMarker(options, nativeMap) {
|
|
946
|
-
return new Promise((resolve, reject) => {
|
|
947
|
-
try {
|
|
948
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
949
|
-
theMap.showsUserLocation = true;
|
|
950
|
-
theMap.userTrackingMode = this._stringToCameraMode(options.cameraMode);
|
|
951
|
-
theMap.showsUserHeadingIndicator = true;
|
|
952
|
-
this.userLocationRenderMode = this._stringToRenderMode(options.renderMode);
|
|
953
|
-
const delegate = theMap.delegate;
|
|
954
|
-
delegate.changeUserLocationRenderMode(this.userLocationRenderMode);
|
|
955
|
-
if (typeof options.clickListener != 'undefined') {
|
|
956
|
-
delegate.setUserLocationClickListener(options.clickListener);
|
|
957
|
-
}
|
|
958
|
-
resolve();
|
|
959
|
-
}
|
|
960
|
-
catch (ex) {
|
|
961
|
-
if (Trace.isEnabled()) {
|
|
962
|
-
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
963
|
-
}
|
|
964
|
-
reject(ex);
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
hideUserLocationMarker(nativeMap) {
|
|
969
|
-
return new Promise((resolve, reject) => {
|
|
970
|
-
try {
|
|
971
|
-
resolve();
|
|
972
|
-
}
|
|
973
|
-
catch (ex) {
|
|
974
|
-
if (Trace.isEnabled()) {
|
|
975
|
-
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
976
|
-
}
|
|
977
|
-
reject(ex);
|
|
978
|
-
}
|
|
979
|
-
});
|
|
980
|
-
}
|
|
981
|
-
changeUserLocationMarkerMode(renderModeString, cameraModeString, nativeMap) {
|
|
982
|
-
return new Promise((resolve, reject) => {
|
|
983
|
-
try {
|
|
984
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
985
|
-
if (Trace.isEnabled()) {
|
|
986
|
-
CLog(CLogTypes.info, "Mapbox::changeUserLocationMarkerMode(): changing renderMode to '" + renderModeString + "' cameraMode '" + cameraModeString + "'");
|
|
987
|
-
}
|
|
988
|
-
theMap.userTrackingMode = this._stringToCameraMode(cameraModeString);
|
|
989
|
-
const delegate = theMap.delegate;
|
|
990
|
-
const renderMode = this._stringToRenderMode(renderModeString);
|
|
991
|
-
delegate.changeUserLocationRenderMode(renderMode);
|
|
992
|
-
}
|
|
993
|
-
catch (ex) {
|
|
994
|
-
if (Trace.isEnabled()) {
|
|
995
|
-
CLog(CLogTypes.info, 'Error in mapbox.showUserLocationMarker: ' + ex);
|
|
996
|
-
}
|
|
997
|
-
reject(ex);
|
|
998
|
-
}
|
|
999
|
-
});
|
|
1000
|
-
}
|
|
1001
|
-
forceUserLocationUpdate(location, nativeMap) { }
|
|
1002
|
-
queryRenderedFeatures(options, nativeMap) {
|
|
1003
|
-
return new Promise((resolve, reject) => {
|
|
1004
|
-
try {
|
|
1005
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1006
|
-
if (options.point === undefined) {
|
|
1007
|
-
reject("Please set the 'point' parameter");
|
|
1008
|
-
return;
|
|
1009
|
-
}
|
|
1010
|
-
if (!options) {
|
|
1011
|
-
options = {};
|
|
1012
|
-
}
|
|
1013
|
-
const { x, y } = theMap.convertCoordinateToPointToView({ latitude: options.point.lat, longitude: options.point.lng }, theMap);
|
|
1014
|
-
const queryLayerIds = options.layers ? NSSet.setWithArray(iOSNativeHelper.collections.jsArrayToNSArray(options.layers)) : null;
|
|
1015
|
-
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
|
|
1016
|
-
const features = theMap.visibleFeaturesAtPointInStyleLayersWithIdentifiersPredicate({ x, y }, queryLayerIds, queryFilter);
|
|
1017
|
-
const result = [];
|
|
1018
|
-
for (let i = 0; i < features.count; i++) {
|
|
1019
|
-
const feature = features.objectAtIndex(i);
|
|
1020
|
-
const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
|
|
1021
|
-
result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
|
|
1022
|
-
}
|
|
1023
|
-
resolve(result);
|
|
1024
|
-
}
|
|
1025
|
-
catch (ex) {
|
|
1026
|
-
if (Trace.isEnabled()) {
|
|
1027
|
-
CLog(CLogTypes.info, 'Error in mapbox.queryRenderedFeatures: ' + ex);
|
|
1028
|
-
}
|
|
1029
|
-
reject(ex);
|
|
1030
|
-
}
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
querySourceFeatures(sourceId, options, nativeMap) {
|
|
1034
|
-
return new Promise((resolve, reject) => {
|
|
1035
|
-
try {
|
|
1036
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1037
|
-
if (!options) {
|
|
1038
|
-
options = {};
|
|
1039
|
-
}
|
|
1040
|
-
const source = theMap.style.sourceWithIdentifier(sourceId);
|
|
1041
|
-
if (!source) {
|
|
1042
|
-
throw new Error(`Source with id "${sourceId}" not found.`);
|
|
1043
|
-
}
|
|
1044
|
-
let features;
|
|
1045
|
-
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
|
|
1046
|
-
if (source instanceof MGLShapeSource) {
|
|
1047
|
-
features = source.featuresMatchingPredicate(queryFilter);
|
|
1048
|
-
}
|
|
1049
|
-
else if (source instanceof MGLVectorTileSource) {
|
|
1050
|
-
if (!options.sourceLayer) {
|
|
1051
|
-
throw new Error('The option "sourceLayer" is required for vector sources.');
|
|
1052
|
-
}
|
|
1053
|
-
const sourceLayerIds = options.sourceLayer ? NSSet.setWithArray(iOSNativeHelper.collections.jsArrayToNSArray([options.sourceLayer])) : null;
|
|
1054
|
-
features = source.featuresInSourceLayersWithIdentifiersPredicate(sourceLayerIds, queryFilter);
|
|
1055
|
-
}
|
|
1056
|
-
else {
|
|
1057
|
-
throw new Error('Only sources from type "vector" or "geojson" are supported.');
|
|
1058
|
-
}
|
|
1059
|
-
const result = [];
|
|
1060
|
-
for (let i = 0; i < features.count; i++) {
|
|
1061
|
-
const feature = features.objectAtIndex(i);
|
|
1062
|
-
const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
|
|
1063
|
-
result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
|
|
1064
|
-
}
|
|
1065
|
-
resolve(result);
|
|
1233
|
+
lng: coordinate.longitude
|
|
1234
|
+
});
|
|
1066
1235
|
}
|
|
1067
1236
|
catch (ex) {
|
|
1068
1237
|
if (Trace.isEnabled()) {
|
|
1069
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1238
|
+
CLog(CLogTypes.info, 'Error in mapbox.getCenter: ' + ex);
|
|
1070
1239
|
}
|
|
1071
1240
|
reject(ex);
|
|
1072
1241
|
}
|
|
1073
1242
|
});
|
|
1074
1243
|
}
|
|
1075
|
-
|
|
1244
|
+
setZoomLevel(options, nativeMap) {
|
|
1076
1245
|
return new Promise((resolve, reject) => {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
return;
|
|
1246
|
+
try {
|
|
1247
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1248
|
+
const animated = options.animated === undefined || options.animated;
|
|
1249
|
+
const level = options.level;
|
|
1250
|
+
if (level >= 0 && level <= 20) {
|
|
1251
|
+
theMap.setZoomLevelAnimated(level, animated);
|
|
1252
|
+
resolve();
|
|
1253
|
+
}
|
|
1254
|
+
else {
|
|
1255
|
+
reject('invalid ZoomLevel, use any double value from 0 to 20 (like 8.3)');
|
|
1256
|
+
}
|
|
1089
1257
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
{
|
|
1094
|
-
"id": ${JSON.stringify(polygonID)},
|
|
1095
|
-
"type": "Feature",
|
|
1096
|
-
"properties": {
|
|
1097
|
-
},
|
|
1098
|
-
"geometry": {
|
|
1099
|
-
"type": "Polygon",
|
|
1100
|
-
"coordinates": [${JSON.stringify(coordinateArray)}]
|
|
1101
|
-
}
|
|
1258
|
+
catch (ex) {
|
|
1259
|
+
if (Trace.isEnabled()) {
|
|
1260
|
+
CLog(CLogTypes.info, 'Error in mapbox.setZoomLevel: ' + ex);
|
|
1102
1261
|
}
|
|
1103
|
-
|
|
1104
|
-
}`;
|
|
1105
|
-
const geoDataStr = NSString.stringWithString(geoJSON);
|
|
1106
|
-
const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1107
|
-
const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
|
|
1108
|
-
const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
|
|
1109
|
-
const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
|
|
1110
|
-
const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polygonID, shape, null);
|
|
1111
|
-
theMap.style.addSource(source);
|
|
1112
|
-
if (options.strokeColor || options.strokeWidth || options.strokeOpacity) {
|
|
1113
|
-
const strokeLayer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polygonID + '_stroke', source);
|
|
1114
|
-
strokeLayer.lineColor = NSExpression.expressionForConstantValue(!options.strokeColor ? UIColor.blackColor : options.strokeColor instanceof Color ? options.strokeColor.ios : new Color(options.strokeColor).ios);
|
|
1115
|
-
strokeLayer.lineWidth = NSExpression.expressionForConstantValue(options.strokeWidth || 5);
|
|
1116
|
-
strokeLayer.lineOpacity = NSExpression.expressionForConstantValue(options.strokeOpacity === undefined ? 1 : options.strokeOpacity);
|
|
1117
|
-
theMap.style.addLayer(strokeLayer);
|
|
1262
|
+
reject(ex);
|
|
1118
1263
|
}
|
|
1119
|
-
const layer = MGLFillStyleLayer.alloc().initWithIdentifierSource(polygonID, source);
|
|
1120
|
-
layer.fillColor = NSExpression.expressionForConstantValue(!options.fillColor ? UIColor.blackColor : options.fillColor instanceof Color ? options.fillColor.ios : new Color(options.fillColor).ios);
|
|
1121
|
-
layer.fillOpacity = NSExpression.expressionForConstantValue(options.fillOpacity === undefined ? 1 : options.fillOpacity);
|
|
1122
|
-
theMap.style.addLayer(layer);
|
|
1123
|
-
resolve();
|
|
1124
1264
|
});
|
|
1125
1265
|
}
|
|
1126
|
-
|
|
1266
|
+
getZoomLevel(nativeMap) {
|
|
1127
1267
|
return new Promise((resolve, reject) => {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
reject("Please set the 'points' parameter");
|
|
1132
|
-
return;
|
|
1268
|
+
try {
|
|
1269
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1270
|
+
resolve(theMap.zoomLevel);
|
|
1133
1271
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
reject(
|
|
1139
|
-
return;
|
|
1272
|
+
catch (ex) {
|
|
1273
|
+
if (Trace.isEnabled()) {
|
|
1274
|
+
CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
|
|
1275
|
+
}
|
|
1276
|
+
reject(ex);
|
|
1140
1277
|
}
|
|
1141
|
-
const geoJSON = `{"type": "FeatureCollection", "features": [{"type": "Feature","properties": {},"geometry": {"type": "LineString", "coordinates": ${JSON.stringify(coordinateArray)}}}]}`;
|
|
1142
|
-
const geoDataStr = NSString.stringWithString(geoJSON);
|
|
1143
|
-
const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1144
|
-
const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
|
|
1145
|
-
const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
|
|
1146
|
-
const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
|
|
1147
|
-
const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polylineID, shape, null);
|
|
1148
|
-
theMap.style.addSource(source);
|
|
1149
|
-
const layer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polylineID, source);
|
|
1150
|
-
layer.lineColor = NSExpression.expressionForConstantValue(!options.color ? UIColor.blackColor : options.color instanceof Color ? options.color.ios : new Color(options.color).ios);
|
|
1151
|
-
layer.lineWidth = NSExpression.expressionForConstantValue(options.width || 5);
|
|
1152
|
-
layer.lineOpacity = NSExpression.expressionForConstantValue(options.opacity === undefined ? 1 : options.opacity);
|
|
1153
|
-
theMap.style.addLayer(layer);
|
|
1154
|
-
resolve();
|
|
1155
|
-
});
|
|
1156
|
-
}
|
|
1157
|
-
removePolyById(theMap, id) {
|
|
1158
|
-
let layer = theMap.style.layerWithIdentifier(id);
|
|
1159
|
-
if (layer !== null) {
|
|
1160
|
-
theMap.style.removeLayer(layer);
|
|
1161
|
-
}
|
|
1162
|
-
layer = theMap.style.layerWithIdentifier(id + '_stroke');
|
|
1163
|
-
if (layer !== null) {
|
|
1164
|
-
theMap.style.removeLayer(layer);
|
|
1165
|
-
}
|
|
1166
|
-
const source = theMap.style.sourceWithIdentifier(id);
|
|
1167
|
-
if (source !== null) {
|
|
1168
|
-
theMap.style.removeSource(source);
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
removePolys(polyType, ids, nativeMap) {
|
|
1172
|
-
return new Promise((resolve) => {
|
|
1173
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1174
|
-
ids.forEach((id) => this.removePolyById(theMap, polyType + id));
|
|
1175
|
-
resolve();
|
|
1176
1278
|
});
|
|
1177
1279
|
}
|
|
1178
|
-
|
|
1179
|
-
return this.removePolys('polygon_', ids, nativeMap);
|
|
1180
|
-
}
|
|
1181
|
-
removePolylines(ids, nativeMap) {
|
|
1182
|
-
return this.removePolys('polyline_', ids, nativeMap);
|
|
1183
|
-
}
|
|
1184
|
-
animateCamera(options, nativeMap) {
|
|
1280
|
+
setTilt(options, nativeMap) {
|
|
1185
1281
|
return new Promise((resolve, reject) => {
|
|
1186
1282
|
try {
|
|
1187
1283
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
const insets = {
|
|
1192
|
-
top: padding,
|
|
1193
|
-
left: padding,
|
|
1194
|
-
bottom: padding,
|
|
1195
|
-
right: padding
|
|
1196
|
-
};
|
|
1197
|
-
const bounds = {
|
|
1198
|
-
sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
|
|
1199
|
-
ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
|
|
1200
|
-
};
|
|
1201
|
-
cam = theMap.cameraThatFitsCoordinateBoundsEdgePadding(bounds, insets);
|
|
1202
|
-
}
|
|
1203
|
-
else {
|
|
1204
|
-
const target = options.target;
|
|
1205
|
-
if (target === undefined) {
|
|
1206
|
-
reject("Please set the 'target' parameter");
|
|
1207
|
-
return;
|
|
1208
|
-
}
|
|
1209
|
-
cam = theMap.camera;
|
|
1210
|
-
cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
|
|
1211
|
-
}
|
|
1212
|
-
if (options.altitude) {
|
|
1213
|
-
cam.altitude = options.altitude;
|
|
1214
|
-
}
|
|
1215
|
-
if (options.bearing) {
|
|
1216
|
-
cam.heading = options.bearing;
|
|
1217
|
-
}
|
|
1218
|
-
if (options.tilt) {
|
|
1219
|
-
cam.pitch = options.tilt;
|
|
1220
|
-
}
|
|
1221
|
-
if (options.zoomLevel && options.target) {
|
|
1222
|
-
cam.altitude = MGLAltitudeForZoomLevel(options.zoomLevel, cam.pitch, options.target.lat, theMap.frame.size);
|
|
1223
|
-
}
|
|
1224
|
-
const durationMs = options.duration ? options.duration : 10000;
|
|
1284
|
+
const cam = theMap.camera;
|
|
1285
|
+
cam.pitch = options.tilt;
|
|
1286
|
+
const durationMs = options.duration ? options.duration : 5000;
|
|
1225
1287
|
theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
|
|
1226
1288
|
setTimeout(() => {
|
|
1227
1289
|
resolve();
|
|
@@ -1229,336 +1291,375 @@ export class Mapbox extends MapboxCommon {
|
|
|
1229
1291
|
}
|
|
1230
1292
|
catch (ex) {
|
|
1231
1293
|
if (Trace.isEnabled()) {
|
|
1232
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1294
|
+
CLog(CLogTypes.info, 'Error in mapbox.setTilt: ' + ex);
|
|
1233
1295
|
}
|
|
1234
1296
|
reject(ex);
|
|
1235
1297
|
}
|
|
1236
1298
|
});
|
|
1237
1299
|
}
|
|
1238
|
-
|
|
1300
|
+
getTilt(nativeMap) {
|
|
1239
1301
|
return new Promise((resolve, reject) => {
|
|
1240
1302
|
try {
|
|
1241
1303
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1242
|
-
|
|
1243
|
-
reject('No map has been loaded');
|
|
1244
|
-
return;
|
|
1245
|
-
}
|
|
1246
|
-
theMap['mapTapHandler'] = MapTapHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
|
|
1247
|
-
const tapGestureRecognizer = UITapGestureRecognizer.alloc().initWithTargetAction(theMap['mapTapHandler'], 'tap');
|
|
1248
|
-
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1249
|
-
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1250
|
-
if (recognizer instanceof UITapGestureRecognizer) {
|
|
1251
|
-
tapGestureRecognizer.requireGestureRecognizerToFail(recognizer);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
theMap.addGestureRecognizer(tapGestureRecognizer);
|
|
1255
|
-
resolve();
|
|
1304
|
+
resolve(theMap.camera.pitch);
|
|
1256
1305
|
}
|
|
1257
1306
|
catch (ex) {
|
|
1258
1307
|
if (Trace.isEnabled()) {
|
|
1259
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1308
|
+
CLog(CLogTypes.info, 'Error in mapbox.getTilt: ' + ex);
|
|
1260
1309
|
}
|
|
1261
1310
|
reject(ex);
|
|
1262
1311
|
}
|
|
1263
1312
|
});
|
|
1264
1313
|
}
|
|
1265
|
-
|
|
1314
|
+
getUserLocation(nativeMap) {
|
|
1266
1315
|
return new Promise((resolve, reject) => {
|
|
1267
1316
|
try {
|
|
1268
1317
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1318
|
+
const loc = theMap.userLocation;
|
|
1319
|
+
if (loc === null) {
|
|
1320
|
+
reject('Location not available');
|
|
1272
1321
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1276
|
-
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1277
|
-
if (recognizer instanceof UILongPressGestureRecognizer) {
|
|
1278
|
-
longPressGestureRecognizer.requireGestureRecognizerToFail(recognizer);
|
|
1279
|
-
}
|
|
1322
|
+
else {
|
|
1323
|
+
resolve(_getLocation(loc));
|
|
1280
1324
|
}
|
|
1281
|
-
theMap.addGestureRecognizer(longPressGestureRecognizer);
|
|
1282
|
-
resolve();
|
|
1283
1325
|
}
|
|
1284
1326
|
catch (ex) {
|
|
1285
1327
|
if (Trace.isEnabled()) {
|
|
1286
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1328
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1287
1329
|
}
|
|
1288
1330
|
reject(ex);
|
|
1289
1331
|
}
|
|
1290
1332
|
});
|
|
1291
1333
|
}
|
|
1292
|
-
|
|
1334
|
+
_stringToCameraMode(mode) {
|
|
1335
|
+
switch (mode) {
|
|
1336
|
+
case 'NONE':
|
|
1337
|
+
return 0;
|
|
1338
|
+
case 'NONE_COMPASS':
|
|
1339
|
+
if (Trace.isEnabled()) {
|
|
1340
|
+
CLog(CLogTypes.info, '_stringToCameraMode(): NONE_COMPASS unsupported on iOS');
|
|
1341
|
+
}
|
|
1342
|
+
return 0;
|
|
1343
|
+
case 'NONE_GPS':
|
|
1344
|
+
if (Trace.isEnabled()) {
|
|
1345
|
+
CLog(CLogTypes.info, '_stringToCameraMode(): NONE_GPS unsupported on iOS');
|
|
1346
|
+
}
|
|
1347
|
+
return 0;
|
|
1348
|
+
case 'TRACKING':
|
|
1349
|
+
return 1;
|
|
1350
|
+
case 'TRACKING_COMPASS':
|
|
1351
|
+
return 2;
|
|
1352
|
+
case 'TRACKING_GPS':
|
|
1353
|
+
return 1;
|
|
1354
|
+
case 'TRACKING_GPS_NORTH':
|
|
1355
|
+
return 3;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
_stringToRenderMode(mode) {
|
|
1359
|
+
let renderMode;
|
|
1360
|
+
switch (mode) {
|
|
1361
|
+
case 'NORMAL':
|
|
1362
|
+
return 'NORMAL';
|
|
1363
|
+
case 'COMPASS':
|
|
1364
|
+
return 'COMPASS';
|
|
1365
|
+
case 'GPS':
|
|
1366
|
+
return 'GPS';
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
showUserLocationMarker(options, nativeMap) {
|
|
1293
1370
|
return new Promise((resolve, reject) => {
|
|
1294
1371
|
try {
|
|
1295
1372
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
|
|
1305
|
-
break;
|
|
1306
|
-
}
|
|
1373
|
+
theMap.showsUserLocation = true;
|
|
1374
|
+
theMap.userTrackingMode = this._stringToCameraMode(options.cameraMode);
|
|
1375
|
+
theMap.showsUserHeadingIndicator = true;
|
|
1376
|
+
this.userLocationRenderMode = this._stringToRenderMode(options.renderMode);
|
|
1377
|
+
const delegate = theMap.delegate;
|
|
1378
|
+
delegate.changeUserLocationRenderMode(this.userLocationRenderMode);
|
|
1379
|
+
if (typeof options.clickListener != 'undefined') {
|
|
1380
|
+
delegate.setUserLocationClickListener(options.clickListener);
|
|
1307
1381
|
}
|
|
1308
1382
|
resolve();
|
|
1309
1383
|
}
|
|
1310
1384
|
catch (ex) {
|
|
1311
1385
|
if (Trace.isEnabled()) {
|
|
1312
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1386
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1313
1387
|
}
|
|
1314
1388
|
reject(ex);
|
|
1315
1389
|
}
|
|
1316
1390
|
});
|
|
1317
1391
|
}
|
|
1318
|
-
|
|
1392
|
+
hideUserLocationMarker(nativeMap) {
|
|
1319
1393
|
return new Promise((resolve, reject) => {
|
|
1320
1394
|
try {
|
|
1321
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1322
|
-
if (!theMap) {
|
|
1323
|
-
reject('No map has been loaded');
|
|
1324
|
-
return;
|
|
1325
|
-
}
|
|
1326
|
-
theMap['mapOnMoveBeginHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
|
|
1327
|
-
theMap['mapOnMoveBeginHandler'].setOnMoveBegin();
|
|
1328
|
-
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1329
|
-
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1330
|
-
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1331
|
-
recognizer.addTargetAction(theMap['mapOnMoveBeginHandler'], 'pan');
|
|
1332
|
-
break;
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
1395
|
resolve();
|
|
1336
1396
|
}
|
|
1337
1397
|
catch (ex) {
|
|
1338
1398
|
if (Trace.isEnabled()) {
|
|
1339
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1399
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1340
1400
|
}
|
|
1341
1401
|
reject(ex);
|
|
1342
1402
|
}
|
|
1343
1403
|
});
|
|
1344
1404
|
}
|
|
1345
|
-
|
|
1346
|
-
return Promise.reject("'setOnFlingListener' is not supported on iOS");
|
|
1347
|
-
}
|
|
1348
|
-
async setOnCameraMoveListener(listener, nativeMap) {
|
|
1349
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1350
|
-
if (theMap) {
|
|
1351
|
-
theMap.delegate.setCameraChangedListener(listener);
|
|
1352
|
-
}
|
|
1353
|
-
else {
|
|
1354
|
-
return Promise.reject('No map has been loaded');
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
setOnCameraMoveCancelListener(listener, nativeMap) {
|
|
1358
|
-
return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
|
|
1359
|
-
}
|
|
1360
|
-
async setOnCameraIdleListener(listener, nativeMap) {
|
|
1361
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1362
|
-
if (theMap) {
|
|
1363
|
-
theMap.delegate.setCameraIdledListener(listener);
|
|
1364
|
-
}
|
|
1365
|
-
else {
|
|
1366
|
-
return Promise.reject('No map has been loaded');
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
getViewport(nativeMap) {
|
|
1405
|
+
changeUserLocationMarkerMode(renderModeString, cameraModeString, nativeMap) {
|
|
1370
1406
|
return new Promise((resolve, reject) => {
|
|
1371
1407
|
try {
|
|
1372
1408
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1373
|
-
if (
|
|
1374
|
-
|
|
1375
|
-
return;
|
|
1409
|
+
if (Trace.isEnabled()) {
|
|
1410
|
+
CLog(CLogTypes.info, "Mapbox::changeUserLocationMarkerMode(): changing renderMode to '" + renderModeString + "' cameraMode '" + cameraModeString + "'");
|
|
1376
1411
|
}
|
|
1377
|
-
|
|
1378
|
-
const
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
south: visibleBounds.sw.latitude,
|
|
1382
|
-
west: visibleBounds.sw.longitude
|
|
1383
|
-
};
|
|
1384
|
-
resolve({
|
|
1385
|
-
bounds,
|
|
1386
|
-
zoomLevel: theMap.zoomLevel
|
|
1387
|
-
});
|
|
1412
|
+
theMap.userTrackingMode = this._stringToCameraMode(cameraModeString);
|
|
1413
|
+
const delegate = theMap.delegate;
|
|
1414
|
+
const renderMode = this._stringToRenderMode(renderModeString);
|
|
1415
|
+
delegate.changeUserLocationRenderMode(renderMode);
|
|
1388
1416
|
}
|
|
1389
1417
|
catch (ex) {
|
|
1390
1418
|
if (Trace.isEnabled()) {
|
|
1391
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1419
|
+
CLog(CLogTypes.info, 'Error in mapbox.showUserLocationMarker: ' + ex);
|
|
1392
1420
|
}
|
|
1393
1421
|
reject(ex);
|
|
1394
1422
|
}
|
|
1395
1423
|
});
|
|
1396
1424
|
}
|
|
1397
|
-
|
|
1425
|
+
forceUserLocationUpdate(location, nativeMap) { }
|
|
1426
|
+
queryRenderedFeatures(options, nativeMap) {
|
|
1398
1427
|
return new Promise((resolve, reject) => {
|
|
1399
1428
|
try {
|
|
1400
1429
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1401
|
-
if (
|
|
1402
|
-
reject(
|
|
1430
|
+
if (options.point === undefined) {
|
|
1431
|
+
reject("Please set the 'point' parameter");
|
|
1403
1432
|
return;
|
|
1404
1433
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
};
|
|
1409
|
-
const
|
|
1410
|
-
const
|
|
1411
|
-
theMap.
|
|
1412
|
-
|
|
1434
|
+
if (!options) {
|
|
1435
|
+
options = {};
|
|
1436
|
+
}
|
|
1437
|
+
const { x, y } = theMap.convertCoordinateToPointToView({ latitude: options.point.lat, longitude: options.point.lng }, theMap);
|
|
1438
|
+
const queryLayerIds = options.layers ? NSSet.setWithArray(Utils.ios.collections.jsArrayToNSArray(options.layers)) : null;
|
|
1439
|
+
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
|
|
1440
|
+
const features = theMap.visibleFeaturesAtPointInStyleLayersWithIdentifiersPredicate({ x, y }, queryLayerIds, queryFilter);
|
|
1441
|
+
const result = [];
|
|
1442
|
+
for (let i = 0; i < features.count; i++) {
|
|
1443
|
+
const feature = features.objectAtIndex(i);
|
|
1444
|
+
const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
|
|
1445
|
+
result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
|
|
1446
|
+
}
|
|
1447
|
+
resolve(result);
|
|
1413
1448
|
}
|
|
1414
1449
|
catch (ex) {
|
|
1415
1450
|
if (Trace.isEnabled()) {
|
|
1416
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1451
|
+
CLog(CLogTypes.info, 'Error in mapbox.queryRenderedFeatures: ' + ex);
|
|
1417
1452
|
}
|
|
1418
1453
|
reject(ex);
|
|
1419
1454
|
}
|
|
1420
1455
|
});
|
|
1421
1456
|
}
|
|
1422
|
-
|
|
1457
|
+
querySourceFeatures(sourceId, options, nativeMap) {
|
|
1423
1458
|
return new Promise((resolve, reject) => {
|
|
1424
1459
|
try {
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
const bounds = {
|
|
1429
|
-
sw: swCoordinate,
|
|
1430
|
-
ne: neCoordinate
|
|
1431
|
-
};
|
|
1432
|
-
const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
|
|
1433
|
-
if (options.accessToken) {
|
|
1434
|
-
MGLAccountManager.accessToken = options.accessToken;
|
|
1460
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1461
|
+
if (!options) {
|
|
1462
|
+
options = {};
|
|
1435
1463
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
const offlinePackProgress = offlinePack.progress;
|
|
1440
|
-
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1441
|
-
const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
|
|
1442
|
-
options.onProgress({
|
|
1443
|
-
name: userInfo.objectForKey('name'),
|
|
1444
|
-
completed: offlinePackProgress.countOfResourcesCompleted,
|
|
1445
|
-
expected: offlinePackProgress.countOfResourcesExpected,
|
|
1446
|
-
percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
|
|
1447
|
-
complete
|
|
1448
|
-
});
|
|
1449
|
-
if (complete) {
|
|
1450
|
-
resolve();
|
|
1451
|
-
}
|
|
1452
|
-
});
|
|
1464
|
+
const source = theMap.style.sourceWithIdentifier(sourceId);
|
|
1465
|
+
if (!source) {
|
|
1466
|
+
throw new Error(`Source with id "${sourceId}" not found.`);
|
|
1453
1467
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
});
|
|
1463
|
-
_addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
|
|
1464
|
-
const offlinePack = notification.object;
|
|
1465
|
-
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1466
|
-
const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
|
|
1467
|
-
console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
|
|
1468
|
-
});
|
|
1469
|
-
const userInfo = { name: options.name };
|
|
1470
|
-
const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
|
|
1471
|
-
MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
|
|
1472
|
-
if (error) {
|
|
1473
|
-
reject(error.localizedFailureReason);
|
|
1474
|
-
}
|
|
1475
|
-
else {
|
|
1476
|
-
pack.resume();
|
|
1468
|
+
let features;
|
|
1469
|
+
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
|
|
1470
|
+
if (source instanceof MGLShapeSource) {
|
|
1471
|
+
features = source.featuresMatchingPredicate(queryFilter);
|
|
1472
|
+
}
|
|
1473
|
+
else if (source instanceof MGLVectorTileSource) {
|
|
1474
|
+
if (!options.sourceLayer) {
|
|
1475
|
+
throw new Error('The option "sourceLayer" is required for vector sources.');
|
|
1477
1476
|
}
|
|
1478
|
-
|
|
1477
|
+
const sourceLayerIds = options.sourceLayer ? NSSet.setWithArray(Utils.ios.collections.jsArrayToNSArray([options.sourceLayer])) : null;
|
|
1478
|
+
features = source.featuresInSourceLayersWithIdentifiersPredicate(sourceLayerIds, queryFilter);
|
|
1479
|
+
}
|
|
1480
|
+
else {
|
|
1481
|
+
throw new Error('Only sources from type "vector" or "geojson" are supported.');
|
|
1482
|
+
}
|
|
1483
|
+
const result = [];
|
|
1484
|
+
for (let i = 0; i < features.count; i++) {
|
|
1485
|
+
const feature = features.objectAtIndex(i);
|
|
1486
|
+
const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
|
|
1487
|
+
result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
|
|
1488
|
+
}
|
|
1489
|
+
resolve(result);
|
|
1479
1490
|
}
|
|
1480
1491
|
catch (ex) {
|
|
1481
1492
|
if (Trace.isEnabled()) {
|
|
1482
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1493
|
+
CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
|
|
1483
1494
|
}
|
|
1484
1495
|
reject(ex);
|
|
1485
1496
|
}
|
|
1486
1497
|
});
|
|
1487
1498
|
}
|
|
1488
|
-
|
|
1499
|
+
addPolygon(options, nativeMap) {
|
|
1489
1500
|
return new Promise((resolve, reject) => {
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1501
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1502
|
+
const points = options.points;
|
|
1503
|
+
if (points === undefined) {
|
|
1504
|
+
reject("Please set the 'points' parameter");
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
const coordinateArray = [];
|
|
1508
|
+
points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
|
|
1509
|
+
const polygonID = `polygon_${options.id || new Date().getTime()}`;
|
|
1510
|
+
if (theMap.style.sourceWithIdentifier(polygonID)) {
|
|
1511
|
+
reject("Remove the polygon with this id first with 'removePolygons': " + polygonID);
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
const geoJSON = `{
|
|
1515
|
+
"type": "FeatureCollection",
|
|
1516
|
+
"features": [
|
|
1517
|
+
{
|
|
1518
|
+
"id": ${JSON.stringify(polygonID)},
|
|
1519
|
+
"type": "Feature",
|
|
1520
|
+
"properties": {
|
|
1521
|
+
},
|
|
1522
|
+
"geometry": {
|
|
1523
|
+
"type": "Polygon",
|
|
1524
|
+
"coordinates": [${JSON.stringify(coordinateArray)}]
|
|
1525
|
+
}
|
|
1513
1526
|
}
|
|
1514
|
-
|
|
1527
|
+
]
|
|
1528
|
+
}`;
|
|
1529
|
+
const geoDataStr = NSString.stringWithString(geoJSON);
|
|
1530
|
+
const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1531
|
+
const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
|
|
1532
|
+
const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
|
|
1533
|
+
const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
|
|
1534
|
+
const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polygonID, shape, null);
|
|
1535
|
+
theMap.style.addSource(source);
|
|
1536
|
+
if (options.strokeColor || options.strokeWidth || options.strokeOpacity) {
|
|
1537
|
+
const strokeLayer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polygonID + '_stroke', source);
|
|
1538
|
+
strokeLayer.lineColor = NSExpression.expressionForConstantValue(!options.strokeColor ? UIColor.blackColor : options.strokeColor instanceof Color ? options.strokeColor.ios : new Color(options.strokeColor).ios);
|
|
1539
|
+
strokeLayer.lineWidth = NSExpression.expressionForConstantValue(options.strokeWidth || 5);
|
|
1540
|
+
strokeLayer.lineOpacity = NSExpression.expressionForConstantValue(options.strokeOpacity === undefined ? 1 : options.strokeOpacity);
|
|
1541
|
+
theMap.style.addLayer(strokeLayer);
|
|
1542
|
+
}
|
|
1543
|
+
const layer = MGLFillStyleLayer.alloc().initWithIdentifierSource(polygonID, source);
|
|
1544
|
+
layer.fillColor = NSExpression.expressionForConstantValue(!options.fillColor ? UIColor.blackColor : options.fillColor instanceof Color ? options.fillColor.ios : new Color(options.fillColor).ios);
|
|
1545
|
+
layer.fillOpacity = NSExpression.expressionForConstantValue(options.fillOpacity === undefined ? 1 : options.fillOpacity);
|
|
1546
|
+
theMap.style.addLayer(layer);
|
|
1547
|
+
resolve();
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
addPolyline(options, nativeMap) {
|
|
1551
|
+
return new Promise((resolve, reject) => {
|
|
1552
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1553
|
+
const points = options.points;
|
|
1554
|
+
if (points === undefined) {
|
|
1555
|
+
reject("Please set the 'points' parameter");
|
|
1556
|
+
return;
|
|
1515
1557
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
reject(
|
|
1558
|
+
const coordinateArray = [];
|
|
1559
|
+
points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
|
|
1560
|
+
const polylineID = 'polyline_' + (options.id || new Date().getTime());
|
|
1561
|
+
if (theMap.style.sourceWithIdentifier(polylineID)) {
|
|
1562
|
+
reject("Remove the polyline with this id first with 'removePolylines': " + polylineID);
|
|
1563
|
+
return;
|
|
1521
1564
|
}
|
|
1565
|
+
const geoJSON = `{"type": "FeatureCollection", "features": [{"type": "Feature","properties": {},"geometry": {"type": "LineString", "coordinates": ${JSON.stringify(coordinateArray)}}}]}`;
|
|
1566
|
+
const geoDataStr = NSString.stringWithString(geoJSON);
|
|
1567
|
+
const geoData = geoDataStr.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1568
|
+
const geoDataBase64Enc = geoData.base64EncodedStringWithOptions(0);
|
|
1569
|
+
const geo = NSData.alloc().initWithBase64EncodedStringOptions(geoDataBase64Enc, null);
|
|
1570
|
+
const shape = MGLShape.shapeWithDataEncodingError(geo, NSUTF8StringEncoding);
|
|
1571
|
+
const source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(polylineID, shape, null);
|
|
1572
|
+
theMap.style.addSource(source);
|
|
1573
|
+
const layer = MGLLineStyleLayer.alloc().initWithIdentifierSource(polylineID, source);
|
|
1574
|
+
layer.lineColor = NSExpression.expressionForConstantValue(!options.color ? UIColor.blackColor : options.color instanceof Color ? options.color.ios : new Color(options.color).ios);
|
|
1575
|
+
layer.lineWidth = NSExpression.expressionForConstantValue(options.width || 5);
|
|
1576
|
+
layer.lineOpacity = NSExpression.expressionForConstantValue(options.opacity === undefined ? 1 : options.opacity);
|
|
1577
|
+
theMap.style.addLayer(layer);
|
|
1578
|
+
resolve();
|
|
1522
1579
|
});
|
|
1523
1580
|
}
|
|
1524
|
-
|
|
1581
|
+
removePolyById(theMap, id) {
|
|
1582
|
+
let layer = theMap.style.layerWithIdentifier(id);
|
|
1583
|
+
if (layer !== null) {
|
|
1584
|
+
theMap.style.removeLayer(layer);
|
|
1585
|
+
}
|
|
1586
|
+
layer = theMap.style.layerWithIdentifier(id + '_stroke');
|
|
1587
|
+
if (layer !== null) {
|
|
1588
|
+
theMap.style.removeLayer(layer);
|
|
1589
|
+
}
|
|
1590
|
+
const source = theMap.style.sourceWithIdentifier(id);
|
|
1591
|
+
if (source !== null) {
|
|
1592
|
+
theMap.style.removeSource(source);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
removePolys(polyType, ids, nativeMap) {
|
|
1596
|
+
return new Promise((resolve) => {
|
|
1597
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1598
|
+
ids.forEach((id) => this.removePolyById(theMap, polyType + id));
|
|
1599
|
+
resolve();
|
|
1600
|
+
});
|
|
1601
|
+
}
|
|
1602
|
+
removePolygons(ids, nativeMap) {
|
|
1603
|
+
return this.removePolys('polygon_', ids, nativeMap);
|
|
1604
|
+
}
|
|
1605
|
+
removePolylines(ids, nativeMap) {
|
|
1606
|
+
return this.removePolys('polyline_', ids, nativeMap);
|
|
1607
|
+
}
|
|
1608
|
+
animateCamera(options, nativeMap) {
|
|
1525
1609
|
return new Promise((resolve, reject) => {
|
|
1526
1610
|
try {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1611
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1612
|
+
let cam;
|
|
1613
|
+
if (options.bounds) {
|
|
1614
|
+
const padding = options.padding || 0;
|
|
1615
|
+
const insets = {
|
|
1616
|
+
top: padding,
|
|
1617
|
+
left: padding,
|
|
1618
|
+
bottom: padding,
|
|
1619
|
+
right: padding
|
|
1620
|
+
};
|
|
1621
|
+
const bounds = {
|
|
1622
|
+
sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
|
|
1623
|
+
ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
|
|
1624
|
+
};
|
|
1625
|
+
cam = theMap.cameraThatFitsCoordinateBoundsEdgePadding(bounds, insets);
|
|
1530
1626
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
const name = userInfo.objectForKey('name');
|
|
1537
|
-
if (name === options.name) {
|
|
1538
|
-
found = true;
|
|
1539
|
-
MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
|
|
1540
|
-
if (error) {
|
|
1541
|
-
reject(error.localizedFailureReason);
|
|
1542
|
-
}
|
|
1543
|
-
else {
|
|
1544
|
-
resolve();
|
|
1545
|
-
}
|
|
1546
|
-
});
|
|
1627
|
+
else {
|
|
1628
|
+
const target = options.target;
|
|
1629
|
+
if (target === undefined) {
|
|
1630
|
+
reject("Please set the 'target' parameter");
|
|
1631
|
+
return;
|
|
1547
1632
|
}
|
|
1633
|
+
cam = theMap.camera;
|
|
1634
|
+
cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
|
|
1548
1635
|
}
|
|
1549
|
-
if (
|
|
1550
|
-
|
|
1636
|
+
if (options.altitude) {
|
|
1637
|
+
cam.altitude = options.altitude;
|
|
1638
|
+
}
|
|
1639
|
+
if (options.bearing) {
|
|
1640
|
+
cam.heading = options.bearing;
|
|
1641
|
+
}
|
|
1642
|
+
if (options.tilt) {
|
|
1643
|
+
cam.pitch = options.tilt;
|
|
1551
1644
|
}
|
|
1645
|
+
if (options.zoomLevel && options.target) {
|
|
1646
|
+
cam.altitude = MGLAltitudeForZoomLevel(options.zoomLevel, cam.pitch, options.target.lat, theMap.frame.size);
|
|
1647
|
+
}
|
|
1648
|
+
const durationMs = options.duration ? options.duration : 10000;
|
|
1649
|
+
theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
|
|
1650
|
+
setTimeout(() => {
|
|
1651
|
+
resolve();
|
|
1652
|
+
}, durationMs);
|
|
1552
1653
|
}
|
|
1553
1654
|
catch (ex) {
|
|
1554
1655
|
if (Trace.isEnabled()) {
|
|
1555
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1656
|
+
CLog(CLogTypes.info, 'Error in mapbox.animateCamera: ' + ex);
|
|
1556
1657
|
}
|
|
1557
1658
|
reject(ex);
|
|
1558
1659
|
}
|
|
1559
1660
|
});
|
|
1560
1661
|
}
|
|
1561
|
-
|
|
1662
|
+
setOnMapClickListener(listener, nativeMap) {
|
|
1562
1663
|
return new Promise((resolve, reject) => {
|
|
1563
1664
|
try {
|
|
1564
1665
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1566,17 +1667,20 @@ export class Mapbox extends MapboxCommon {
|
|
|
1566
1667
|
reject('No map has been loaded');
|
|
1567
1668
|
return;
|
|
1568
1669
|
}
|
|
1670
|
+
theMap['mapTapHandler'] = MapTapHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
|
|
1671
|
+
const tapGestureRecognizer = UITapGestureRecognizer.alloc().initWithTargetAction(theMap['mapTapHandler'], 'tap');
|
|
1672
|
+
theMap.addGestureRecognizer(tapGestureRecognizer);
|
|
1569
1673
|
resolve();
|
|
1570
1674
|
}
|
|
1571
1675
|
catch (ex) {
|
|
1572
1676
|
if (Trace.isEnabled()) {
|
|
1573
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1677
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
|
|
1574
1678
|
}
|
|
1575
1679
|
reject(ex);
|
|
1576
1680
|
}
|
|
1577
1681
|
});
|
|
1578
1682
|
}
|
|
1579
|
-
|
|
1683
|
+
setOnMapLongClickListener(listener, nativeMap) {
|
|
1580
1684
|
return new Promise((resolve, reject) => {
|
|
1581
1685
|
try {
|
|
1582
1686
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1584,159 +1688,88 @@ export class Mapbox extends MapboxCommon {
|
|
|
1584
1688
|
reject('No map has been loaded');
|
|
1585
1689
|
return;
|
|
1586
1690
|
}
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
1595
|
-
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1596
|
-
const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
1597
|
-
source.shape = geoJsonShape;
|
|
1598
|
-
break;
|
|
1599
|
-
default:
|
|
1600
|
-
reject('Invalid source type: ' + options['type']);
|
|
1601
|
-
return;
|
|
1691
|
+
theMap['mapLongPressHandler'] = MapLongPressHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
|
|
1692
|
+
const longPressGestureRecognizer = UILongPressGestureRecognizer.alloc().initWithTargetAction(theMap['mapLongPressHandler'], 'longPress');
|
|
1693
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1694
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1695
|
+
if (recognizer instanceof UILongPressGestureRecognizer) {
|
|
1696
|
+
longPressGestureRecognizer.requireGestureRecognizerToFail(recognizer);
|
|
1697
|
+
}
|
|
1602
1698
|
}
|
|
1699
|
+
theMap.addGestureRecognizer(longPressGestureRecognizer);
|
|
1700
|
+
resolve();
|
|
1603
1701
|
}
|
|
1604
1702
|
catch (ex) {
|
|
1605
1703
|
if (Trace.isEnabled()) {
|
|
1606
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1704
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
|
|
1607
1705
|
}
|
|
1608
1706
|
reject(ex);
|
|
1609
1707
|
}
|
|
1610
1708
|
});
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
return new Promise((resolve, reject) => {
|
|
1614
|
-
try {
|
|
1615
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
else {
|
|
1631
|
-
const sourceOptions = {};
|
|
1632
|
-
if (options.minzoom !== undefined) {
|
|
1633
|
-
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
1634
|
-
}
|
|
1635
|
-
if (options.maxzoom !== undefined) {
|
|
1636
|
-
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
1637
|
-
}
|
|
1638
|
-
if (options.scheme) {
|
|
1639
|
-
switch (options.scheme) {
|
|
1640
|
-
case 'xyz':
|
|
1641
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
1642
|
-
break;
|
|
1643
|
-
case 'tms':
|
|
1644
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
1645
|
-
break;
|
|
1646
|
-
default:
|
|
1647
|
-
throw new Error('Unknown raster tile scheme.');
|
|
1648
|
-
}
|
|
1649
|
-
}
|
|
1650
|
-
if (options.bounds) {
|
|
1651
|
-
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
1652
|
-
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
1653
|
-
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
1654
|
-
});
|
|
1655
|
-
}
|
|
1656
|
-
source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
1657
|
-
}
|
|
1658
|
-
break;
|
|
1659
|
-
}
|
|
1660
|
-
case 'geojson':
|
|
1661
|
-
if (theMap.style.sourceWithIdentifier(id)) {
|
|
1662
|
-
reject("Remove the layer with this id first with 'removeLayer': " + id);
|
|
1663
|
-
return;
|
|
1664
|
-
}
|
|
1665
|
-
let geoJsonShape;
|
|
1666
|
-
if (options.data) {
|
|
1667
|
-
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
1668
|
-
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1669
|
-
geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
1670
|
-
}
|
|
1671
|
-
const sourceOptions = {};
|
|
1672
|
-
if (options.minzoom !== undefined) {
|
|
1673
|
-
sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
1674
|
-
}
|
|
1675
|
-
if (options.maxzoom !== undefined) {
|
|
1676
|
-
sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
1677
|
-
}
|
|
1678
|
-
if (options.cluster) {
|
|
1679
|
-
sourceOptions[MGLShapeSourceOptionClustered] = true;
|
|
1680
|
-
sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
|
|
1681
|
-
sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
|
|
1682
|
-
}
|
|
1683
|
-
source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
|
|
1684
|
-
break;
|
|
1685
|
-
case 'raster': {
|
|
1686
|
-
const sourceOptions = {
|
|
1687
|
-
[MGLTileSourceOptionTileSize]: options.tileSize || 256
|
|
1688
|
-
};
|
|
1689
|
-
if (options.minzoom !== undefined) {
|
|
1690
|
-
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
1691
|
-
}
|
|
1692
|
-
if (options.maxzoom !== undefined) {
|
|
1693
|
-
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
1694
|
-
}
|
|
1695
|
-
if (options.scheme) {
|
|
1696
|
-
switch (options.scheme || 'xyz') {
|
|
1697
|
-
case 'xyz':
|
|
1698
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
1699
|
-
break;
|
|
1700
|
-
case 'tms':
|
|
1701
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
1702
|
-
break;
|
|
1703
|
-
default:
|
|
1704
|
-
throw new Error('Unknown raster tile scheme.');
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
if (options.bounds) {
|
|
1708
|
-
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
1709
|
-
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
1710
|
-
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
1711
|
-
});
|
|
1712
|
-
}
|
|
1713
|
-
source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
1709
|
+
}
|
|
1710
|
+
setOnScrollListener(listener, nativeMap) {
|
|
1711
|
+
return new Promise((resolve, reject) => {
|
|
1712
|
+
try {
|
|
1713
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1714
|
+
if (!theMap) {
|
|
1715
|
+
reject('No map has been loaded');
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
if (theMap['mapPanHandler'] === undefined) {
|
|
1719
|
+
theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 2, theMap);
|
|
1720
|
+
}
|
|
1721
|
+
else {
|
|
1722
|
+
theMap['mapPanHandler'].addListener(2, listener);
|
|
1723
|
+
}
|
|
1724
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1725
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1726
|
+
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1727
|
+
recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
|
|
1714
1728
|
break;
|
|
1715
1729
|
}
|
|
1716
|
-
default:
|
|
1717
|
-
reject('Invalid source type: ' + options['type']);
|
|
1718
|
-
return;
|
|
1719
1730
|
}
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1731
|
+
resolve();
|
|
1732
|
+
}
|
|
1733
|
+
catch (ex) {
|
|
1734
|
+
if (Trace.isEnabled()) {
|
|
1735
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnScrollListener: ' + ex);
|
|
1736
|
+
}
|
|
1737
|
+
reject(ex);
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
setOnMoveBeginListener(listener, nativeMap) {
|
|
1742
|
+
return new Promise((resolve, reject) => {
|
|
1743
|
+
try {
|
|
1744
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1745
|
+
if (!theMap) {
|
|
1746
|
+
reject('No map has been loaded');
|
|
1726
1747
|
return;
|
|
1727
1748
|
}
|
|
1728
|
-
theMap
|
|
1749
|
+
if (theMap['mapPanHandler'] === undefined) {
|
|
1750
|
+
theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 1, theMap);
|
|
1751
|
+
}
|
|
1752
|
+
else {
|
|
1753
|
+
theMap['mapPanHandler'].addListener(1, listener);
|
|
1754
|
+
}
|
|
1755
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1756
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1757
|
+
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1758
|
+
recognizer.addTargetAction(theMap['mapPanHandler'], 'panBegin');
|
|
1759
|
+
break;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1729
1762
|
resolve();
|
|
1730
1763
|
}
|
|
1731
1764
|
catch (ex) {
|
|
1732
1765
|
if (Trace.isEnabled()) {
|
|
1733
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1766
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMoveBeginListener: ' + ex);
|
|
1734
1767
|
}
|
|
1735
1768
|
reject(ex);
|
|
1736
1769
|
}
|
|
1737
1770
|
});
|
|
1738
1771
|
}
|
|
1739
|
-
|
|
1772
|
+
setOnMoveEndListener(listener, nativeMap) {
|
|
1740
1773
|
return new Promise((resolve, reject) => {
|
|
1741
1774
|
try {
|
|
1742
1775
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1744,86 +1777,82 @@ export class Mapbox extends MapboxCommon {
|
|
|
1744
1777
|
reject('No map has been loaded');
|
|
1745
1778
|
return;
|
|
1746
1779
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1780
|
+
if (theMap['mapPanHandler'] === undefined) {
|
|
1781
|
+
theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 3, theMap);
|
|
1782
|
+
}
|
|
1783
|
+
else {
|
|
1784
|
+
theMap['mapPanHandler'].addListener(3, listener);
|
|
1785
|
+
}
|
|
1786
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1787
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1788
|
+
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1789
|
+
recognizer.addTargetAction(theMap['mapPanHandler'], 'panEnd');
|
|
1790
|
+
break;
|
|
1791
|
+
}
|
|
1751
1792
|
}
|
|
1752
|
-
theMap.style.removeSource(source);
|
|
1753
1793
|
resolve();
|
|
1754
1794
|
}
|
|
1755
1795
|
catch (ex) {
|
|
1756
1796
|
if (Trace.isEnabled()) {
|
|
1757
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1797
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMoveEndListener: ' + ex);
|
|
1758
1798
|
}
|
|
1759
1799
|
reject(ex);
|
|
1760
1800
|
}
|
|
1761
1801
|
});
|
|
1762
1802
|
}
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1803
|
+
setOnFlingListener(listener, nativeMap) {
|
|
1804
|
+
return Promise.reject("'setOnFlingListener' is not supported on iOS");
|
|
1805
|
+
}
|
|
1806
|
+
async setOnCameraMoveListener(listener, nativeMap) {
|
|
1807
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1808
|
+
if (theMap) {
|
|
1809
|
+
theMap.delegate.setCameraChangedListener(listener);
|
|
1769
1810
|
}
|
|
1770
1811
|
else {
|
|
1771
|
-
|
|
1772
|
-
}
|
|
1773
|
-
const layer = await LayerFactory.createLayer(style, source);
|
|
1774
|
-
if (belowLayerId) {
|
|
1775
|
-
const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
|
|
1776
|
-
if (belowlayer) {
|
|
1777
|
-
theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
|
|
1778
|
-
return;
|
|
1779
|
-
}
|
|
1812
|
+
return Promise.reject('No map has been loaded');
|
|
1780
1813
|
}
|
|
1781
|
-
theMap.style.addLayer(layer.getNativeInstance());
|
|
1782
1814
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
if (Trace.isEnabled()) {
|
|
1786
|
-
CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
|
|
1787
|
-
}
|
|
1788
|
-
const layer = theMap.style.layerWithIdentifier(id);
|
|
1789
|
-
if (Trace.isEnabled()) {
|
|
1790
|
-
CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
|
|
1791
|
-
}
|
|
1792
|
-
if (!layer) {
|
|
1793
|
-
throw new Error("Layer '" + id + "' not found when attempting to remove it.");
|
|
1794
|
-
}
|
|
1795
|
-
theMap.style.removeLayer(layer);
|
|
1796
|
-
if (Trace.isEnabled()) {
|
|
1797
|
-
CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
|
|
1798
|
-
}
|
|
1815
|
+
setOnCameraMoveCancelListener(listener, nativeMap) {
|
|
1816
|
+
return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
|
|
1799
1817
|
}
|
|
1800
|
-
async
|
|
1801
|
-
const theMap =
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
if (!lineSource) {
|
|
1805
|
-
throw new Error(`no source found with id: ${sId}`);
|
|
1806
|
-
}
|
|
1807
|
-
try {
|
|
1808
|
-
const lineFeatures = lineSource.featuresMatchingPredicate(FilterParser.parseJson(['==', '$type', 'LineString']));
|
|
1809
|
-
if (lineFeatures.count === 0) {
|
|
1810
|
-
throw new Error('no line string feature found');
|
|
1811
|
-
}
|
|
1812
|
-
const lineFeature = lineFeatures.objectAtIndex(0);
|
|
1813
|
-
const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
|
|
1814
|
-
const newCoordPointer = new interop.Reference(newCoord);
|
|
1815
|
-
lineFeature.appendCoordinatesCount(newCoordPointer, 1);
|
|
1816
|
-
lineSource.shape = lineFeature;
|
|
1818
|
+
async setOnCameraIdleListener(listener, nativeMap) {
|
|
1819
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1820
|
+
if (theMap) {
|
|
1821
|
+
theMap.delegate.setCameraIdledListener(listener);
|
|
1817
1822
|
}
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
throw error;
|
|
1823
|
+
else {
|
|
1824
|
+
return Promise.reject('No map has been loaded');
|
|
1821
1825
|
}
|
|
1822
1826
|
}
|
|
1823
|
-
|
|
1824
|
-
|
|
1827
|
+
getViewport(nativeMap) {
|
|
1828
|
+
return new Promise((resolve, reject) => {
|
|
1829
|
+
try {
|
|
1830
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1831
|
+
if (!theMap) {
|
|
1832
|
+
reject('No map has been loaded');
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
const visibleBounds = theMap.visibleCoordinateBounds;
|
|
1836
|
+
const bounds = {
|
|
1837
|
+
north: visibleBounds.ne.latitude,
|
|
1838
|
+
east: visibleBounds.ne.longitude,
|
|
1839
|
+
south: visibleBounds.sw.latitude,
|
|
1840
|
+
west: visibleBounds.sw.longitude
|
|
1841
|
+
};
|
|
1842
|
+
resolve({
|
|
1843
|
+
bounds,
|
|
1844
|
+
zoomLevel: theMap.zoomLevel
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1847
|
+
catch (ex) {
|
|
1848
|
+
if (Trace.isEnabled()) {
|
|
1849
|
+
CLog(CLogTypes.info, 'Error in mapbox.getViewport: ' + ex);
|
|
1850
|
+
}
|
|
1851
|
+
reject(ex);
|
|
1852
|
+
}
|
|
1853
|
+
});
|
|
1825
1854
|
}
|
|
1826
|
-
|
|
1855
|
+
setViewport(options, nativeMap) {
|
|
1827
1856
|
return new Promise((resolve, reject) => {
|
|
1828
1857
|
try {
|
|
1829
1858
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1831,41 +1860,163 @@ export class Mapbox extends MapboxCommon {
|
|
|
1831
1860
|
reject('No map has been loaded');
|
|
1832
1861
|
return;
|
|
1833
1862
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1863
|
+
const bounds = {
|
|
1864
|
+
sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
|
|
1865
|
+
ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
|
|
1866
|
+
};
|
|
1867
|
+
const animated = options.animated === undefined || options.animated;
|
|
1868
|
+
const padding = options.padding !== undefined ? { top: options.padding, left: options.padding, bottom: options.padding, right: options.padding } : { top: 25, left: 25, bottom: 25, right: 25 };
|
|
1869
|
+
theMap.setVisibleCoordinateBoundsEdgePaddingAnimated(bounds, padding, animated);
|
|
1870
|
+
resolve();
|
|
1871
|
+
}
|
|
1872
|
+
catch (ex) {
|
|
1873
|
+
if (Trace.isEnabled()) {
|
|
1874
|
+
CLog(CLogTypes.info, 'Error in mapbox.setViewport: ' + ex);
|
|
1875
|
+
}
|
|
1876
|
+
reject(ex);
|
|
1877
|
+
}
|
|
1878
|
+
});
|
|
1879
|
+
}
|
|
1880
|
+
downloadOfflineRegion(options) {
|
|
1881
|
+
return new Promise((resolve, reject) => {
|
|
1882
|
+
try {
|
|
1883
|
+
const styleURL = _getMapStyle(options.style);
|
|
1884
|
+
const swCoordinate = CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west);
|
|
1885
|
+
const neCoordinate = CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east);
|
|
1886
|
+
const bounds = {
|
|
1887
|
+
sw: swCoordinate,
|
|
1888
|
+
ne: neCoordinate
|
|
1889
|
+
};
|
|
1890
|
+
const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
|
|
1891
|
+
if (options.accessToken) {
|
|
1892
|
+
MGLAccountManager.accessToken = options.accessToken;
|
|
1893
|
+
}
|
|
1894
|
+
if (options.onProgress) {
|
|
1895
|
+
_addObserver(MGLOfflinePackProgressChangedNotification, (notification) => {
|
|
1896
|
+
const offlinePack = notification.object;
|
|
1897
|
+
const offlinePackProgress = offlinePack.progress;
|
|
1898
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1899
|
+
const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
|
|
1900
|
+
options.onProgress({
|
|
1901
|
+
name: userInfo.objectForKey('name'),
|
|
1902
|
+
completed: offlinePackProgress.countOfResourcesCompleted,
|
|
1903
|
+
expected: offlinePackProgress.countOfResourcesExpected,
|
|
1904
|
+
percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
|
|
1905
|
+
complete
|
|
1906
|
+
});
|
|
1907
|
+
if (complete) {
|
|
1908
|
+
resolve();
|
|
1909
|
+
}
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
_addObserver(MGLOfflinePackErrorNotification, (notification) => {
|
|
1913
|
+
const offlinePack = notification.object;
|
|
1914
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1915
|
+
const error = notification.userInfo[MGLOfflinePackUserInfoKeyError];
|
|
1916
|
+
reject({
|
|
1917
|
+
name: userInfo.objectForKey('name'),
|
|
1918
|
+
error: 'Download error. ' + error
|
|
1919
|
+
});
|
|
1920
|
+
});
|
|
1921
|
+
_addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
|
|
1922
|
+
const offlinePack = notification.object;
|
|
1923
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1924
|
+
const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
|
|
1925
|
+
console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
|
|
1926
|
+
});
|
|
1927
|
+
const userInfo = { name: options.name };
|
|
1928
|
+
const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
|
|
1929
|
+
MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
|
|
1930
|
+
if (error) {
|
|
1931
|
+
reject(error.localizedFailureReason);
|
|
1932
|
+
}
|
|
1933
|
+
else {
|
|
1934
|
+
pack.resume();
|
|
1935
|
+
}
|
|
1936
|
+
});
|
|
1937
|
+
}
|
|
1938
|
+
catch (ex) {
|
|
1939
|
+
if (Trace.isEnabled()) {
|
|
1940
|
+
CLog(CLogTypes.info, 'Error in mapbox.downloadOfflineRegion: ' + ex);
|
|
1941
|
+
}
|
|
1942
|
+
reject(ex);
|
|
1943
|
+
}
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
listOfflineRegions(options) {
|
|
1947
|
+
return new Promise((resolve, reject) => {
|
|
1948
|
+
try {
|
|
1949
|
+
const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
|
|
1950
|
+
if (!packs) {
|
|
1951
|
+
reject('No packs found or Mapbox not ready yet');
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
const regions = [];
|
|
1955
|
+
for (let i = 0; i < packs.count; i++) {
|
|
1956
|
+
const pack = packs.objectAtIndex(i);
|
|
1957
|
+
const region = pack.region;
|
|
1958
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
|
|
1959
|
+
regions.push({
|
|
1960
|
+
name: userInfo.objectForKey('name'),
|
|
1961
|
+
style: '' + region.styleURL,
|
|
1962
|
+
minZoom: region.minimumZoomLevel,
|
|
1963
|
+
maxZoom: region.maximumZoomLevel,
|
|
1964
|
+
bounds: {
|
|
1965
|
+
north: region.bounds.ne.latitude,
|
|
1966
|
+
east: region.bounds.ne.longitude,
|
|
1967
|
+
south: region.bounds.sw.latitude,
|
|
1968
|
+
west: region.bounds.sw.longitude
|
|
1969
|
+
}
|
|
1970
|
+
});
|
|
1837
1971
|
}
|
|
1838
|
-
|
|
1839
|
-
resolve();
|
|
1972
|
+
resolve(regions);
|
|
1840
1973
|
}
|
|
1841
1974
|
catch (ex) {
|
|
1842
1975
|
if (Trace.isEnabled()) {
|
|
1843
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1976
|
+
CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
|
|
1844
1977
|
}
|
|
1845
1978
|
reject(ex);
|
|
1846
1979
|
}
|
|
1847
1980
|
});
|
|
1848
1981
|
}
|
|
1849
|
-
|
|
1982
|
+
deleteOfflineRegion(options) {
|
|
1850
1983
|
return new Promise((resolve, reject) => {
|
|
1851
1984
|
try {
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
reject('No map has been loaded');
|
|
1985
|
+
if (!options || (!options.id && !options.name)) {
|
|
1986
|
+
reject("Pass in the 'id' or 'name' param");
|
|
1855
1987
|
return;
|
|
1856
1988
|
}
|
|
1857
|
-
const
|
|
1858
|
-
|
|
1989
|
+
const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
|
|
1990
|
+
let found = false;
|
|
1991
|
+
for (let i = 0; i < packs.count; i++) {
|
|
1992
|
+
const pack = packs.objectAtIndex(i);
|
|
1993
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
|
|
1994
|
+
const regionId = options.id ? userInfo.objectForKey('id') : userInfo.objectForKey('name');
|
|
1995
|
+
if (regionId === (options.id || options.name)) {
|
|
1996
|
+
found = true;
|
|
1997
|
+
MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
|
|
1998
|
+
if (error) {
|
|
1999
|
+
reject(error.localizedFailureReason);
|
|
2000
|
+
}
|
|
2001
|
+
else {
|
|
2002
|
+
resolve();
|
|
2003
|
+
}
|
|
2004
|
+
});
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
if (!found) {
|
|
2008
|
+
reject('Region not found');
|
|
2009
|
+
}
|
|
1859
2010
|
}
|
|
1860
2011
|
catch (ex) {
|
|
1861
2012
|
if (Trace.isEnabled()) {
|
|
1862
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
2013
|
+
CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
|
|
1863
2014
|
}
|
|
1864
2015
|
reject(ex);
|
|
1865
2016
|
}
|
|
1866
2017
|
});
|
|
1867
2018
|
}
|
|
1868
|
-
|
|
2019
|
+
addExtrusion(options, nativeMap) {
|
|
1869
2020
|
return new Promise((resolve, reject) => {
|
|
1870
2021
|
try {
|
|
1871
2022
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1873,489 +2024,370 @@ export class Mapbox extends MapboxCommon {
|
|
|
1873
2024
|
reject('No map has been loaded');
|
|
1874
2025
|
return;
|
|
1875
2026
|
}
|
|
1876
|
-
|
|
1877
|
-
const result = [];
|
|
1878
|
-
for (let i = 0; i < layers.count; i++) {
|
|
1879
|
-
result.push(new Layer(layers[i]));
|
|
1880
|
-
}
|
|
1881
|
-
resolve(result);
|
|
2027
|
+
resolve();
|
|
1882
2028
|
}
|
|
1883
2029
|
catch (ex) {
|
|
1884
2030
|
if (Trace.isEnabled()) {
|
|
1885
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
2031
|
+
CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
|
|
1886
2032
|
}
|
|
1887
2033
|
reject(ex);
|
|
1888
2034
|
}
|
|
1889
2035
|
});
|
|
1890
2036
|
}
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
resolve(marker);
|
|
1915
|
-
}, (ignoredError) => {
|
|
1916
|
-
console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
|
|
1917
|
-
resolve(marker);
|
|
1918
|
-
});
|
|
1919
|
-
});
|
|
1920
|
-
}
|
|
1921
|
-
const _downloadMarkerImages = (markers) => {
|
|
1922
|
-
const iterations = [];
|
|
1923
|
-
const result = [];
|
|
1924
|
-
markers.forEach((marker) => {
|
|
1925
|
-
if (marker.icon && marker.icon.startsWith('http')) {
|
|
1926
|
-
const p = _downloadImage(marker).then((mark) => result.push(mark));
|
|
1927
|
-
iterations.push(p);
|
|
1928
|
-
}
|
|
1929
|
-
else {
|
|
1930
|
-
result.push(marker);
|
|
1931
|
-
}
|
|
1932
|
-
});
|
|
1933
|
-
return Promise.all(iterations).then(() => result);
|
|
1934
|
-
};
|
|
1935
|
-
var MGLMapViewDelegateImpl = /** @class */ (function (_super) {
|
|
1936
|
-
__extends(MGLMapViewDelegateImpl, _super);
|
|
1937
|
-
function MGLMapViewDelegateImpl() {
|
|
1938
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1939
|
-
}
|
|
1940
|
-
MGLMapViewDelegateImpl.new = function () {
|
|
1941
|
-
return _super.new.call(this);
|
|
1942
|
-
};
|
|
1943
|
-
/**
|
|
1944
|
-
* initialize with the mapReady callback
|
|
1945
|
-
*/
|
|
1946
|
-
MGLMapViewDelegateImpl.prototype.initWithCallback = function (mapLoadedCallback) {
|
|
1947
|
-
if (Trace.isEnabled()) {
|
|
1948
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::initWithCallback()');
|
|
1949
|
-
}
|
|
1950
|
-
this.mapLoadedCallback = mapLoadedCallback;
|
|
1951
|
-
return this;
|
|
1952
|
-
};
|
|
1953
|
-
/**
|
|
1954
|
-
* set a reference to the mapboxAPI instance
|
|
1955
|
-
*/
|
|
1956
|
-
MGLMapViewDelegateImpl.prototype.setMapboxApi = function (api) {
|
|
1957
|
-
this.mapboxApi = api;
|
|
1958
|
-
};
|
|
1959
|
-
/**
|
|
1960
|
-
* set the user location click listener callback
|
|
1961
|
-
*/
|
|
1962
|
-
MGLMapViewDelegateImpl.prototype.setUserLocationClickListener = function (callback) {
|
|
1963
|
-
this.userLocationClickListener = callback;
|
|
1964
|
-
};
|
|
1965
|
-
/**
|
|
1966
|
-
* set the user location click listener callback
|
|
1967
|
-
*/
|
|
1968
|
-
MGLMapViewDelegateImpl.prototype.setUserLocationChangedistener = function (callback) {
|
|
1969
|
-
this.userLocationChangedListener = callback;
|
|
1970
|
-
};
|
|
1971
|
-
/**
|
|
1972
|
-
* set user location marker modes
|
|
1973
|
-
*/
|
|
1974
|
-
MGLMapViewDelegateImpl.prototype.changeUserLocationRenderMode = function (userLocationRenderMode) {
|
|
1975
|
-
this.userLocationAnnotationView.changeUserLocationRenderMode(userLocationRenderMode);
|
|
1976
|
-
};
|
|
1977
|
-
/**
|
|
1978
|
-
* set the camera changd listener callback
|
|
1979
|
-
*/
|
|
1980
|
-
MGLMapViewDelegateImpl.prototype.setCameraChangedListener = function (callback) {
|
|
1981
|
-
this.cameraChangedListener = callback;
|
|
1982
|
-
};
|
|
1983
|
-
/**
|
|
1984
|
-
* set the camera idled listener callback
|
|
1985
|
-
*/
|
|
1986
|
-
MGLMapViewDelegateImpl.prototype.setCameraIdledListener = function (callback) {
|
|
1987
|
-
this.cameraIdledListener = callback;
|
|
1988
|
-
};
|
|
1989
|
-
/**
|
|
1990
|
-
* set style loaded callback.
|
|
1991
|
-
*
|
|
1992
|
-
* set an optional callback to be invoked when a style set with
|
|
1993
|
-
* setMapStyle() is finished loading
|
|
1994
|
-
*
|
|
1995
|
-
* @param {function} callback function with loaded style as parameter.
|
|
1996
|
-
*
|
|
1997
|
-
* @see Mapbox:setMapStyle()
|
|
1998
|
-
*/
|
|
1999
|
-
MGLMapViewDelegateImpl.prototype.setStyleLoadedCallback = function (callback) {
|
|
2000
|
-
this.styleLoadedCallback = callback;
|
|
2001
|
-
};
|
|
2002
|
-
/**
|
|
2003
|
-
* map ready callback
|
|
2004
|
-
*/
|
|
2005
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingMap = function (mapView) {
|
|
2006
|
-
if (Trace.isEnabled()) {
|
|
2007
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingMap(): top');
|
|
2008
|
-
}
|
|
2009
|
-
if (this.mapLoadedCallback !== undefined) {
|
|
2010
|
-
this.mapLoadedCallback(mapView);
|
|
2011
|
-
// this should be fired only once, but it's also fired when the style changes, so just remove the callback
|
|
2012
|
-
this.mapLoadedCallback = undefined;
|
|
2013
|
-
}
|
|
2014
|
-
};
|
|
2015
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFinishRenderingMapFullyRendered = function (mapView, fullyRendered) {
|
|
2016
|
-
if (Trace.isEnabled()) {
|
|
2017
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishRenderingMapFullyRendered(): rendered is:', fullyRendered);
|
|
2018
|
-
}
|
|
2019
|
-
};
|
|
2020
|
-
/**
|
|
2021
|
-
* Callback when the style has been loaded.
|
|
2022
|
-
*
|
|
2023
|
-
* Based on my testing, it looks like this callback is invoked multiple times.
|
|
2024
|
-
*
|
|
2025
|
-
* @see Mapbox:setMapStyle()
|
|
2026
|
-
*
|
|
2027
|
-
* @link https://mapbox.github.io/mapbox-gl-native/macos/0.3.0/Protocols/MGLMapViewDelegate.html#/c:objc(pl)MGLMapViewDelegate(im)mapView:didFinishLoadingStyle:
|
|
2028
|
-
*/
|
|
2029
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingStyle = function (mapView, style) {
|
|
2030
|
-
if (Trace.isEnabled()) {
|
|
2031
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingStyle(): callback called.');
|
|
2032
|
-
}
|
|
2033
|
-
if (this.styleLoadedCallback !== undefined) {
|
|
2034
|
-
this.styleLoadedCallback(mapView, style);
|
|
2035
|
-
// to avoid multiple calls. This is only invoked from setMapStyle().
|
|
2036
|
-
this.styleLoadedCallback = undefined;
|
|
2037
|
-
}
|
|
2038
|
-
};
|
|
2039
|
-
/**
|
|
2040
|
-
* disable the default user location callout
|
|
2041
|
-
*
|
|
2042
|
-
* This took forever to find. The default iOS click handler for the user location
|
|
2043
|
-
* marker is about useless. It just displays "You Are Here". The examples do not
|
|
2044
|
-
* show how to disable it.
|
|
2045
|
-
*/
|
|
2046
|
-
MGLMapViewDelegateImpl.prototype.mapViewAnnotationCanShowCallout = function (mapView, annotation) {
|
|
2047
|
-
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
2048
|
-
return false;
|
|
2049
|
-
}
|
|
2050
|
-
else {
|
|
2051
|
-
return true;
|
|
2052
|
-
}
|
|
2053
|
-
};
|
|
2054
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFailLoadingMapWithError = function (mapView, error) {
|
|
2055
|
-
if (Trace.isEnabled()) {
|
|
2056
|
-
CLog(CLogTypes.info, 'mapViewDidFailLoadingMapWithError: ' + error);
|
|
2057
|
-
}
|
|
2058
|
-
};
|
|
2059
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidChangeUserTrackingModeAnimated = function (mapView, mode, animated) {
|
|
2060
|
-
if (Trace.isEnabled()) {
|
|
2061
|
-
CLog(CLogTypes.info, 'mapViewDidChangeUserTrackingModeAnimated: ' + mode);
|
|
2062
|
-
}
|
|
2063
|
-
};
|
|
2064
|
-
/**
|
|
2065
|
-
* fired when the marker icon is about to be rendered - return null for the default icon
|
|
2066
|
-
*/
|
|
2067
|
-
MGLMapViewDelegateImpl.prototype.mapViewImageForAnnotation = function (mapView, annotation) {
|
|
2068
|
-
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
2069
|
-
if (cachedMarker) {
|
|
2070
|
-
if (cachedMarker.reuseIdentifier) {
|
|
2071
|
-
var reusedImage = mapView.dequeueReusableAnnotationImageWithIdentifier(cachedMarker.reuseIdentifier);
|
|
2072
|
-
if (reusedImage) {
|
|
2073
|
-
return reusedImage;
|
|
2037
|
+
updateSource(id, options, nativeMap) {
|
|
2038
|
+
return new Promise((resolve, reject) => {
|
|
2039
|
+
try {
|
|
2040
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2041
|
+
if (!theMap) {
|
|
2042
|
+
reject('No map has been loaded');
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
const source = theMap.style.sourceWithIdentifier(id);
|
|
2046
|
+
if (!source) {
|
|
2047
|
+
reject('Source does not exists: ' + id);
|
|
2048
|
+
return;
|
|
2049
|
+
}
|
|
2050
|
+
switch (options.type) {
|
|
2051
|
+
case 'geojson':
|
|
2052
|
+
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
2053
|
+
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
2054
|
+
const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
2055
|
+
source.shape = geoJsonShape;
|
|
2056
|
+
break;
|
|
2057
|
+
default:
|
|
2058
|
+
reject('Invalid source type: ' + options['type']);
|
|
2059
|
+
return;
|
|
2074
2060
|
}
|
|
2075
2061
|
}
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
if (cachedMarker.icon.startsWith('res://')) {
|
|
2080
|
-
var resourceName = cachedMarker.icon.substring('res://'.length);
|
|
2081
|
-
var imageSource = ImageSource.fromResourceSync(resourceName);
|
|
2082
|
-
if (imageSource === null) {
|
|
2083
|
-
console.log("Unable to locate " + resourceName);
|
|
2084
|
-
}
|
|
2085
|
-
else {
|
|
2086
|
-
cachedMarker.reuseIdentifier = cachedMarker.icon;
|
|
2087
|
-
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(imageSource.ios, cachedMarker.reuseIdentifier);
|
|
2088
|
-
}
|
|
2062
|
+
catch (ex) {
|
|
2063
|
+
if (Trace.isEnabled()) {
|
|
2064
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2089
2065
|
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2066
|
+
reject(ex);
|
|
2067
|
+
}
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
addSource(id, options, nativeMap) {
|
|
2071
|
+
return new Promise((resolve, reject) => {
|
|
2072
|
+
try {
|
|
2073
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2074
|
+
let source;
|
|
2075
|
+
if (!theMap) {
|
|
2076
|
+
reject('No map has been loaded');
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
if (theMap.style.sourceWithIdentifier(id)) {
|
|
2080
|
+
reject('Source exists: ' + id);
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2083
|
+
switch (options.type) {
|
|
2084
|
+
case 'vector': {
|
|
2085
|
+
if (options.url) {
|
|
2086
|
+
source = MGLVectorTileSource.alloc().initWithIdentifierConfigurationURL(id, NSURL.URLWithString(options.url));
|
|
2087
|
+
}
|
|
2088
|
+
else {
|
|
2089
|
+
const sourceOptions = {};
|
|
2090
|
+
if (options.minzoom !== undefined) {
|
|
2091
|
+
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
2092
|
+
}
|
|
2093
|
+
if (options.maxzoom !== undefined) {
|
|
2094
|
+
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
2095
|
+
}
|
|
2096
|
+
if (options.scheme) {
|
|
2097
|
+
switch (options.scheme) {
|
|
2098
|
+
case 'xyz':
|
|
2099
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
2100
|
+
break;
|
|
2101
|
+
case 'tms':
|
|
2102
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
2103
|
+
break;
|
|
2104
|
+
default:
|
|
2105
|
+
throw new Error('Unknown raster tile scheme.');
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
if (options.bounds) {
|
|
2109
|
+
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
2110
|
+
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
2111
|
+
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
2115
|
+
}
|
|
2116
|
+
break;
|
|
2117
|
+
}
|
|
2118
|
+
case 'geojson':
|
|
2119
|
+
if (theMap.style.sourceWithIdentifier(id)) {
|
|
2120
|
+
reject("Remove the layer with this id first with 'removeLayer': " + id);
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
2123
|
+
let geoJsonShape;
|
|
2124
|
+
if (options.data) {
|
|
2125
|
+
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
2126
|
+
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
2127
|
+
geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
2128
|
+
}
|
|
2129
|
+
const sourceOptions = {};
|
|
2130
|
+
if (options.minzoom !== undefined) {
|
|
2131
|
+
sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
2132
|
+
}
|
|
2133
|
+
if (options.maxzoom !== undefined) {
|
|
2134
|
+
sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
2135
|
+
}
|
|
2136
|
+
if (options.cluster) {
|
|
2137
|
+
sourceOptions[MGLShapeSourceOptionClustered] = true;
|
|
2138
|
+
sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
|
|
2139
|
+
sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
|
|
2140
|
+
}
|
|
2141
|
+
source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
|
|
2142
|
+
break;
|
|
2143
|
+
case 'raster': {
|
|
2144
|
+
const sourceOptions = {
|
|
2145
|
+
[MGLTileSourceOptionTileSize]: options.tileSize || 256
|
|
2146
|
+
};
|
|
2147
|
+
if (options.minzoom !== undefined) {
|
|
2148
|
+
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
2149
|
+
}
|
|
2150
|
+
if (options.maxzoom !== undefined) {
|
|
2151
|
+
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
2152
|
+
}
|
|
2153
|
+
if (options.scheme) {
|
|
2154
|
+
switch (options.scheme || 'xyz') {
|
|
2155
|
+
case 'xyz':
|
|
2156
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
2157
|
+
break;
|
|
2158
|
+
case 'tms':
|
|
2159
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
2160
|
+
break;
|
|
2161
|
+
default:
|
|
2162
|
+
throw new Error('Unknown raster tile scheme.');
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
if (options.bounds) {
|
|
2166
|
+
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
2167
|
+
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
2168
|
+
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
2172
|
+
break;
|
|
2094
2173
|
}
|
|
2174
|
+
default:
|
|
2175
|
+
reject('Invalid source type: ' + options['type']);
|
|
2176
|
+
return;
|
|
2095
2177
|
}
|
|
2096
|
-
|
|
2178
|
+
if (!source) {
|
|
2179
|
+
const ex = 'No source to add';
|
|
2097
2180
|
if (Trace.isEnabled()) {
|
|
2098
|
-
CLog(CLogTypes.info, '
|
|
2181
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2099
2182
|
}
|
|
2183
|
+
reject(ex);
|
|
2184
|
+
return;
|
|
2100
2185
|
}
|
|
2186
|
+
theMap.style.addSource(source);
|
|
2187
|
+
resolve();
|
|
2101
2188
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
if (File.exists(iconFullPath)) {
|
|
2106
|
-
var image = ImageSource.fromFileSync(iconFullPath).ios;
|
|
2107
|
-
// perhaps add resize options for nice retina rendering (although you can now use the 'icon' param instead)
|
|
2108
|
-
cachedMarker.reuseIdentifier = cachedMarker.iconPath;
|
|
2109
|
-
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(image, cachedMarker.reuseIdentifier);
|
|
2189
|
+
catch (ex) {
|
|
2190
|
+
if (Trace.isEnabled()) {
|
|
2191
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2110
2192
|
}
|
|
2193
|
+
reject(ex);
|
|
2111
2194
|
}
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2195
|
+
});
|
|
2196
|
+
}
|
|
2197
|
+
removeSource(id, nativeMap) {
|
|
2198
|
+
return new Promise((resolve, reject) => {
|
|
2199
|
+
try {
|
|
2200
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2201
|
+
if (!theMap) {
|
|
2202
|
+
reject('No map has been loaded');
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
const source = theMap.style.sourceWithIdentifier(id);
|
|
2206
|
+
if (!source) {
|
|
2207
|
+
reject('Source does not exist');
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
theMap.style.removeSource(source);
|
|
2211
|
+
resolve();
|
|
2129
2212
|
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2213
|
+
catch (ex) {
|
|
2214
|
+
if (Trace.isEnabled()) {
|
|
2215
|
+
CLog(CLogTypes.info, 'Error in mapbox.removeSource: ' + ex);
|
|
2216
|
+
}
|
|
2217
|
+
reject(ex);
|
|
2133
2218
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2219
|
+
});
|
|
2220
|
+
}
|
|
2221
|
+
async addLayer(style, belowLayerId, nativeMapView) {
|
|
2222
|
+
const theMap = nativeMapView || this._mapboxViewInstance;
|
|
2223
|
+
let source = null;
|
|
2224
|
+
if (typeof style.source != 'string') {
|
|
2225
|
+
await this.addSource(style.id + '_source', style.source);
|
|
2226
|
+
source = theMap.style.sourceWithIdentifier(style.id + '_source');
|
|
2139
2227
|
}
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
* fired when a callout is tapped
|
|
2143
|
-
*/
|
|
2144
|
-
MGLMapViewDelegateImpl.prototype.mapViewTapOnCalloutForAnnotation = function (mapView, annotation) {
|
|
2145
|
-
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
2146
|
-
if (cachedMarker && cachedMarker.onCalloutTap) {
|
|
2147
|
-
cachedMarker.onCalloutTap(cachedMarker);
|
|
2228
|
+
else {
|
|
2229
|
+
source = theMap.style.sourceWithIdentifier(style.source);
|
|
2148
2230
|
}
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
// eslint-disable-next-line eqeqeq
|
|
2156
|
-
cached.lat == tapped.coordinate.latitude &&
|
|
2157
|
-
// eslint-disable-next-line eqeqeq
|
|
2158
|
-
cached.lng == tapped.coordinate.longitude &&
|
|
2159
|
-
// eslint-disable-next-line eqeqeq
|
|
2160
|
-
cached.title == tapped.title &&
|
|
2161
|
-
// eslint-disable-next-line eqeqeq
|
|
2162
|
-
cached.subtitle == tapped.subtitle) {
|
|
2163
|
-
return cached;
|
|
2231
|
+
const layer = await LayerFactory.createLayer(style, source);
|
|
2232
|
+
if (belowLayerId) {
|
|
2233
|
+
const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
|
|
2234
|
+
if (belowlayer) {
|
|
2235
|
+
theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
|
|
2236
|
+
return;
|
|
2164
2237
|
}
|
|
2165
2238
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
|
|
2239
|
+
theMap.style.addLayer(layer.getNativeInstance());
|
|
2240
|
+
}
|
|
2241
|
+
async removeLayer(id, nativeMapViewInstance) {
|
|
2242
|
+
const theMap = nativeMapViewInstance || this._mapboxViewInstance;
|
|
2171
2243
|
if (Trace.isEnabled()) {
|
|
2172
|
-
CLog(CLogTypes.info,
|
|
2173
|
-
}
|
|
2174
|
-
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
2175
|
-
this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init();
|
|
2176
|
-
return this.userLocationAnnotationView;
|
|
2244
|
+
CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
|
|
2177
2245
|
}
|
|
2178
|
-
|
|
2179
|
-
};
|
|
2180
|
-
MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
|
|
2246
|
+
const layer = theMap.style.layerWithIdentifier(id);
|
|
2181
2247
|
if (Trace.isEnabled()) {
|
|
2182
|
-
CLog(CLogTypes.info, '
|
|
2248
|
+
CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
|
|
2183
2249
|
}
|
|
2184
|
-
if (
|
|
2185
|
-
|
|
2250
|
+
if (!layer) {
|
|
2251
|
+
throw new Error("Layer '" + id + "' not found when attempting to remove it.");
|
|
2186
2252
|
}
|
|
2187
|
-
|
|
2188
|
-
MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
|
|
2253
|
+
theMap.style.removeLayer(layer);
|
|
2189
2254
|
if (Trace.isEnabled()) {
|
|
2190
|
-
CLog(CLogTypes.info, '
|
|
2191
|
-
}
|
|
2192
|
-
if (this.cameraChangedListener) {
|
|
2193
|
-
this.cameraChangedListener(reason, animated);
|
|
2255
|
+
CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
|
|
2194
2256
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2257
|
+
}
|
|
2258
|
+
async addLinePoint(id, lnglat, sourceId, nativeMapView) {
|
|
2259
|
+
const theMap = nativeMapView || this._mapboxViewInstance;
|
|
2260
|
+
const sId = !!sourceId ? sourceId : id + '_source';
|
|
2261
|
+
const lineSource = theMap.style.sourceWithIdentifier(sId);
|
|
2262
|
+
if (!lineSource) {
|
|
2263
|
+
throw new Error(`no source found with id: ${sId}`);
|
|
2197
2264
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2265
|
+
try {
|
|
2266
|
+
const lineFeatures = lineSource.featuresMatchingPredicate(FilterParser.parseJson(['==', '$type', 'LineString']));
|
|
2267
|
+
if (lineFeatures.count === 0) {
|
|
2268
|
+
throw new Error('no line string feature found');
|
|
2269
|
+
}
|
|
2270
|
+
const lineFeature = lineFeatures.objectAtIndex(0);
|
|
2271
|
+
const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
|
|
2272
|
+
const newCoordPointer = new interop.Reference(newCoord);
|
|
2273
|
+
lineFeature.appendCoordinatesCount(newCoordPointer, 1);
|
|
2274
|
+
lineSource.shape = lineFeature;
|
|
2202
2275
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2276
|
+
catch (error) {
|
|
2277
|
+
console.log(error);
|
|
2278
|
+
throw error;
|
|
2205
2279
|
}
|
|
2206
|
-
};
|
|
2207
|
-
MGLMapViewDelegateImpl.ObjCProtocols = [MGLMapViewDelegate];
|
|
2208
|
-
return MGLMapViewDelegateImpl;
|
|
2209
|
-
}(NSObject));
|
|
2210
|
-
var MapTapHandlerImpl = /** @class */ (function (_super) {
|
|
2211
|
-
__extends(MapTapHandlerImpl, _super);
|
|
2212
|
-
function MapTapHandlerImpl() {
|
|
2213
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2214
2280
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
handler._owner = owner;
|
|
2218
|
-
handler._listener = listener;
|
|
2219
|
-
handler._mapView = mapView;
|
|
2220
|
-
return handler;
|
|
2221
|
-
};
|
|
2222
|
-
MapTapHandlerImpl.prototype.tap = function (recognizer) {
|
|
2223
|
-
var tapPoint = recognizer.locationInView(this._mapView);
|
|
2224
|
-
var tapCoordinate = this._mapView.convertPointToCoordinateFromView(tapPoint, this._mapView);
|
|
2225
|
-
this._listener({
|
|
2226
|
-
lat: tapCoordinate.latitude,
|
|
2227
|
-
lng: tapCoordinate.longitude
|
|
2228
|
-
});
|
|
2229
|
-
};
|
|
2230
|
-
MapTapHandlerImpl.ObjCExposedMethods = {
|
|
2231
|
-
tap: { returns: interop.types.void, params: [interop.types.id] }
|
|
2232
|
-
};
|
|
2233
|
-
return MapTapHandlerImpl;
|
|
2234
|
-
}(NSObject));
|
|
2235
|
-
var MapLongPressHandlerImpl = /** @class */ (function (_super) {
|
|
2236
|
-
__extends(MapLongPressHandlerImpl, _super);
|
|
2237
|
-
function MapLongPressHandlerImpl() {
|
|
2238
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2281
|
+
addGeoJsonClustered(options, nativeMapViewInstance) {
|
|
2282
|
+
throw new Error('Method not implemented.');
|
|
2239
2283
|
}
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2284
|
+
trackUser(options, nativeMap) {
|
|
2285
|
+
return new Promise((resolve, reject) => {
|
|
2286
|
+
try {
|
|
2287
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2288
|
+
if (!theMap) {
|
|
2289
|
+
reject('No map has been loaded');
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
if (!theMap.showsUserLocation) {
|
|
2293
|
+
reject('The map is not currently showing the user location');
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
theMap.setUserTrackingModeAnimated(_getTrackingMode(options.cameraMode), options.animated !== false);
|
|
2297
|
+
resolve();
|
|
2298
|
+
}
|
|
2299
|
+
catch (ex) {
|
|
2300
|
+
if (Trace.isEnabled()) {
|
|
2301
|
+
CLog(CLogTypes.info, 'Error in mapbox.trackUser: ' + ex);
|
|
2302
|
+
}
|
|
2303
|
+
reject(ex);
|
|
2304
|
+
}
|
|
2253
2305
|
});
|
|
2254
|
-
};
|
|
2255
|
-
MapLongPressHandlerImpl.ObjCExposedMethods = {
|
|
2256
|
-
longPress: { returns: interop.types.void, params: [interop.types.id] }
|
|
2257
|
-
};
|
|
2258
|
-
return MapLongPressHandlerImpl;
|
|
2259
|
-
}(NSObject));
|
|
2260
|
-
var MapPanHandlerImpl = /** @class */ (function (_super) {
|
|
2261
|
-
__extends(MapPanHandlerImpl, _super);
|
|
2262
|
-
function MapPanHandlerImpl() {
|
|
2263
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2264
2306
|
}
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
var panPoint = recognizer.locationInView(this._mapView);
|
|
2278
|
-
var panCoordinate = this._mapView.convertPointToCoordinateFromView(panPoint, this._mapView);
|
|
2279
|
-
if (Trace.isEnabled()) {
|
|
2280
|
-
CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): top with state:', recognizer.state);
|
|
2281
|
-
}
|
|
2282
|
-
// if this is the beginning of the pan simulate the Android onMoveBegin
|
|
2283
|
-
//
|
|
2284
|
-
// See the objc platform declarations in objc!UIKit.d.ts. It doesn't quite match the apple documention
|
|
2285
|
-
if (this.onMoveBegin) {
|
|
2286
|
-
if (recognizer.state === UIGestureRecognizerState.Began) {
|
|
2307
|
+
getLayer(name, nativeMap) {
|
|
2308
|
+
return new Promise((resolve, reject) => {
|
|
2309
|
+
try {
|
|
2310
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2311
|
+
if (!theMap) {
|
|
2312
|
+
reject('No map has been loaded');
|
|
2313
|
+
return;
|
|
2314
|
+
}
|
|
2315
|
+
const layer = theMap.style.layerWithIdentifier(name);
|
|
2316
|
+
resolve(new Layer(layer));
|
|
2317
|
+
}
|
|
2318
|
+
catch (ex) {
|
|
2287
2319
|
if (Trace.isEnabled()) {
|
|
2288
|
-
CLog(CLogTypes.info, '
|
|
2320
|
+
CLog(CLogTypes.info, 'Error in mapbox.getLayer: ' + ex);
|
|
2289
2321
|
}
|
|
2290
|
-
|
|
2291
|
-
lat: panCoordinate.latitude,
|
|
2292
|
-
lng: panCoordinate.longitude
|
|
2293
|
-
});
|
|
2322
|
+
reject(ex);
|
|
2294
2323
|
}
|
|
2295
|
-
return;
|
|
2296
|
-
}
|
|
2297
|
-
this._listener({
|
|
2298
|
-
lat: panCoordinate.latitude,
|
|
2299
|
-
lng: panCoordinate.longitude
|
|
2300
2324
|
});
|
|
2301
|
-
};
|
|
2302
|
-
MapPanHandlerImpl.ObjCExposedMethods = {
|
|
2303
|
-
pan: { returns: interop.types.void, params: [interop.types.id] }
|
|
2304
|
-
};
|
|
2305
|
-
return MapPanHandlerImpl;
|
|
2306
|
-
}(NSObject));
|
|
2307
|
-
var MapSwipeHandlerImpl = /** @class */ (function (_super) {
|
|
2308
|
-
__extends(MapSwipeHandlerImpl, _super);
|
|
2309
|
-
function MapSwipeHandlerImpl() {
|
|
2310
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2311
2325
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2326
|
+
getLayers(nativeMap) {
|
|
2327
|
+
return new Promise((resolve, reject) => {
|
|
2328
|
+
try {
|
|
2329
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2330
|
+
if (!theMap) {
|
|
2331
|
+
reject('No map has been loaded');
|
|
2332
|
+
return;
|
|
2333
|
+
}
|
|
2334
|
+
const layers = theMap.style.layers;
|
|
2335
|
+
const result = [];
|
|
2336
|
+
for (let i = 0; i < layers.count; i++) {
|
|
2337
|
+
result.push(new Layer(layers[i]));
|
|
2338
|
+
}
|
|
2339
|
+
resolve(result);
|
|
2340
|
+
}
|
|
2341
|
+
catch (ex) {
|
|
2342
|
+
if (Trace.isEnabled()) {
|
|
2343
|
+
CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
|
|
2344
|
+
}
|
|
2345
|
+
reject(ex);
|
|
2346
|
+
}
|
|
2325
2347
|
});
|
|
2326
|
-
};
|
|
2327
|
-
MapSwipeHandlerImpl.ObjCExposedMethods = {
|
|
2328
|
-
swipe: { returns: interop.types.void, params: [interop.types.id] }
|
|
2329
|
-
};
|
|
2330
|
-
return MapSwipeHandlerImpl;
|
|
2331
|
-
}(NSObject));
|
|
2332
|
-
export class Layer {
|
|
2333
|
-
constructor(instance) {
|
|
2334
|
-
this.instance = instance;
|
|
2335
|
-
this.id = instance.identifier;
|
|
2336
|
-
}
|
|
2337
|
-
visibility() {
|
|
2338
|
-
return this.instance.visible;
|
|
2339
|
-
}
|
|
2340
|
-
show() {
|
|
2341
|
-
this.instance.visible = true;
|
|
2342
2348
|
}
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
return this.instance;
|
|
2349
|
+
project(data) {
|
|
2350
|
+
const theMap = this._mapboxViewInstance;
|
|
2351
|
+
const { x, y } = theMap.convertCoordinateToPointToView({ latitude: data.lat, longitude: data.lng }, theMap);
|
|
2352
|
+
return { x, y };
|
|
2348
2353
|
}
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2354
|
+
}
|
|
2355
|
+
const _addObserver = (eventName, callback) => NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback);
|
|
2356
|
+
function _downloadImage(marker) {
|
|
2357
|
+
return new Promise((resolve, reject) => {
|
|
2358
|
+
if (Trace.isEnabled()) {
|
|
2359
|
+
CLog(CLogTypes.info, '>> _downloadImage');
|
|
2352
2360
|
}
|
|
2353
|
-
|
|
2354
|
-
|
|
2361
|
+
if (_markerIconDownloadCache[marker.icon]) {
|
|
2362
|
+
marker.iconDownloaded = _markerIconDownloadCache[marker.icon];
|
|
2363
|
+
if (Trace.isEnabled()) {
|
|
2364
|
+
CLog(CLogTypes.info, '>> marker.iconDownloaded: ' + marker.iconDownloaded);
|
|
2365
|
+
}
|
|
2366
|
+
resolve(marker);
|
|
2367
|
+
return;
|
|
2355
2368
|
}
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2369
|
+
Http.getImage(marker.icon).then((output) => {
|
|
2370
|
+
marker.iconDownloaded = output.ios;
|
|
2371
|
+
_markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
|
|
2372
|
+
resolve(marker);
|
|
2373
|
+
}, (ignoredError) => {
|
|
2374
|
+
console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
|
|
2375
|
+
resolve(marker);
|
|
2376
|
+
});
|
|
2377
|
+
});
|
|
2360
2378
|
}
|
|
2361
|
-
|
|
2379
|
+
const _downloadMarkerImages = (markers) => {
|
|
2380
|
+
const iterations = [];
|
|
2381
|
+
const result = [];
|
|
2382
|
+
markers.forEach((marker) => {
|
|
2383
|
+
if (marker.icon && marker.icon.startsWith('http')) {
|
|
2384
|
+
const p = _downloadImage(marker).then((mark) => result.push(mark));
|
|
2385
|
+
iterations.push(p);
|
|
2386
|
+
}
|
|
2387
|
+
else {
|
|
2388
|
+
result.push(marker);
|
|
2389
|
+
}
|
|
2390
|
+
});
|
|
2391
|
+
return Promise.all(iterations).then(() => result);
|
|
2392
|
+
};
|
|
2393
|
+
//# sourceMappingURL=index.ios.js.map
|