@nativescript-community/ui-mapbox 6.2.10 → 6.2.14
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 +36 -0
- package/README.md +199 -99
- package/{mapbox.common.d.ts → common.d.ts} +42 -4
- package/{mapbox.common.js → common.js} +21 -1
- package/{filter/filter-parser.android.d.ts → expression/expression-parser.android.d.ts} +1 -1
- package/{filter/filter-parser.android.js → expression/expression-parser.android.js} +2 -2
- package/expression/expression-parser.d.ts +4 -0
- package/{filter/filter-parser.ios.d.ts → expression/expression-parser.ios.d.ts} +1 -1
- package/{filter/filter-parser.ios.js → expression/expression-parser.ios.js} +2 -2
- package/{mapbox.android.d.ts → index.android.d.ts} +9 -14
- package/{mapbox.android.js → index.android.js} +152 -65
- package/index.d.ts +99 -6
- package/{mapbox.ios.d.ts → index.ios.d.ts} +7 -30
- package/{mapbox.ios.js → index.ios.js} +1977 -1912
- package/layers/layer-factory.android.d.ts +15 -1
- package/layers/layer-factory.android.js +63 -2
- package/layers/layer-factory.d.ts +17 -2
- package/layers/layer-factory.ios.d.ts +15 -1
- package/layers/layer-factory.ios.js +72 -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/typings/Mapbox.ios.d.ts +2 -0
- package/LICENSE +0 -21
|
@@ -1,1564 +1,1665 @@
|
|
|
1
|
-
import { Color, File, ImageSource, Trace, knownFolders, path } from '@nativescript/core';
|
|
2
|
-
import { CLog, CLogTypes, MapStyle, MapboxCommon,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const _markerIconDownloadCache = [];
|
|
10
|
-
const _setMapboxMapOptions = (mapView, settings) => {
|
|
11
|
-
mapView.logoView.hidden = settings.hideLogo;
|
|
12
|
-
mapView.attributionButton.hidden = settings.hideAttribution;
|
|
13
|
-
mapView.compassView.hidden = settings.hideCompass;
|
|
14
|
-
mapView.rotateEnabled = !settings.disableRotation;
|
|
15
|
-
mapView.scrollEnabled = !settings.disableScroll;
|
|
16
|
-
mapView.zoomEnabled = !settings.disableZoom;
|
|
17
|
-
mapView.allowsTilting = !settings.disableTilt;
|
|
18
|
-
if (settings.center && settings.center.lat && settings.center.lng) {
|
|
19
|
-
const centerCoordinate = CLLocationCoordinate2DMake(settings.center.lat, settings.center.lng);
|
|
20
|
-
mapView.setCenterCoordinateZoomLevelAnimated(centerCoordinate, settings.zoomLevel, false);
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
mapView.setZoomLevelAnimated(settings.zoomLevel, false);
|
|
24
|
-
}
|
|
25
|
-
mapView.showsUserLocation = settings.showUserLocation;
|
|
26
|
-
mapView.autoresizingMask = 2 | 16;
|
|
27
|
-
};
|
|
28
|
-
const _getMapStyle = (input) => {
|
|
29
|
-
if (input.startsWith('mapbox://styles') || input.startsWith('http://') || input.startsWith('https://')) {
|
|
30
|
-
return NSURL.URLWithString(input);
|
|
31
|
-
}
|
|
32
|
-
else if (input.startsWith('~/')) {
|
|
33
|
-
return NSURL.URLWithString('file://' + path.join(knownFolders.currentApp().path, input.replace('~/', '')));
|
|
34
|
-
}
|
|
35
|
-
else if (input === MapStyle.LIGHT) {
|
|
36
|
-
return MGLStyle.lightStyleURL;
|
|
37
|
-
}
|
|
38
|
-
else if (input === MapStyle.DARK) {
|
|
39
|
-
return MGLStyle.darkStyleURL;
|
|
40
|
-
}
|
|
41
|
-
else if (input === MapStyle.OUTDOORS) {
|
|
42
|
-
return MGLStyle.outdoorsStyleURL;
|
|
43
|
-
}
|
|
44
|
-
else if (input === MapStyle.SATELLITE) {
|
|
45
|
-
return MGLStyle.satelliteStyleURL;
|
|
46
|
-
}
|
|
47
|
-
else if (input === MapStyle.SATELLITE_STREETS) {
|
|
48
|
-
return MGLStyle.satelliteStreetsStyleURL;
|
|
49
|
-
}
|
|
50
|
-
else if (input === MapStyle.TRAFFIC_DAY) {
|
|
51
|
-
return NSURL.URLWithString('mapbox://styles/mapbox/traffic-day-v2');
|
|
52
|
-
}
|
|
53
|
-
else if (input === MapStyle.TRAFFIC_NIGHT) {
|
|
54
|
-
return NSURL.URLWithString('mapbox://styles/mapbox/traffic-night-v2');
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
return MGLStyle.streetsStyleURL;
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
function _getTrackingMode(input) {
|
|
61
|
-
return 0;
|
|
62
|
-
}
|
|
63
|
-
function _getLocation(loc) {
|
|
64
|
-
if (loc === null) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
return {
|
|
69
|
-
location: {
|
|
70
|
-
lat: loc.coordinate.latitude,
|
|
71
|
-
lng: loc.coordinate.longitude
|
|
72
|
-
},
|
|
73
|
-
speed: loc.location ? loc.location.speed : 0
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
export function setLogLevel(level) {
|
|
78
|
-
let loggingLevel;
|
|
79
|
-
switch (level) {
|
|
80
|
-
case 'none':
|
|
81
|
-
loggingLevel = 0;
|
|
82
|
-
break;
|
|
83
|
-
case 'info':
|
|
84
|
-
loggingLevel = 1;
|
|
85
|
-
break;
|
|
86
|
-
case 'verbose':
|
|
87
|
-
case 'debug':
|
|
88
|
-
loggingLevel = 2;
|
|
89
|
-
break;
|
|
90
|
-
case 'error':
|
|
91
|
-
loggingLevel = 3;
|
|
92
|
-
break;
|
|
93
|
-
case 'fault':
|
|
94
|
-
loggingLevel = 4;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
MGLLoggingConfiguration.sharedConfiguration.loggingLevel = loggingLevel;
|
|
98
|
-
}
|
|
99
|
-
export class MapboxView extends MapboxViewBase {
|
|
100
|
-
constructor() {
|
|
101
|
-
super(...arguments);
|
|
102
|
-
this.nativeMapView = null;
|
|
103
|
-
this.delegate = null;
|
|
104
|
-
this.settings = null;
|
|
105
|
-
this.initialized = false;
|
|
106
|
-
this.initCountHack = 50;
|
|
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 { ExpressionParser } from './expression/expression-parser';
|
|
5
|
+
var MGLMapViewDelegateImpl = /** @class */ (function (_super) {
|
|
6
|
+
__extends(MGLMapViewDelegateImpl, _super);
|
|
7
|
+
function MGLMapViewDelegateImpl() {
|
|
8
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
107
9
|
}
|
|
108
|
-
|
|
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) {
|
|
109
17
|
if (Trace.isEnabled()) {
|
|
110
|
-
CLog(CLogTypes.info, '
|
|
18
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::initWithCallback()');
|
|
111
19
|
}
|
|
112
|
-
this.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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) {
|
|
118
76
|
if (Trace.isEnabled()) {
|
|
119
|
-
CLog(CLogTypes.info, '
|
|
77
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingMap(): top');
|
|
120
78
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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) {
|
|
126
86
|
if (Trace.isEnabled()) {
|
|
127
|
-
CLog(CLogTypes.info, '
|
|
87
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishRenderingMapFullyRendered(): rendered is:', fullyRendered);
|
|
128
88
|
}
|
|
129
|
-
|
|
130
|
-
|
|
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.');
|
|
131
102
|
}
|
|
132
|
-
if (
|
|
133
|
-
this.
|
|
134
|
-
|
|
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;
|
|
135
107
|
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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;
|
|
144
119
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (Trace.isEnabled()) {
|
|
148
|
-
CLog(CLogTypes.info, 'disposeNativeView(): after mapbox.destroy()');
|
|
120
|
+
else {
|
|
121
|
+
return true;
|
|
149
122
|
}
|
|
150
|
-
|
|
123
|
+
};
|
|
124
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidFailLoadingMapWithError = function (mapView, error) {
|
|
151
125
|
if (Trace.isEnabled()) {
|
|
152
|
-
CLog(CLogTypes.info, '
|
|
126
|
+
CLog(CLogTypes.info, 'mapViewDidFailLoadingMapWithError: ' + error);
|
|
153
127
|
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return this.mapbox;
|
|
157
|
-
}
|
|
158
|
-
initMap() {
|
|
128
|
+
};
|
|
129
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidChangeUserTrackingModeAnimated = function (mapView, mode, animated) {
|
|
159
130
|
if (Trace.isEnabled()) {
|
|
160
|
-
CLog(CLogTypes.info, '
|
|
131
|
+
CLog(CLogTypes.info, 'mapViewDidChangeUserTrackingModeAnimated: ' + mode);
|
|
161
132
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
if (!this.settings) {
|
|
176
|
-
this.settings = Mapbox.merge(this.config, Mapbox.defaults);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
this.settings = Mapbox.merge(this.settings, Mapbox.defaults);
|
|
180
|
-
}
|
|
181
|
-
if (!this.nativeMapView) {
|
|
182
|
-
this.mapbox = new Mapbox(this);
|
|
183
|
-
if (Trace.isEnabled()) {
|
|
184
|
-
CLog(CLogTypes.info, 'initMap(): after new Mapbox()');
|
|
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
|
+
}
|
|
185
145
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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));
|
|
192
154
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
ios: this.nativeMapView
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
_setMapboxMapOptions(this.nativeMapView, this.settings);
|
|
209
|
-
_markers = [];
|
|
210
|
-
this.nativeView.addSubview(this.nativeMapView);
|
|
211
|
-
this.mapbox.setOnMoveBeginListener((data) => {
|
|
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 {
|
|
212
167
|
if (Trace.isEnabled()) {
|
|
213
|
-
CLog(CLogTypes.info, '
|
|
168
|
+
CLog(CLogTypes.info, 'Please use res://resourceName, http(s)://imageUrl or iconPath to use a local path');
|
|
214
169
|
}
|
|
215
|
-
|
|
216
|
-
eventName: MapboxViewBase.moveBeginEvent,
|
|
217
|
-
object: this,
|
|
218
|
-
map: this,
|
|
219
|
-
ios: this.nativeMapView
|
|
220
|
-
});
|
|
221
|
-
}, this.nativeMapView);
|
|
222
|
-
};
|
|
223
|
-
setTimeout(drawMap, this.settings.delay ? this.settings.delay : 0);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
onLayout(left, top, right, bottom) {
|
|
227
|
-
super.onLayout(left, top, right, bottom);
|
|
228
|
-
if (this.nativeMapView) {
|
|
229
|
-
this.nativeMapView.layer.frame = this.ios.layer.bounds;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
[telemetryProperty.setNative](value) {
|
|
233
|
-
NSUserDefaults.standardUserDefaults.setBoolForKey(false, 'MGLMapboxMetricsEnabled');
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
"use strict";
|
|
237
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
238
|
-
exports.CustomUserLocationAnnotationView = void 0;
|
|
239
|
-
var CustomUserLocationAnnotationView = /** @class */ (function (_super) {
|
|
240
|
-
__extends(CustomUserLocationAnnotationView, _super);
|
|
241
|
-
function CustomUserLocationAnnotationView() {
|
|
242
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* init
|
|
246
|
-
*
|
|
247
|
-
* @link https://docs.nativescript.org/core-concepts/ios-runtime/HelloWorld
|
|
248
|
-
*/
|
|
249
|
-
CustomUserLocationAnnotationView.prototype.init = function () {
|
|
250
|
-
this.size = 48;
|
|
251
|
-
_super.prototype.initWithFrame.call(this, CGRectMake(0, 0, this.size, this.size));
|
|
252
|
-
this.renderModeChanged = true;
|
|
253
|
-
this.userLocationRenderMode = 'NORMAL';
|
|
254
|
-
return this;
|
|
255
|
-
};
|
|
256
|
-
/**
|
|
257
|
-
* update
|
|
258
|
-
*
|
|
259
|
-
* The note from the Objective-C sample indicates this method may be called quite
|
|
260
|
-
* often so it needs to be kept lightweight.
|
|
261
|
-
*/
|
|
262
|
-
CustomUserLocationAnnotationView.prototype.update = function () {
|
|
263
|
-
if (CLLocationCoordinate2DIsValid(this.userLocation.coordinate)) {
|
|
264
|
-
// if it's the first time here, setup the layers that make up the
|
|
265
|
-
// location marker.
|
|
266
|
-
if (!this.dot) {
|
|
267
|
-
this.drawNonTrackingLocationMarker();
|
|
170
|
+
}
|
|
268
171
|
}
|
|
269
|
-
if (
|
|
270
|
-
|
|
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
|
+
}
|
|
271
181
|
}
|
|
272
182
|
}
|
|
183
|
+
return null;
|
|
273
184
|
};
|
|
274
185
|
/**
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* @link https://docs.nativescript.org/ns-framework-modules/color
|
|
186
|
+
* fired when one of the callout's accessoryviews is tapped (not currently used)
|
|
278
187
|
*/
|
|
279
|
-
|
|
280
|
-
if (Trace.isEnabled()) {
|
|
281
|
-
CLog(CLogTypes.info, 'CustomerUserLocationAnnotatinView::drawTrackingLocationMarker()');
|
|
282
|
-
}
|
|
283
|
-
this.drawTrackingDot();
|
|
284
|
-
this.drawArrow();
|
|
285
|
-
}; // end of setupLayers()
|
|
188
|
+
MGLMapViewDelegateImpl.prototype.mapViewAnnotationCalloutAccessoryControlTapped = function (mapView, annotation, control) { };
|
|
286
189
|
/**
|
|
287
|
-
*
|
|
190
|
+
* fired when a marker is tapped
|
|
288
191
|
*/
|
|
289
|
-
|
|
192
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidSelectAnnotation = function (mapView, annotation) {
|
|
290
193
|
if (Trace.isEnabled()) {
|
|
291
|
-
CLog(CLogTypes.info, '
|
|
194
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidSelectAnntation()');
|
|
292
195
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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);
|
|
297
209
|
}
|
|
298
210
|
};
|
|
299
211
|
/**
|
|
300
|
-
*
|
|
212
|
+
* fired when a callout is tapped
|
|
301
213
|
*/
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
this.bounds = CGRectMake(0, 0, this.size, this.size);
|
|
307
|
-
var dot = CALayer.layer();
|
|
308
|
-
dot.frame = this.bounds;
|
|
309
|
-
// user corner radius to turn the layer into a circle
|
|
310
|
-
dot.cornerRadius = this.size / 2;
|
|
311
|
-
dot.backgroundColor = this.tintColor.CGColor;
|
|
312
|
-
dot.borderWidth = 4;
|
|
313
|
-
var whiteColor = new Color('#FFFFFF');
|
|
314
|
-
dot.borderColor = whiteColor.ios.CGColor;
|
|
315
|
-
if (!this.dot) {
|
|
316
|
-
this.layer.addSublayer(dot);
|
|
214
|
+
MGLMapViewDelegateImpl.prototype.mapViewTapOnCalloutForAnnotation = function (mapView, annotation) {
|
|
215
|
+
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
216
|
+
if (cachedMarker && cachedMarker.onCalloutTap) {
|
|
217
|
+
cachedMarker.onCalloutTap(cachedMarker);
|
|
317
218
|
}
|
|
318
|
-
|
|
319
|
-
|
|
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
|
+
}
|
|
320
235
|
}
|
|
321
|
-
// QUESTION: does GC catch this?
|
|
322
|
-
this.dot = dot;
|
|
323
236
|
};
|
|
324
237
|
/**
|
|
325
|
-
*
|
|
238
|
+
* override the standard location marker
|
|
326
239
|
*/
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
var dot = CALayer.layer();
|
|
331
|
-
dot.frame = this.bounds;
|
|
332
|
-
// user corner radius to turn the layer into a circle
|
|
333
|
-
dot.cornerRadius = this.size / 2;
|
|
334
|
-
dot.backgroundColor = this.tintColor.CGColor;
|
|
335
|
-
dot.borderWidth = 1;
|
|
336
|
-
var whiteColor = new Color('#FFFFFF');
|
|
337
|
-
dot.borderColor = whiteColor.ios.CGColor;
|
|
338
|
-
if (!this.dot) {
|
|
339
|
-
this.layer.addSublayer(dot);
|
|
240
|
+
MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
|
|
241
|
+
if (Trace.isEnabled()) {
|
|
242
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewViewForAnnotation() top');
|
|
340
243
|
}
|
|
341
|
-
|
|
342
|
-
this.
|
|
244
|
+
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
245
|
+
this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init();
|
|
246
|
+
return this.userLocationAnnotationView;
|
|
343
247
|
}
|
|
344
|
-
|
|
345
|
-
this.dot = dot;
|
|
248
|
+
return null;
|
|
346
249
|
};
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
CustomUserLocationAnnotationView.prototype.drawArrow = function () {
|
|
351
|
-
var arrow = CAShapeLayer.layer();
|
|
352
|
-
arrow.path = this.arrowPath();
|
|
353
|
-
arrow.frame = CGRectMake(0, 0, this.size / 2, this.size / 2);
|
|
354
|
-
arrow.position = CGPointMake(CGRectGetMidX(this.dot.frame), CGRectGetMidY(this.dot.frame));
|
|
355
|
-
arrow.fillColor = this.dot.borderColor;
|
|
356
|
-
if (!this.arrow) {
|
|
357
|
-
this.layer.addSublayer(arrow);
|
|
250
|
+
MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
|
|
251
|
+
if (Trace.isEnabled()) {
|
|
252
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionIsChanging()');
|
|
358
253
|
}
|
|
359
|
-
|
|
360
|
-
this.
|
|
254
|
+
if (this.cameraChangedListener) {
|
|
255
|
+
this.cameraChangedListener(reason);
|
|
361
256
|
}
|
|
362
|
-
// QUESTION: Does GC catch this?
|
|
363
|
-
this.arrow = arrow;
|
|
364
257
|
};
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
* @link https://docs.nativescript.org/core-concepts/ios-runtime/types/C-Functions
|
|
369
|
-
*/
|
|
370
|
-
CustomUserLocationAnnotationView.prototype.updateHeading = function () {
|
|
371
|
-
// just to avoid a possible race condition where the arrow isnt' drawn yet
|
|
372
|
-
if (!this.arrow) {
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
if (typeof this.userLocation == 'undefined') {
|
|
376
|
-
return;
|
|
258
|
+
MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
|
|
259
|
+
if (Trace.isEnabled()) {
|
|
260
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionDidChangeAnimated()');
|
|
377
261
|
}
|
|
378
|
-
if (
|
|
379
|
-
|
|
262
|
+
if (this.cameraChangedListener) {
|
|
263
|
+
this.cameraChangedListener(reason, animated);
|
|
380
264
|
}
|
|
381
|
-
if (
|
|
382
|
-
|
|
265
|
+
if (this.cameraIdledListener) {
|
|
266
|
+
this.cameraIdledListener();
|
|
383
267
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
//
|
|
389
|
-
// The original Objective-C example uses the inline C function MGLRadiansFromDegrees but because
|
|
390
|
-
// it's declared as inline it is not available for NativeScript. See linked article above.
|
|
391
|
-
// let rotation : number = MGLRadiansFromDegrees( this.mapView.direction - this.userLocation.heading.trueHeading );
|
|
392
|
-
var degrees = this.mapView.direction - this.userLocation.heading.trueHeading;
|
|
393
|
-
// in radians
|
|
394
|
-
var rotation = (degrees * Math.PI) / 180;
|
|
395
|
-
rotation = -rotation;
|
|
396
|
-
// if the difference would be perceptible, rotate the arrow.
|
|
397
|
-
if (fabs(rotation) > 0.01) {
|
|
398
|
-
// Disable implicit animations of this rotation, which reduces lag between updates
|
|
399
|
-
CATransaction.begin();
|
|
400
|
-
CATransaction.setDisableActions(true);
|
|
401
|
-
this.arrow.setAffineTransform(CGAffineTransformRotate(CGAffineTransformIdentity, rotation));
|
|
402
|
-
CATransaction.commit();
|
|
403
|
-
}
|
|
268
|
+
};
|
|
269
|
+
MGLMapViewDelegateImpl.prototype.mapViewDidUpdateUserLocation = function (mapView, userLocation) {
|
|
270
|
+
if (Trace.isEnabled()) {
|
|
271
|
+
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewDidUpdateUserLocation()');
|
|
404
272
|
}
|
|
405
|
-
|
|
406
|
-
this.
|
|
273
|
+
if (this.userLocationChangedListener) {
|
|
274
|
+
this.userLocationChangedListener(_getLocation(userLocation));
|
|
407
275
|
}
|
|
408
276
|
};
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
var
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
bezierPath.addLineToPoint(right);
|
|
424
|
-
bezierPath.addLineToPoint(top);
|
|
425
|
-
bezierPath.closePath();
|
|
426
|
-
return bezierPath.CGPath;
|
|
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;
|
|
427
291
|
};
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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);
|
|
434
347
|
if (Trace.isEnabled()) {
|
|
435
|
-
CLog(CLogTypes.info,
|
|
348
|
+
CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): top with state:', recognizer.state);
|
|
436
349
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
this.drawTrackingLocationMarker();
|
|
350
|
+
if (recognizer.state === UIGestureRecognizerState.Changed) {
|
|
351
|
+
this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
|
|
440
352
|
}
|
|
441
|
-
|
|
442
|
-
|
|
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);
|
|
443
361
|
}
|
|
444
362
|
};
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
exports.CustomUserLocationAnnotationView = CustomUserLocationAnnotationView;
|
|
448
|
-
export class Mapbox extends MapboxCommon {
|
|
449
|
-
constructor() {
|
|
450
|
-
super(...arguments);
|
|
451
|
-
this.eventCallbacks = {};
|
|
452
|
-
}
|
|
453
|
-
setMapboxViewInstance(mapboxViewInstance) {
|
|
454
|
-
this._mapboxViewInstance = mapboxViewInstance;
|
|
455
|
-
}
|
|
456
|
-
initEventHandlerShim(settings, mapboxNativeViewInstance) {
|
|
363
|
+
MapPanHandlerImpl.prototype.panBegin = function (recognizer) {
|
|
364
|
+
var panCoordinate = this.getCoordinates(recognizer);
|
|
457
365
|
if (Trace.isEnabled()) {
|
|
458
|
-
CLog(CLogTypes.info, '
|
|
366
|
+
CLog(CLogTypes.info, 'MapPanHandlerImpl::panBegin(): top with state:', recognizer.state);
|
|
459
367
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
onMapEvent(eventName, id, callback, nativeMapView) {
|
|
463
|
-
if (typeof this.eventCallbacks[eventName] == 'undefined') {
|
|
464
|
-
this.eventCallbacks[eventName] = [];
|
|
368
|
+
if (recognizer.state === UIGestureRecognizerState.Began) {
|
|
369
|
+
this.notifyListener(recognizer.state, panCoordinate.latitude, panCoordinate.longitude);
|
|
465
370
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
|
469
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';
|
|
414
|
+
let _markers = [];
|
|
415
|
+
const _markerIconDownloadCache = [];
|
|
416
|
+
const _setMapboxMapOptions = (mapView, settings) => {
|
|
417
|
+
mapView.logoView.hidden = settings.hideLogo;
|
|
418
|
+
mapView.attributionButton.hidden = settings.hideAttribution;
|
|
419
|
+
mapView.compassView.hidden = settings.hideCompass;
|
|
420
|
+
mapView.rotateEnabled = !settings.disableRotation;
|
|
421
|
+
mapView.scrollEnabled = !settings.disableScroll;
|
|
422
|
+
mapView.zoomEnabled = !settings.disableZoom;
|
|
423
|
+
mapView.allowsTilting = !settings.disableTilt;
|
|
424
|
+
if (settings.center && settings.center.lat && settings.center.lng) {
|
|
425
|
+
const centerCoordinate = CLLocationCoordinate2DMake(settings.center.lat, settings.center.lng);
|
|
426
|
+
mapView.setCenterCoordinateZoomLevelAnimated(centerCoordinate, settings.zoomLevel, false);
|
|
470
427
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
this.eventCallbacks[eventName] = this.eventCallbacks[eventName].filter((entry) => entry.id !== id);
|
|
428
|
+
else {
|
|
429
|
+
mapView.setZoomLevelAnimated(settings.zoomLevel, false);
|
|
476
430
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
this.queryRenderedFeatures({ point, layers: [eventListener.id] }, nativeMap)
|
|
484
|
-
.then((response) => {
|
|
485
|
-
if (response.length > 0) {
|
|
486
|
-
eventListener.callback(response);
|
|
487
|
-
}
|
|
488
|
-
})
|
|
489
|
-
.catch((err) => {
|
|
490
|
-
console.error('click error ', eventListener.id, err);
|
|
491
|
-
});
|
|
492
|
-
});
|
|
493
|
-
this.view && this.view.notify({ eventName: 'mapClick', object: this.view, point });
|
|
494
|
-
return false;
|
|
431
|
+
mapView.showsUserLocation = settings.showUserLocation;
|
|
432
|
+
mapView.autoresizingMask = 2 | 16;
|
|
433
|
+
};
|
|
434
|
+
const _getMapStyle = (input) => {
|
|
435
|
+
if (input.startsWith('mapbox://styles') || input.startsWith('http://') || input.startsWith('https://')) {
|
|
436
|
+
return NSURL.URLWithString(input);
|
|
495
437
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
if (Trace.isEnabled()) {
|
|
499
|
-
CLog(CLogTypes.info, 'No markers passed');
|
|
500
|
-
}
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
if (!Array.isArray(markers)) {
|
|
504
|
-
if (Trace.isEnabled()) {
|
|
505
|
-
CLog(CLogTypes.info, "markers must be passed as an Array: [{title: 'foo'}]");
|
|
506
|
-
}
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
510
|
-
_downloadMarkerImages(markers).then((updatedMarkers) => {
|
|
511
|
-
updatedMarkers.forEach((marker) => {
|
|
512
|
-
const lat = marker.lat;
|
|
513
|
-
const lng = marker.lng;
|
|
514
|
-
const point = MGLPointAnnotation.new();
|
|
515
|
-
point.coordinate = CLLocationCoordinate2DMake(lat, lng);
|
|
516
|
-
point.title = marker.title;
|
|
517
|
-
point.subtitle = marker.subtitle;
|
|
518
|
-
_markers.push(marker);
|
|
519
|
-
theMap.addAnnotation(point);
|
|
520
|
-
if (marker.selected) {
|
|
521
|
-
theMap.selectAnnotationAnimated(point, false);
|
|
522
|
-
}
|
|
523
|
-
marker.ios = point;
|
|
524
|
-
marker.update = (newSettings) => {
|
|
525
|
-
_markers.forEach((_marker) => {
|
|
526
|
-
if (marker.id === _marker.id) {
|
|
527
|
-
if (newSettings.onTap !== undefined) {
|
|
528
|
-
_marker.onTap = newSettings.onTap;
|
|
529
|
-
}
|
|
530
|
-
if (newSettings.onCalloutTap !== undefined) {
|
|
531
|
-
_marker.onCalloutTap = newSettings.onCalloutTap;
|
|
532
|
-
}
|
|
533
|
-
if (newSettings.title !== undefined) {
|
|
534
|
-
_marker.ios.title = _marker.title = newSettings.title;
|
|
535
|
-
}
|
|
536
|
-
if (newSettings.subtitle !== undefined) {
|
|
537
|
-
_marker.ios.subtitle = _marker.subtitle = newSettings.subtitle;
|
|
538
|
-
}
|
|
539
|
-
if (newSettings.lat && newSettings.lng) {
|
|
540
|
-
_marker.lat = newSettings.lat;
|
|
541
|
-
_marker.lng = newSettings.lng;
|
|
542
|
-
_marker.ios.coordinate = CLLocationCoordinate2DMake(newSettings.lat, newSettings.lng);
|
|
543
|
-
}
|
|
544
|
-
if (newSettings.selected) {
|
|
545
|
-
theMap.selectAnnotationAnimated(_marker.ios, false);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
});
|
|
549
|
-
};
|
|
550
|
-
});
|
|
551
|
-
});
|
|
438
|
+
else if (input.startsWith('~/')) {
|
|
439
|
+
return NSURL.URLWithString('file://' + path.join(knownFolders.currentApp().path, input.replace('~/', '')));
|
|
552
440
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
CLog(CLogTypes.info, 'show(): top with options:', options);
|
|
556
|
-
}
|
|
557
|
-
return new Promise((resolve, reject) => {
|
|
558
|
-
try {
|
|
559
|
-
const settings = Mapbox.merge(options, Mapbox.defaults);
|
|
560
|
-
if (settings.accessToken === undefined) {
|
|
561
|
-
reject("Please set the 'accessToken' parameter");
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
if (this._mapboxViewInstance) {
|
|
565
|
-
this._mapboxViewInstance.removeFromSuperview();
|
|
566
|
-
}
|
|
567
|
-
const view = UIApplication.sharedApplication.keyWindow.rootViewController.view, frameRect = view.frame, mapFrame = CGRectMake(settings.margins.left, settings.margins.top, frameRect.size.width - settings.margins.left - settings.margins.right, frameRect.size.height - settings.margins.top - settings.margins.bottom), styleURL = _getMapStyle(settings.style);
|
|
568
|
-
MGLAccountManager.accessToken = settings.accessToken;
|
|
569
|
-
this._mapboxViewInstance = MGLMapView.alloc().initWithFrameStyleURL(mapFrame, styleURL);
|
|
570
|
-
_setMapboxMapOptions(this._mapboxViewInstance, settings);
|
|
571
|
-
this._mapboxViewInstance.delegate = MGLMapViewDelegateImpl.new().initWithCallback((mapView) => {
|
|
572
|
-
resolve({
|
|
573
|
-
ios: mapView
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
_markers = [];
|
|
577
|
-
this._addMarkers(settings.markers);
|
|
578
|
-
setTimeout(() => {
|
|
579
|
-
view.addSubview(this._mapboxViewInstance);
|
|
580
|
-
}, 500);
|
|
581
|
-
}
|
|
582
|
-
catch (ex) {
|
|
583
|
-
if (Trace.isEnabled()) {
|
|
584
|
-
CLog(CLogTypes.info, 'Error in mapbox.show: ' + ex);
|
|
585
|
-
}
|
|
586
|
-
reject(ex);
|
|
587
|
-
}
|
|
588
|
-
});
|
|
441
|
+
else if (input === MapStyle.LIGHT) {
|
|
442
|
+
return MGLStyle.lightStyleURL;
|
|
589
443
|
}
|
|
590
|
-
|
|
591
|
-
return
|
|
592
|
-
try {
|
|
593
|
-
if (this._mapboxViewInstance) {
|
|
594
|
-
this._mapboxViewInstance.removeFromSuperview();
|
|
595
|
-
}
|
|
596
|
-
resolve();
|
|
597
|
-
}
|
|
598
|
-
catch (ex) {
|
|
599
|
-
if (Trace.isEnabled()) {
|
|
600
|
-
CLog(CLogTypes.info, 'Error in mapbox.hide: ' + ex);
|
|
601
|
-
}
|
|
602
|
-
reject(ex);
|
|
603
|
-
}
|
|
604
|
-
});
|
|
444
|
+
else if (input === MapStyle.DARK) {
|
|
445
|
+
return MGLStyle.darkStyleURL;
|
|
605
446
|
}
|
|
606
|
-
|
|
607
|
-
return
|
|
608
|
-
try {
|
|
609
|
-
if (this._mapboxViewInstance) {
|
|
610
|
-
const view = UIApplication.sharedApplication.keyWindow.rootViewController.view;
|
|
611
|
-
view.addSubview(this._mapboxViewInstance);
|
|
612
|
-
resolve();
|
|
613
|
-
}
|
|
614
|
-
else {
|
|
615
|
-
reject('No map found');
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
catch (ex) {
|
|
619
|
-
if (Trace.isEnabled()) {
|
|
620
|
-
CLog(CLogTypes.info, 'Error in mapbox.unhide: ' + ex);
|
|
621
|
-
}
|
|
622
|
-
reject(ex);
|
|
623
|
-
}
|
|
624
|
-
});
|
|
447
|
+
else if (input === MapStyle.OUTDOORS) {
|
|
448
|
+
return MGLStyle.outdoorsStyleURL;
|
|
625
449
|
}
|
|
626
|
-
|
|
627
|
-
return
|
|
628
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
629
|
-
if (theMap) {
|
|
630
|
-
theMap.removeFromSuperview();
|
|
631
|
-
theMap.delegate = null;
|
|
632
|
-
}
|
|
633
|
-
resolve();
|
|
634
|
-
});
|
|
450
|
+
else if (input === MapStyle.SATELLITE) {
|
|
451
|
+
return MGLStyle.satelliteStyleURL;
|
|
635
452
|
}
|
|
636
|
-
|
|
637
|
-
return
|
|
453
|
+
else if (input === MapStyle.SATELLITE_STREETS) {
|
|
454
|
+
return MGLStyle.satelliteStreetsStyleURL;
|
|
638
455
|
}
|
|
639
|
-
|
|
640
|
-
return
|
|
456
|
+
else if (input === MapStyle.TRAFFIC_DAY) {
|
|
457
|
+
return NSURL.URLWithString('mapbox://styles/mapbox/traffic-day-v2');
|
|
641
458
|
}
|
|
642
|
-
|
|
643
|
-
return
|
|
459
|
+
else if (input === MapStyle.TRAFFIC_NIGHT) {
|
|
460
|
+
return NSURL.URLWithString('mapbox://styles/mapbox/traffic-night-v2');
|
|
644
461
|
}
|
|
645
|
-
|
|
646
|
-
return
|
|
462
|
+
else {
|
|
463
|
+
return MGLStyle.streetsStyleURL;
|
|
647
464
|
}
|
|
648
|
-
|
|
649
|
-
|
|
465
|
+
};
|
|
466
|
+
function _getTrackingMode(input) {
|
|
467
|
+
return 0;
|
|
468
|
+
}
|
|
469
|
+
function _getLocation(loc) {
|
|
470
|
+
if (loc === null) {
|
|
471
|
+
return null;
|
|
650
472
|
}
|
|
651
|
-
|
|
652
|
-
return
|
|
473
|
+
else {
|
|
474
|
+
return {
|
|
475
|
+
location: {
|
|
476
|
+
lat: loc.coordinate.latitude,
|
|
477
|
+
lng: loc.coordinate.longitude
|
|
478
|
+
},
|
|
479
|
+
speed: loc.location ? loc.location.speed : 0
|
|
480
|
+
};
|
|
653
481
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
482
|
+
}
|
|
483
|
+
export function setLogLevel(level) {
|
|
484
|
+
let loggingLevel;
|
|
485
|
+
switch (level) {
|
|
486
|
+
case 'none':
|
|
487
|
+
loggingLevel = 0;
|
|
488
|
+
break;
|
|
489
|
+
case 'info':
|
|
490
|
+
loggingLevel = 1;
|
|
491
|
+
break;
|
|
492
|
+
case 'verbose':
|
|
493
|
+
case 'debug':
|
|
494
|
+
loggingLevel = 2;
|
|
495
|
+
break;
|
|
496
|
+
case 'error':
|
|
497
|
+
loggingLevel = 3;
|
|
498
|
+
break;
|
|
499
|
+
case 'fault':
|
|
500
|
+
loggingLevel = 4;
|
|
501
|
+
break;
|
|
674
502
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
resolve(img);
|
|
686
|
-
}
|
|
687
|
-
catch (ex) {
|
|
688
|
-
reject('Error during getImage: ' + ex);
|
|
689
|
-
if (Trace.isEnabled()) {
|
|
690
|
-
CLog(CLogTypes.info, 'Error in mapbox.getImage: ' + ex);
|
|
691
|
-
}
|
|
692
|
-
throw ex;
|
|
693
|
-
}
|
|
694
|
-
});
|
|
503
|
+
MGLLoggingConfiguration.sharedConfiguration.loggingLevel = loggingLevel;
|
|
504
|
+
}
|
|
505
|
+
export class MapboxView extends MapboxViewBase {
|
|
506
|
+
constructor() {
|
|
507
|
+
super(...arguments);
|
|
508
|
+
this.nativeMapView = null;
|
|
509
|
+
this.delegate = null;
|
|
510
|
+
this.settings = null;
|
|
511
|
+
this.initialized = false;
|
|
512
|
+
this.initCountHack = 50;
|
|
695
513
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
return;
|
|
702
|
-
}
|
|
703
|
-
if (!image.startsWith('res://')) {
|
|
704
|
-
const appPath = knownFolders.currentApp().path;
|
|
705
|
-
image = appPath + '/' + image.replace('~/', '');
|
|
706
|
-
}
|
|
707
|
-
const img = ImageSource.fromFileOrResourceSync(image);
|
|
708
|
-
try {
|
|
709
|
-
theMap.style.setImageForName(img.ios, imageId);
|
|
710
|
-
resolve();
|
|
711
|
-
}
|
|
712
|
-
catch (ex) {
|
|
713
|
-
reject('Error during addImage: ' + ex);
|
|
714
|
-
if (Trace.isEnabled()) {
|
|
715
|
-
CLog(CLogTypes.info, 'Error in mapbox.addImage: ' + ex);
|
|
716
|
-
}
|
|
717
|
-
throw ex;
|
|
718
|
-
}
|
|
719
|
-
});
|
|
514
|
+
setConfig(settings) {
|
|
515
|
+
if (Trace.isEnabled()) {
|
|
516
|
+
CLog(CLogTypes.info, 'setConfig(): settings:', settings);
|
|
517
|
+
}
|
|
518
|
+
this.settings = settings;
|
|
720
519
|
}
|
|
721
|
-
|
|
722
|
-
return
|
|
723
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
724
|
-
if (!theMap) {
|
|
725
|
-
reject('No map has been loaded');
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
728
|
-
try {
|
|
729
|
-
theMap.style.removeImageForName(imageId);
|
|
730
|
-
resolve();
|
|
731
|
-
}
|
|
732
|
-
catch (ex) {
|
|
733
|
-
reject('Error during removeImage: ' + ex);
|
|
734
|
-
if (Trace.isEnabled()) {
|
|
735
|
-
CLog(CLogTypes.info, 'Error in mapbox.removeImage: ' + ex);
|
|
736
|
-
}
|
|
737
|
-
throw ex;
|
|
738
|
-
}
|
|
739
|
-
});
|
|
520
|
+
getNativeMapView() {
|
|
521
|
+
return this.nativeMapView;
|
|
740
522
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
523
|
+
createNativeView() {
|
|
524
|
+
if (Trace.isEnabled()) {
|
|
525
|
+
CLog(CLogTypes.info, 'createNativeView(): top');
|
|
526
|
+
}
|
|
527
|
+
const v = super.createNativeView();
|
|
528
|
+
return v;
|
|
529
|
+
}
|
|
530
|
+
onLoaded() {
|
|
531
|
+
super.onLoaded();
|
|
532
|
+
if (Trace.isEnabled()) {
|
|
533
|
+
CLog(CLogTypes.info, 'initNativeView(): on - loaded');
|
|
534
|
+
}
|
|
535
|
+
if (this.telemetry === false) {
|
|
536
|
+
NSUserDefaults.standardUserDefaults.setBoolForKey(false, 'MGLMapboxMetricsEnabled');
|
|
537
|
+
}
|
|
538
|
+
if (!this.initialized) {
|
|
539
|
+
this.initMap();
|
|
540
|
+
this.initialized = true;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
initNativeView() {
|
|
544
|
+
super.initNativeView();
|
|
545
|
+
this.nativeView.owner = this;
|
|
546
|
+
}
|
|
547
|
+
async disposeNativeView() {
|
|
548
|
+
if (Trace.isEnabled()) {
|
|
549
|
+
CLog(CLogTypes.info, 'disposeNativeView(): top');
|
|
550
|
+
}
|
|
551
|
+
this.nativeView.owner = null;
|
|
552
|
+
await this.mapbox.destroy();
|
|
553
|
+
if (Trace.isEnabled()) {
|
|
554
|
+
CLog(CLogTypes.info, 'disposeNativeView(): after mapbox.destroy()');
|
|
555
|
+
}
|
|
556
|
+
super.disposeNativeView();
|
|
557
|
+
if (Trace.isEnabled()) {
|
|
558
|
+
CLog(CLogTypes.info, 'disposeNativeView(): bottom');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
getMapboxApi() {
|
|
562
|
+
return this.mapbox;
|
|
563
|
+
}
|
|
564
|
+
initMap() {
|
|
565
|
+
if (Trace.isEnabled()) {
|
|
566
|
+
CLog(CLogTypes.info, 'initMap() top with settings:', this.settings);
|
|
567
|
+
}
|
|
568
|
+
if (!this.settings && !this.config.accessToken) {
|
|
569
|
+
if (Trace.isEnabled()) {
|
|
570
|
+
CLog(CLogTypes.info, 'initMap() no access token. Race condition on XML property evaluation?');
|
|
747
571
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
CLog(CLogTypes.info, 'Error in mapbox.addMarkers: ' + ex);
|
|
751
|
-
}
|
|
752
|
-
reject(ex);
|
|
572
|
+
if (this.initCountHack > 50) {
|
|
573
|
+
return;
|
|
753
574
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
575
|
+
setTimeout(() => {
|
|
576
|
+
this.initMap();
|
|
577
|
+
}, 50);
|
|
578
|
+
this.initCountHack++;
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (!this.settings) {
|
|
582
|
+
this.settings = Mapbox.merge(this.config, Mapbox.defaults);
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
this.settings = Mapbox.merge(this.settings, Mapbox.defaults);
|
|
586
|
+
}
|
|
587
|
+
if (!this.nativeMapView) {
|
|
588
|
+
this.mapbox = new Mapbox(this);
|
|
589
|
+
if (Trace.isEnabled()) {
|
|
590
|
+
CLog(CLogTypes.info, 'initMap(): after new Mapbox()');
|
|
591
|
+
}
|
|
592
|
+
const drawMap = () => {
|
|
593
|
+
MGLAccountManager.accessToken = this.settings.accessToken;
|
|
594
|
+
this.nativeMapView = MGLMapView.alloc().initWithFrameStyleURL(CGRectMake(0, 0, this.nativeView.frame.size.width, this.nativeView.frame.size.height), _getMapStyle(this.settings.style));
|
|
595
|
+
this.nativeMapView.delegate = this.delegate = MGLMapViewDelegateImpl.new().initWithCallback(() => {
|
|
596
|
+
if (Trace.isEnabled()) {
|
|
597
|
+
CLog(CLogTypes.info, 'initMap(): MLMapViewDeleteImpl onMapReady callback');
|
|
764
598
|
}
|
|
599
|
+
this.mapbox.setMapboxViewInstance(this.nativeMapView);
|
|
600
|
+
this.mapbox.initEventHandlerShim(this.settings, this.nativeMapView);
|
|
601
|
+
this.notify({
|
|
602
|
+
eventName: MapboxViewBase.mapReadyEvent,
|
|
603
|
+
object: this,
|
|
604
|
+
map: this,
|
|
605
|
+
ios: this.nativeMapView
|
|
606
|
+
});
|
|
607
|
+
this.notify({
|
|
608
|
+
eventName: MapboxViewBase.locationPermissionGrantedEvent,
|
|
609
|
+
object: this,
|
|
610
|
+
map: this,
|
|
611
|
+
ios: this.nativeMapView
|
|
612
|
+
});
|
|
765
613
|
});
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
614
|
+
_setMapboxMapOptions(this.nativeMapView, this.settings);
|
|
615
|
+
_markers = [];
|
|
616
|
+
this.nativeView.addSubview(this.nativeMapView);
|
|
617
|
+
this.mapbox.setOnMoveBeginListener((data) => {
|
|
618
|
+
if (Trace.isEnabled()) {
|
|
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');
|
|
642
|
+
}
|
|
643
|
+
this.notify({
|
|
644
|
+
eventName: MapboxViewBase.scrollEvent,
|
|
645
|
+
object: this,
|
|
646
|
+
map: this,
|
|
647
|
+
ios: this.nativeMapView
|
|
648
|
+
});
|
|
649
|
+
}, this.nativeMapView);
|
|
650
|
+
};
|
|
651
|
+
setTimeout(drawMap, this.settings.delay ? this.settings.delay : 0);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
onLayout(left, top, right, bottom) {
|
|
655
|
+
super.onLayout(left, top, right, bottom);
|
|
656
|
+
if (this.nativeMapView) {
|
|
657
|
+
this.nativeMapView.layer.frame = this.ios.layer.bounds;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
[telemetryProperty.setNative](value) {
|
|
661
|
+
NSUserDefaults.standardUserDefaults.setBoolForKey(false, 'MGLMapboxMetricsEnabled');
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
var CustomUserLocationAnnotationView = /** @class */ (function (_super) {
|
|
665
|
+
__extends(CustomUserLocationAnnotationView, _super);
|
|
666
|
+
function CustomUserLocationAnnotationView() {
|
|
667
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* init
|
|
671
|
+
*
|
|
672
|
+
* @link https://docs.nativescript.org/core-concepts/ios-runtime/HelloWorld
|
|
673
|
+
*/
|
|
674
|
+
CustomUserLocationAnnotationView.prototype.init = function () {
|
|
675
|
+
this.size = 48;
|
|
676
|
+
_super.prototype.initWithFrame.call(this, CGRectMake(0, 0, this.size, this.size));
|
|
677
|
+
this.renderModeChanged = true;
|
|
678
|
+
this.userLocationRenderMode = 'NORMAL';
|
|
679
|
+
return this;
|
|
680
|
+
};
|
|
681
|
+
/**
|
|
682
|
+
* update
|
|
683
|
+
*
|
|
684
|
+
* The note from the Objective-C sample indicates this method may be called quite
|
|
685
|
+
* often so it needs to be kept lightweight.
|
|
686
|
+
*/
|
|
687
|
+
CustomUserLocationAnnotationView.prototype.update = function () {
|
|
688
|
+
if (CLLocationCoordinate2DIsValid(this.userLocation.coordinate)) {
|
|
689
|
+
// if it's the first time here, setup the layers that make up the
|
|
690
|
+
// location marker.
|
|
691
|
+
if (!this.dot) {
|
|
692
|
+
this.drawNonTrackingLocationMarker();
|
|
776
693
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
CLog(CLogTypes.info, 'Error in mapbox.removeMarkers: ' + ex);
|
|
780
|
-
}
|
|
781
|
-
reject(ex);
|
|
694
|
+
if (this.userLocationRenderMode === 'GPS') {
|
|
695
|
+
this.updateHeading();
|
|
782
696
|
}
|
|
783
|
-
}
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
/**
|
|
700
|
+
* Draw the GPS tracking arrow.
|
|
701
|
+
*
|
|
702
|
+
* @link https://docs.nativescript.org/ns-framework-modules/color
|
|
703
|
+
*/
|
|
704
|
+
CustomUserLocationAnnotationView.prototype.drawTrackingLocationMarker = function () {
|
|
705
|
+
if (Trace.isEnabled()) {
|
|
706
|
+
CLog(CLogTypes.info, 'CustomerUserLocationAnnotatinView::drawTrackingLocationMarker()');
|
|
707
|
+
}
|
|
708
|
+
this.drawTrackingDot();
|
|
709
|
+
this.drawArrow();
|
|
710
|
+
}; // end of setupLayers()
|
|
711
|
+
/**
|
|
712
|
+
* draw the non-tracking marker
|
|
713
|
+
*/
|
|
714
|
+
CustomUserLocationAnnotationView.prototype.drawNonTrackingLocationMarker = function () {
|
|
715
|
+
if (Trace.isEnabled()) {
|
|
716
|
+
CLog(CLogTypes.info, 'CustomerUserLocationAnnotatinView::drawNonTrackingLocationMarker()');
|
|
717
|
+
}
|
|
718
|
+
this.drawNonTrackingDot();
|
|
719
|
+
if (this.arrow) {
|
|
720
|
+
this.arrow.removeFromSuperlayer();
|
|
721
|
+
this.arrow = null;
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
/**
|
|
725
|
+
* draw the tracking dot.
|
|
726
|
+
*/
|
|
727
|
+
CustomUserLocationAnnotationView.prototype.drawTrackingDot = function () {
|
|
728
|
+
this.size = 48;
|
|
729
|
+
// we need to adjust the size of the bounds of the marker. The Tracking marker
|
|
730
|
+
// is larger than the non tracking marker.
|
|
731
|
+
this.bounds = CGRectMake(0, 0, this.size, this.size);
|
|
732
|
+
var dot = CALayer.layer();
|
|
733
|
+
dot.frame = this.bounds;
|
|
734
|
+
// user corner radius to turn the layer into a circle
|
|
735
|
+
dot.cornerRadius = this.size / 2;
|
|
736
|
+
dot.backgroundColor = this.tintColor.CGColor;
|
|
737
|
+
dot.borderWidth = 4;
|
|
738
|
+
var whiteColor = new Color('#FFFFFF');
|
|
739
|
+
dot.borderColor = whiteColor.ios.CGColor;
|
|
740
|
+
if (!this.dot) {
|
|
741
|
+
this.layer.addSublayer(dot);
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
this.layer.replaceSublayerWith(this.dot, dot);
|
|
745
|
+
}
|
|
746
|
+
// QUESTION: does GC catch this?
|
|
747
|
+
this.dot = dot;
|
|
748
|
+
};
|
|
749
|
+
/**
|
|
750
|
+
* draw the non-tracking dot.
|
|
751
|
+
*/
|
|
752
|
+
CustomUserLocationAnnotationView.prototype.drawNonTrackingDot = function () {
|
|
753
|
+
this.size = 24;
|
|
754
|
+
this.bounds = CGRectMake(0, 0, this.size, this.size);
|
|
755
|
+
var dot = CALayer.layer();
|
|
756
|
+
dot.frame = this.bounds;
|
|
757
|
+
// user corner radius to turn the layer into a circle
|
|
758
|
+
dot.cornerRadius = this.size / 2;
|
|
759
|
+
dot.backgroundColor = this.tintColor.CGColor;
|
|
760
|
+
dot.borderWidth = 1;
|
|
761
|
+
var whiteColor = new Color('#FFFFFF');
|
|
762
|
+
dot.borderColor = whiteColor.ios.CGColor;
|
|
763
|
+
if (!this.dot) {
|
|
764
|
+
this.layer.addSublayer(dot);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
this.layer.replaceSublayerWith(this.dot, dot);
|
|
768
|
+
}
|
|
769
|
+
// QUESTION: does GC catch this?
|
|
770
|
+
this.dot = dot;
|
|
771
|
+
};
|
|
772
|
+
/**
|
|
773
|
+
* draw an arrow
|
|
774
|
+
*/
|
|
775
|
+
CustomUserLocationAnnotationView.prototype.drawArrow = function () {
|
|
776
|
+
var arrow = CAShapeLayer.layer();
|
|
777
|
+
arrow.path = this.arrowPath();
|
|
778
|
+
arrow.frame = CGRectMake(0, 0, this.size / 2, this.size / 2);
|
|
779
|
+
arrow.position = CGPointMake(CGRectGetMidX(this.dot.frame), CGRectGetMidY(this.dot.frame));
|
|
780
|
+
arrow.fillColor = this.dot.borderColor;
|
|
781
|
+
if (!this.arrow) {
|
|
782
|
+
this.layer.addSublayer(arrow);
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
this.layer.replaceSublayerWith(this.arrow, arrow);
|
|
786
|
+
}
|
|
787
|
+
// QUESTION: Does GC catch this?
|
|
788
|
+
this.arrow = arrow;
|
|
789
|
+
};
|
|
790
|
+
/**
|
|
791
|
+
* update arrow heading
|
|
792
|
+
*
|
|
793
|
+
* @link https://docs.nativescript.org/core-concepts/ios-runtime/types/C-Functions
|
|
794
|
+
*/
|
|
795
|
+
CustomUserLocationAnnotationView.prototype.updateHeading = function () {
|
|
796
|
+
// just to avoid a possible race condition where the arrow isnt' drawn yet
|
|
797
|
+
if (!this.arrow) {
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
if (typeof this.userLocation == 'undefined') {
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
if (typeof this.userLocation.heading == 'undefined' || this.userLocation.heading === null) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
if (typeof this.userLocation.heading.trueHeading == 'undefined' || this.userLocation.heading.trueHeading === null) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
if (this.userLocation.heading.trueHeading > 0) {
|
|
810
|
+
this.arrow.hidden = false;
|
|
811
|
+
// get the difference between the map's current direction and the
|
|
812
|
+
// user's heading, then convert it from degrees to radians
|
|
813
|
+
//
|
|
814
|
+
// The original Objective-C example uses the inline C function MGLRadiansFromDegrees but because
|
|
815
|
+
// it's declared as inline it is not available for NativeScript. See linked article above.
|
|
816
|
+
// let rotation : number = MGLRadiansFromDegrees( this.mapView.direction - this.userLocation.heading.trueHeading );
|
|
817
|
+
var degrees = this.mapView.direction - this.userLocation.heading.trueHeading;
|
|
818
|
+
// in radians
|
|
819
|
+
var rotation = (degrees * Math.PI) / 180;
|
|
820
|
+
rotation = -rotation;
|
|
821
|
+
// if the difference would be perceptible, rotate the arrow.
|
|
822
|
+
if (fabs(rotation) > 0.01) {
|
|
823
|
+
// Disable implicit animations of this rotation, which reduces lag between updates
|
|
824
|
+
CATransaction.begin();
|
|
825
|
+
CATransaction.setDisableActions(true);
|
|
826
|
+
this.arrow.setAffineTransform(CGAffineTransformRotate(CGAffineTransformIdentity, rotation));
|
|
827
|
+
CATransaction.commit();
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
else {
|
|
831
|
+
this.arrow.hidden = true;
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
/**
|
|
835
|
+
* Calculate the vector path for an arrow
|
|
836
|
+
*/
|
|
837
|
+
CustomUserLocationAnnotationView.prototype.arrowPath = function () {
|
|
838
|
+
var max = this.size / 2;
|
|
839
|
+
var pad = 3;
|
|
840
|
+
var top = CGPointMake(max * 0.5, 0);
|
|
841
|
+
var left = CGPointMake(0 + pad, max - pad);
|
|
842
|
+
var right = CGPointMake(max - pad, max - pad);
|
|
843
|
+
var center = CGPointMake(max * 0.5, max * 0.6);
|
|
844
|
+
var bezierPath = UIBezierPath.bezierPath();
|
|
845
|
+
bezierPath.moveToPoint(top);
|
|
846
|
+
bezierPath.addLineToPoint(left);
|
|
847
|
+
bezierPath.addLineToPoint(center);
|
|
848
|
+
bezierPath.addLineToPoint(right);
|
|
849
|
+
bezierPath.addLineToPoint(top);
|
|
850
|
+
bezierPath.closePath();
|
|
851
|
+
return bezierPath.CGPath;
|
|
852
|
+
};
|
|
853
|
+
/**
|
|
854
|
+
* change Render mode
|
|
855
|
+
*
|
|
856
|
+
* @param {string} renderMode
|
|
857
|
+
*/
|
|
858
|
+
CustomUserLocationAnnotationView.prototype.changeUserLocationRenderMode = function (renderMode) {
|
|
859
|
+
if (Trace.isEnabled()) {
|
|
860
|
+
CLog(CLogTypes.info, "CustomUserLocationAnnotatinView::changeUserLocationRenderMode(): changing mode to '" + renderMode + "'");
|
|
861
|
+
}
|
|
862
|
+
this.userLocationRenderMode = renderMode;
|
|
863
|
+
if (renderMode === 'GPS') {
|
|
864
|
+
this.drawTrackingLocationMarker();
|
|
865
|
+
}
|
|
866
|
+
else {
|
|
867
|
+
this.drawNonTrackingLocationMarker();
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
return CustomUserLocationAnnotationView;
|
|
871
|
+
}(MGLUserLocationAnnotationView));
|
|
872
|
+
export class Mapbox extends MapboxCommon {
|
|
873
|
+
constructor() {
|
|
874
|
+
super(...arguments);
|
|
875
|
+
this.eventCallbacks = {};
|
|
784
876
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
try {
|
|
788
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
789
|
-
const animated = options.animated === undefined || options.animated;
|
|
790
|
-
const coordinate = CLLocationCoordinate2DMake(options.lat, options.lng);
|
|
791
|
-
theMap.setCenterCoordinateAnimated(coordinate, animated);
|
|
792
|
-
resolve();
|
|
793
|
-
}
|
|
794
|
-
catch (ex) {
|
|
795
|
-
if (Trace.isEnabled()) {
|
|
796
|
-
CLog(CLogTypes.info, 'Error in mapbox.setCenter: ' + ex);
|
|
797
|
-
}
|
|
798
|
-
reject(ex);
|
|
799
|
-
}
|
|
800
|
-
});
|
|
877
|
+
setMapboxViewInstance(mapboxViewInstance) {
|
|
878
|
+
this._mapboxViewInstance = mapboxViewInstance;
|
|
801
879
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
resolve({
|
|
808
|
-
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
|
-
});
|
|
880
|
+
initEventHandlerShim(settings, mapboxNativeViewInstance) {
|
|
881
|
+
if (Trace.isEnabled()) {
|
|
882
|
+
CLog(CLogTypes.info, 'Mapbox:initEventHandlerShim(): top');
|
|
883
|
+
}
|
|
884
|
+
this.setOnMapClickListener((point) => this.checkForClickEvent(point), mapboxNativeViewInstance);
|
|
819
885
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
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
|
-
}
|
|
886
|
+
onMapEvent(eventName, id, callback, nativeMapView) {
|
|
887
|
+
if (typeof this.eventCallbacks[eventName] == 'undefined') {
|
|
888
|
+
this.eventCallbacks[eventName] = [];
|
|
889
|
+
}
|
|
890
|
+
this.eventCallbacks[eventName].push({
|
|
891
|
+
id,
|
|
892
|
+
callback
|
|
840
893
|
});
|
|
841
894
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
}
|
|
848
|
-
catch (ex) {
|
|
849
|
-
if (Trace.isEnabled()) {
|
|
850
|
-
CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
|
|
851
|
-
}
|
|
852
|
-
reject(ex);
|
|
853
|
-
}
|
|
854
|
-
});
|
|
895
|
+
offMapEvent(eventName, id, nativeMapView) {
|
|
896
|
+
if (typeof this.eventCallbacks[eventName] == 'undefined') {
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
this.eventCallbacks[eventName] = this.eventCallbacks[eventName].filter((entry) => entry.id !== id);
|
|
855
900
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
});
|
|
901
|
+
checkForClickEvent(point, nativeMap) {
|
|
902
|
+
if (Trace.isEnabled()) {
|
|
903
|
+
CLog(CLogTypes.info, 'Mapbox:checkForClickEvent(): got click event with point:', point);
|
|
904
|
+
}
|
|
905
|
+
this.eventCallbacks['click'] &&
|
|
906
|
+
this.eventCallbacks['click'].forEach((eventListener) => {
|
|
907
|
+
this.queryRenderedFeatures({ point, layers: [eventListener.id] }, nativeMap)
|
|
908
|
+
.then((response) => {
|
|
909
|
+
if (response.length > 0) {
|
|
910
|
+
eventListener.callback(response);
|
|
911
|
+
}
|
|
912
|
+
})
|
|
913
|
+
.catch((err) => {
|
|
914
|
+
console.error('click error ', eventListener.id, err);
|
|
915
|
+
});
|
|
916
|
+
});
|
|
917
|
+
this.view && this.view.notify({ eventName: 'mapClick', object: this.view, point });
|
|
918
|
+
return false;
|
|
875
919
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
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);
|
|
920
|
+
_addMarkers(markers, nativeMap) {
|
|
921
|
+
if (!markers) {
|
|
922
|
+
if (Trace.isEnabled()) {
|
|
923
|
+
CLog(CLogTypes.info, 'No markers passed');
|
|
887
924
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
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
|
-
}
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
if (!Array.isArray(markers)) {
|
|
928
|
+
if (Trace.isEnabled()) {
|
|
929
|
+
CLog(CLogTypes.info, "markers must be passed as an Array: [{title: 'foo'}]");
|
|
901
930
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
934
|
+
_downloadMarkerImages(markers).then((updatedMarkers) => {
|
|
935
|
+
updatedMarkers.forEach((marker) => {
|
|
936
|
+
const lat = marker.lat;
|
|
937
|
+
const lng = marker.lng;
|
|
938
|
+
const point = MGLPointAnnotation.new();
|
|
939
|
+
point.coordinate = CLLocationCoordinate2DMake(lat, lng);
|
|
940
|
+
point.title = marker.title;
|
|
941
|
+
point.subtitle = marker.subtitle;
|
|
942
|
+
_markers.push(marker);
|
|
943
|
+
theMap.addAnnotation(point);
|
|
944
|
+
if (marker.selected) {
|
|
945
|
+
theMap.selectAnnotationAnimated(point, false);
|
|
905
946
|
}
|
|
906
|
-
|
|
907
|
-
|
|
947
|
+
marker.ios = point;
|
|
948
|
+
marker.update = (newSettings) => {
|
|
949
|
+
_markers.forEach((_marker) => {
|
|
950
|
+
if (marker.id === _marker.id) {
|
|
951
|
+
if (newSettings.onTap !== undefined) {
|
|
952
|
+
_marker.onTap = newSettings.onTap;
|
|
953
|
+
}
|
|
954
|
+
if (newSettings.onCalloutTap !== undefined) {
|
|
955
|
+
_marker.onCalloutTap = newSettings.onCalloutTap;
|
|
956
|
+
}
|
|
957
|
+
if (newSettings.title !== undefined) {
|
|
958
|
+
_marker.ios.title = _marker.title = newSettings.title;
|
|
959
|
+
}
|
|
960
|
+
if (newSettings.subtitle !== undefined) {
|
|
961
|
+
_marker.ios.subtitle = _marker.subtitle = newSettings.subtitle;
|
|
962
|
+
}
|
|
963
|
+
if (newSettings.lat && newSettings.lng) {
|
|
964
|
+
_marker.lat = newSettings.lat;
|
|
965
|
+
_marker.lng = newSettings.lng;
|
|
966
|
+
_marker.ios.coordinate = CLLocationCoordinate2DMake(newSettings.lat, newSettings.lng);
|
|
967
|
+
}
|
|
968
|
+
if (newSettings.selected) {
|
|
969
|
+
theMap.selectAnnotationAnimated(_marker.ios, false);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
};
|
|
974
|
+
});
|
|
908
975
|
});
|
|
909
976
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
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';
|
|
977
|
+
show(options) {
|
|
978
|
+
if (Trace.isEnabled()) {
|
|
979
|
+
CLog(CLogTypes.info, 'show(): top with options:', options);
|
|
943
980
|
}
|
|
944
|
-
}
|
|
945
|
-
showUserLocationMarker(options, nativeMap) {
|
|
946
981
|
return new Promise((resolve, reject) => {
|
|
947
982
|
try {
|
|
948
|
-
const
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
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);
|
|
983
|
+
const settings = Mapbox.merge(options, Mapbox.defaults);
|
|
984
|
+
if (settings.accessToken === undefined) {
|
|
985
|
+
reject("Please set the 'accessToken' parameter");
|
|
986
|
+
return;
|
|
957
987
|
}
|
|
958
|
-
|
|
988
|
+
if (this._mapboxViewInstance) {
|
|
989
|
+
this._mapboxViewInstance.removeFromSuperview();
|
|
990
|
+
}
|
|
991
|
+
const view = UIApplication.sharedApplication.keyWindow.rootViewController.view, frameRect = view.frame, mapFrame = CGRectMake(settings.margins.left, settings.margins.top, frameRect.size.width - settings.margins.left - settings.margins.right, frameRect.size.height - settings.margins.top - settings.margins.bottom), styleURL = _getMapStyle(settings.style);
|
|
992
|
+
MGLAccountManager.accessToken = settings.accessToken;
|
|
993
|
+
this._mapboxViewInstance = MGLMapView.alloc().initWithFrameStyleURL(mapFrame, styleURL);
|
|
994
|
+
_setMapboxMapOptions(this._mapboxViewInstance, settings);
|
|
995
|
+
this._mapboxViewInstance.delegate = MGLMapViewDelegateImpl.new().initWithCallback((mapView) => {
|
|
996
|
+
resolve({
|
|
997
|
+
ios: mapView
|
|
998
|
+
});
|
|
999
|
+
});
|
|
1000
|
+
_markers = [];
|
|
1001
|
+
this._addMarkers(settings.markers);
|
|
1002
|
+
setTimeout(() => {
|
|
1003
|
+
view.addSubview(this._mapboxViewInstance);
|
|
1004
|
+
}, 500);
|
|
959
1005
|
}
|
|
960
1006
|
catch (ex) {
|
|
961
1007
|
if (Trace.isEnabled()) {
|
|
962
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1008
|
+
CLog(CLogTypes.info, 'Error in mapbox.show: ' + ex);
|
|
963
1009
|
}
|
|
964
1010
|
reject(ex);
|
|
965
1011
|
}
|
|
966
1012
|
});
|
|
967
1013
|
}
|
|
968
|
-
|
|
1014
|
+
hide() {
|
|
969
1015
|
return new Promise((resolve, reject) => {
|
|
970
1016
|
try {
|
|
1017
|
+
if (this._mapboxViewInstance) {
|
|
1018
|
+
this._mapboxViewInstance.removeFromSuperview();
|
|
1019
|
+
}
|
|
971
1020
|
resolve();
|
|
972
1021
|
}
|
|
973
1022
|
catch (ex) {
|
|
974
1023
|
if (Trace.isEnabled()) {
|
|
975
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1024
|
+
CLog(CLogTypes.info, 'Error in mapbox.hide: ' + ex);
|
|
976
1025
|
}
|
|
977
1026
|
reject(ex);
|
|
978
1027
|
}
|
|
979
1028
|
});
|
|
980
1029
|
}
|
|
981
|
-
|
|
1030
|
+
unhide() {
|
|
982
1031
|
return new Promise((resolve, reject) => {
|
|
983
1032
|
try {
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1033
|
+
if (this._mapboxViewInstance) {
|
|
1034
|
+
const view = UIApplication.sharedApplication.keyWindow.rootViewController.view;
|
|
1035
|
+
view.addSubview(this._mapboxViewInstance);
|
|
1036
|
+
resolve();
|
|
1037
|
+
}
|
|
1038
|
+
else {
|
|
1039
|
+
reject('No map found');
|
|
987
1040
|
}
|
|
988
|
-
theMap.userTrackingMode = this._stringToCameraMode(cameraModeString);
|
|
989
|
-
const delegate = theMap.delegate;
|
|
990
|
-
const renderMode = this._stringToRenderMode(renderModeString);
|
|
991
|
-
delegate.changeUserLocationRenderMode(renderMode);
|
|
992
1041
|
}
|
|
993
1042
|
catch (ex) {
|
|
994
1043
|
if (Trace.isEnabled()) {
|
|
995
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1044
|
+
CLog(CLogTypes.info, 'Error in mapbox.unhide: ' + ex);
|
|
996
1045
|
}
|
|
997
1046
|
reject(ex);
|
|
998
1047
|
}
|
|
999
1048
|
});
|
|
1000
1049
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1050
|
+
destroy(nativeMap) {
|
|
1051
|
+
return new Promise((resolve, reject) => {
|
|
1052
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1053
|
+
if (theMap) {
|
|
1054
|
+
theMap.removeFromSuperview();
|
|
1055
|
+
theMap.delegate = null;
|
|
1056
|
+
}
|
|
1057
|
+
resolve();
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
onStart(nativeMap) {
|
|
1061
|
+
return Promise.resolve();
|
|
1062
|
+
}
|
|
1063
|
+
onResume(nativeMap) {
|
|
1064
|
+
return Promise.resolve();
|
|
1065
|
+
}
|
|
1066
|
+
onPause(nativeMap) {
|
|
1067
|
+
return Promise.resolve();
|
|
1068
|
+
}
|
|
1069
|
+
onStop(nativeMap) {
|
|
1070
|
+
return Promise.resolve();
|
|
1071
|
+
}
|
|
1072
|
+
onLowMemory(nativeMap) {
|
|
1073
|
+
return Promise.resolve();
|
|
1074
|
+
}
|
|
1075
|
+
onDestroy(nativeMap) {
|
|
1076
|
+
return Promise.resolve();
|
|
1077
|
+
}
|
|
1078
|
+
setMapStyle(style, nativeMap) {
|
|
1003
1079
|
return new Promise((resolve, reject) => {
|
|
1004
1080
|
try {
|
|
1005
1081
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
}
|
|
1013
|
-
|
|
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);
|
|
1082
|
+
const delegate = theMap.delegate;
|
|
1083
|
+
delegate.setStyleLoadedCallback((mapView) => {
|
|
1084
|
+
if (Trace.isEnabled()) {
|
|
1085
|
+
CLog(CLogTypes.info, 'Mapbox:setMapStyle(): style loaded callback returned.');
|
|
1086
|
+
}
|
|
1087
|
+
resolve();
|
|
1088
|
+
});
|
|
1089
|
+
theMap.styleURL = _getMapStyle(style);
|
|
1024
1090
|
}
|
|
1025
1091
|
catch (ex) {
|
|
1026
1092
|
if (Trace.isEnabled()) {
|
|
1027
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1093
|
+
CLog(CLogTypes.info, 'Error in mapbox.setMapStyle: ' + ex);
|
|
1028
1094
|
}
|
|
1029
1095
|
reject(ex);
|
|
1030
1096
|
}
|
|
1031
1097
|
});
|
|
1032
1098
|
}
|
|
1033
|
-
|
|
1099
|
+
async getImage(imageId, nativeMap) {
|
|
1034
1100
|
return new Promise((resolve, reject) => {
|
|
1101
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1102
|
+
if (!theMap) {
|
|
1103
|
+
reject('No map has been loaded');
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1035
1106
|
try {
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
|
|
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);
|
|
1107
|
+
const nativeImage = theMap.style.imageForName(imageId);
|
|
1108
|
+
const img = new ImageSource(nativeImage);
|
|
1109
|
+
resolve(img);
|
|
1066
1110
|
}
|
|
1067
1111
|
catch (ex) {
|
|
1112
|
+
reject('Error during getImage: ' + ex);
|
|
1068
1113
|
if (Trace.isEnabled()) {
|
|
1069
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1114
|
+
CLog(CLogTypes.info, 'Error in mapbox.getImage: ' + ex);
|
|
1070
1115
|
}
|
|
1071
|
-
|
|
1116
|
+
throw ex;
|
|
1072
1117
|
}
|
|
1073
1118
|
});
|
|
1074
1119
|
}
|
|
1075
|
-
|
|
1120
|
+
async addImage(imageId, image, nativeMap) {
|
|
1076
1121
|
return new Promise((resolve, reject) => {
|
|
1077
1122
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
reject("Please set the 'points' parameter");
|
|
1123
|
+
if (!theMap) {
|
|
1124
|
+
reject('No map has been loaded');
|
|
1081
1125
|
return;
|
|
1082
1126
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
if (theMap.style.sourceWithIdentifier(polygonID)) {
|
|
1087
|
-
reject("Remove the polygon with this id first with 'removePolygons': " + polygonID);
|
|
1088
|
-
return;
|
|
1127
|
+
if (!image.startsWith('res://')) {
|
|
1128
|
+
const appPath = knownFolders.currentApp().path;
|
|
1129
|
+
image = appPath + '/' + image.replace('~/', '');
|
|
1089
1130
|
}
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
"type": "Polygon",
|
|
1100
|
-
"coordinates": [${JSON.stringify(coordinateArray)}]
|
|
1101
|
-
}
|
|
1131
|
+
const img = ImageSource.fromFileOrResourceSync(image);
|
|
1132
|
+
try {
|
|
1133
|
+
theMap.style.setImageForName(img.ios, imageId);
|
|
1134
|
+
resolve();
|
|
1135
|
+
}
|
|
1136
|
+
catch (ex) {
|
|
1137
|
+
reject('Error during addImage: ' + ex);
|
|
1138
|
+
if (Trace.isEnabled()) {
|
|
1139
|
+
CLog(CLogTypes.info, 'Error in mapbox.addImage: ' + ex);
|
|
1102
1140
|
}
|
|
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);
|
|
1141
|
+
throw ex;
|
|
1118
1142
|
}
|
|
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
1143
|
});
|
|
1125
1144
|
}
|
|
1126
|
-
|
|
1145
|
+
async removeImage(imageId, nativeMap) {
|
|
1127
1146
|
return new Promise((resolve, reject) => {
|
|
1128
1147
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
reject("Please set the 'points' parameter");
|
|
1148
|
+
if (!theMap) {
|
|
1149
|
+
reject('No map has been loaded');
|
|
1132
1150
|
return;
|
|
1133
1151
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1152
|
+
try {
|
|
1153
|
+
theMap.style.removeImageForName(imageId);
|
|
1154
|
+
resolve();
|
|
1155
|
+
}
|
|
1156
|
+
catch (ex) {
|
|
1157
|
+
reject('Error during removeImage: ' + ex);
|
|
1158
|
+
if (Trace.isEnabled()) {
|
|
1159
|
+
CLog(CLogTypes.info, 'Error in mapbox.removeImage: ' + ex);
|
|
1160
|
+
}
|
|
1161
|
+
throw ex;
|
|
1140
1162
|
}
|
|
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
1163
|
});
|
|
1177
1164
|
}
|
|
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) {
|
|
1165
|
+
addMarkers(markers, nativeMap) {
|
|
1185
1166
|
return new Promise((resolve, reject) => {
|
|
1186
1167
|
try {
|
|
1187
1168
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
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);
|
|
1169
|
+
this._addMarkers(markers, theMap);
|
|
1170
|
+
resolve();
|
|
1171
|
+
}
|
|
1172
|
+
catch (ex) {
|
|
1173
|
+
if (Trace.isEnabled()) {
|
|
1174
|
+
CLog(CLogTypes.info, 'Error in mapbox.addMarkers: ' + ex);
|
|
1202
1175
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1176
|
+
reject(ex);
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
removeMarkers(ids, nativeMap) {
|
|
1181
|
+
return new Promise((resolve, reject) => {
|
|
1182
|
+
try {
|
|
1183
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1184
|
+
const markersToRemove = [];
|
|
1185
|
+
_markers.forEach((marker) => {
|
|
1186
|
+
if (!ids || (marker.id && ids.indexOf(marker.id) > -1)) {
|
|
1187
|
+
markersToRemove.push(marker.ios);
|
|
1208
1188
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1189
|
+
});
|
|
1190
|
+
if (ids) {
|
|
1191
|
+
_markers = _markers.filter((marker) => ids.indexOf(marker.id) < 0);
|
|
1211
1192
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1193
|
+
else {
|
|
1194
|
+
_markers = [];
|
|
1214
1195
|
}
|
|
1215
|
-
if (
|
|
1216
|
-
|
|
1196
|
+
if (markersToRemove.length > 0) {
|
|
1197
|
+
theMap.removeAnnotations(markersToRemove);
|
|
1217
1198
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1199
|
+
resolve();
|
|
1200
|
+
}
|
|
1201
|
+
catch (ex) {
|
|
1202
|
+
if (Trace.isEnabled()) {
|
|
1203
|
+
CLog(CLogTypes.info, 'Error in mapbox.removeMarkers: ' + ex);
|
|
1220
1204
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1205
|
+
reject(ex);
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
setCenter(options, nativeMap) {
|
|
1210
|
+
return new Promise((resolve, reject) => {
|
|
1211
|
+
try {
|
|
1212
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1213
|
+
const animated = options.animated === undefined || options.animated;
|
|
1214
|
+
const coordinate = CLLocationCoordinate2DMake(options.lat, options.lng);
|
|
1215
|
+
theMap.setCenterCoordinateAnimated(coordinate, animated);
|
|
1216
|
+
resolve();
|
|
1217
|
+
}
|
|
1218
|
+
catch (ex) {
|
|
1219
|
+
if (Trace.isEnabled()) {
|
|
1220
|
+
CLog(CLogTypes.info, 'Error in mapbox.setCenter: ' + ex);
|
|
1223
1221
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1222
|
+
reject(ex);
|
|
1223
|
+
}
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
getCenter(nativeMap) {
|
|
1227
|
+
return new Promise((resolve, reject) => {
|
|
1228
|
+
try {
|
|
1229
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1230
|
+
const coordinate = theMap.centerCoordinate;
|
|
1231
|
+
resolve({
|
|
1232
|
+
lat: coordinate.latitude,
|
|
1233
|
+
lng: coordinate.longitude
|
|
1234
|
+
});
|
|
1229
1235
|
}
|
|
1230
1236
|
catch (ex) {
|
|
1231
1237
|
if (Trace.isEnabled()) {
|
|
1232
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1238
|
+
CLog(CLogTypes.info, 'Error in mapbox.getCenter: ' + ex);
|
|
1233
1239
|
}
|
|
1234
1240
|
reject(ex);
|
|
1235
1241
|
}
|
|
1236
1242
|
});
|
|
1237
1243
|
}
|
|
1238
|
-
|
|
1244
|
+
setZoomLevel(options, nativeMap) {
|
|
1239
1245
|
return new Promise((resolve, reject) => {
|
|
1240
1246
|
try {
|
|
1241
1247
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
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();
|
|
1245
1253
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
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
|
-
}
|
|
1254
|
+
else {
|
|
1255
|
+
reject('invalid ZoomLevel, use any double value from 0 to 20 (like 8.3)');
|
|
1253
1256
|
}
|
|
1254
|
-
theMap.addGestureRecognizer(tapGestureRecognizer);
|
|
1255
|
-
resolve();
|
|
1256
1257
|
}
|
|
1257
1258
|
catch (ex) {
|
|
1258
1259
|
if (Trace.isEnabled()) {
|
|
1259
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1260
|
+
CLog(CLogTypes.info, 'Error in mapbox.setZoomLevel: ' + ex);
|
|
1260
1261
|
}
|
|
1261
1262
|
reject(ex);
|
|
1262
1263
|
}
|
|
1263
1264
|
});
|
|
1264
1265
|
}
|
|
1265
|
-
|
|
1266
|
+
getZoomLevel(nativeMap) {
|
|
1266
1267
|
return new Promise((resolve, reject) => {
|
|
1267
1268
|
try {
|
|
1268
1269
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1270
|
+
resolve(theMap.zoomLevel);
|
|
1271
|
+
}
|
|
1272
|
+
catch (ex) {
|
|
1273
|
+
if (Trace.isEnabled()) {
|
|
1274
|
+
CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
|
|
1272
1275
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1276
|
+
reject(ex);
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
setTilt(options, nativeMap) {
|
|
1281
|
+
return new Promise((resolve, reject) => {
|
|
1282
|
+
try {
|
|
1283
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1284
|
+
const cam = theMap.camera;
|
|
1285
|
+
cam.pitch = options.tilt;
|
|
1286
|
+
const durationMs = options.duration ? options.duration : 5000;
|
|
1287
|
+
theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
|
|
1288
|
+
setTimeout(() => {
|
|
1289
|
+
resolve();
|
|
1290
|
+
}, durationMs);
|
|
1291
|
+
}
|
|
1292
|
+
catch (ex) {
|
|
1293
|
+
if (Trace.isEnabled()) {
|
|
1294
|
+
CLog(CLogTypes.info, 'Error in mapbox.setTilt: ' + ex);
|
|
1280
1295
|
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1296
|
+
reject(ex);
|
|
1297
|
+
}
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
getTilt(nativeMap) {
|
|
1301
|
+
return new Promise((resolve, reject) => {
|
|
1302
|
+
try {
|
|
1303
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1304
|
+
resolve(theMap.camera.pitch);
|
|
1283
1305
|
}
|
|
1284
1306
|
catch (ex) {
|
|
1285
1307
|
if (Trace.isEnabled()) {
|
|
1286
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1308
|
+
CLog(CLogTypes.info, 'Error in mapbox.getTilt: ' + ex);
|
|
1287
1309
|
}
|
|
1288
1310
|
reject(ex);
|
|
1289
1311
|
}
|
|
1290
1312
|
});
|
|
1291
1313
|
}
|
|
1292
|
-
|
|
1314
|
+
getUserLocation(nativeMap) {
|
|
1293
1315
|
return new Promise((resolve, reject) => {
|
|
1294
1316
|
try {
|
|
1295
1317
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1318
|
+
const loc = theMap.userLocation;
|
|
1319
|
+
if (loc === null) {
|
|
1320
|
+
reject('Location not available');
|
|
1299
1321
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1303
|
-
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1304
|
-
recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
|
|
1305
|
-
break;
|
|
1306
|
-
}
|
|
1322
|
+
else {
|
|
1323
|
+
resolve(_getLocation(loc));
|
|
1307
1324
|
}
|
|
1308
|
-
resolve();
|
|
1309
1325
|
}
|
|
1310
1326
|
catch (ex) {
|
|
1311
1327
|
if (Trace.isEnabled()) {
|
|
1312
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1328
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1313
1329
|
}
|
|
1314
1330
|
reject(ex);
|
|
1315
1331
|
}
|
|
1316
1332
|
});
|
|
1317
1333
|
}
|
|
1318
|
-
|
|
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) {
|
|
1319
1370
|
return new Promise((resolve, reject) => {
|
|
1320
1371
|
try {
|
|
1321
1372
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
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);
|
|
1325
1381
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
recognizer.addTargetAction(theMap['mapOnMoveBeginHandler'], 'pan');
|
|
1332
|
-
break;
|
|
1333
|
-
}
|
|
1382
|
+
resolve();
|
|
1383
|
+
}
|
|
1384
|
+
catch (ex) {
|
|
1385
|
+
if (Trace.isEnabled()) {
|
|
1386
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1334
1387
|
}
|
|
1388
|
+
reject(ex);
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
hideUserLocationMarker(nativeMap) {
|
|
1393
|
+
return new Promise((resolve, reject) => {
|
|
1394
|
+
try {
|
|
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 ? ExpressionParser.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 ? ExpressionParser.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) {
|
|
1500
|
+
return new Promise((resolve, reject) => {
|
|
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
|
+
}
|
|
1526
|
+
}
|
|
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;
|
|
1557
|
+
}
|
|
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;
|
|
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();
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
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) {
|
|
1489
1609
|
return new Promise((resolve, reject) => {
|
|
1490
1610
|
try {
|
|
1491
|
-
const
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
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);
|
|
1495
1626
|
}
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
minZoom: region.minimumZoomLevel,
|
|
1505
|
-
maxZoom: region.maximumZoomLevel,
|
|
1506
|
-
bounds: {
|
|
1507
|
-
north: region.bounds.ne.latitude,
|
|
1508
|
-
east: region.bounds.ne.longitude,
|
|
1509
|
-
south: region.bounds.sw.latitude,
|
|
1510
|
-
west: region.bounds.sw.longitude
|
|
1511
|
-
}
|
|
1512
|
-
});
|
|
1627
|
+
else {
|
|
1628
|
+
const target = options.target;
|
|
1629
|
+
if (target === undefined) {
|
|
1630
|
+
reject("Please set the 'target' parameter");
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
cam = theMap.camera;
|
|
1634
|
+
cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
|
|
1513
1635
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
catch (ex) {
|
|
1517
|
-
if (Trace.isEnabled()) {
|
|
1518
|
-
CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
|
|
1636
|
+
if (options.altitude) {
|
|
1637
|
+
cam.altitude = options.altitude;
|
|
1519
1638
|
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
});
|
|
1523
|
-
}
|
|
1524
|
-
deleteOfflineRegion(options) {
|
|
1525
|
-
return new Promise((resolve, reject) => {
|
|
1526
|
-
try {
|
|
1527
|
-
if (!options || !options.name) {
|
|
1528
|
-
reject("Pass in the 'name' param");
|
|
1529
|
-
return;
|
|
1639
|
+
if (options.bearing) {
|
|
1640
|
+
cam.heading = options.bearing;
|
|
1530
1641
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
for (let i = 0; i < packs.count; i++) {
|
|
1534
|
-
const pack = packs.objectAtIndex(i);
|
|
1535
|
-
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
|
|
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
|
-
});
|
|
1547
|
-
}
|
|
1642
|
+
if (options.tilt) {
|
|
1643
|
+
cam.pitch = options.tilt;
|
|
1548
1644
|
}
|
|
1549
|
-
if (
|
|
1550
|
-
|
|
1645
|
+
if (options.zoomLevel && options.target) {
|
|
1646
|
+
cam.altitude = MGLAltitudeForZoomLevel(options.zoomLevel, cam.pitch, options.target.lat, theMap.frame.size);
|
|
1551
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,26 @@ 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
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1673
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1674
|
+
if (recognizer instanceof UITapGestureRecognizer) {
|
|
1675
|
+
tapGestureRecognizer.requireGestureRecognizerToFail(recognizer);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
theMap.addGestureRecognizer(tapGestureRecognizer);
|
|
1569
1679
|
resolve();
|
|
1570
1680
|
}
|
|
1571
1681
|
catch (ex) {
|
|
1572
1682
|
if (Trace.isEnabled()) {
|
|
1573
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1683
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
|
|
1574
1684
|
}
|
|
1575
1685
|
reject(ex);
|
|
1576
1686
|
}
|
|
1577
1687
|
});
|
|
1578
1688
|
}
|
|
1579
|
-
|
|
1689
|
+
setOnMapLongClickListener(listener, nativeMap) {
|
|
1580
1690
|
return new Promise((resolve, reject) => {
|
|
1581
1691
|
try {
|
|
1582
1692
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1584,159 +1694,57 @@ export class Mapbox extends MapboxCommon {
|
|
|
1584
1694
|
reject('No map has been loaded');
|
|
1585
1695
|
return;
|
|
1586
1696
|
}
|
|
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;
|
|
1697
|
+
theMap['mapLongPressHandler'] = MapLongPressHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
|
|
1698
|
+
const longPressGestureRecognizer = UILongPressGestureRecognizer.alloc().initWithTargetAction(theMap['mapLongPressHandler'], 'longPress');
|
|
1699
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1700
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1701
|
+
if (recognizer instanceof UILongPressGestureRecognizer) {
|
|
1702
|
+
longPressGestureRecognizer.requireGestureRecognizerToFail(recognizer);
|
|
1703
|
+
}
|
|
1602
1704
|
}
|
|
1705
|
+
theMap.addGestureRecognizer(longPressGestureRecognizer);
|
|
1706
|
+
resolve();
|
|
1603
1707
|
}
|
|
1604
1708
|
catch (ex) {
|
|
1605
1709
|
if (Trace.isEnabled()) {
|
|
1606
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1710
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
|
|
1607
1711
|
}
|
|
1608
1712
|
reject(ex);
|
|
1609
1713
|
}
|
|
1610
1714
|
});
|
|
1611
1715
|
}
|
|
1612
|
-
|
|
1716
|
+
setOnScrollListener(listener, nativeMap) {
|
|
1613
1717
|
return new Promise((resolve, reject) => {
|
|
1614
1718
|
try {
|
|
1615
1719
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1616
|
-
let source;
|
|
1617
1720
|
if (!theMap) {
|
|
1618
1721
|
reject('No map has been loaded');
|
|
1619
1722
|
return;
|
|
1620
1723
|
}
|
|
1621
|
-
if (theMap
|
|
1622
|
-
|
|
1623
|
-
return;
|
|
1724
|
+
if (theMap['mapPanHandler'] === undefined) {
|
|
1725
|
+
theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 2, theMap);
|
|
1624
1726
|
}
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
if (options.url) {
|
|
1628
|
-
source = MGLVectorTileSource.alloc().initWithIdentifierConfigurationURL(id, NSURL.URLWithString(options.url));
|
|
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);
|
|
1714
|
-
break;
|
|
1715
|
-
}
|
|
1716
|
-
default:
|
|
1717
|
-
reject('Invalid source type: ' + options['type']);
|
|
1718
|
-
return;
|
|
1727
|
+
else {
|
|
1728
|
+
theMap['mapPanHandler'].addListener(2, listener);
|
|
1719
1729
|
}
|
|
1720
|
-
|
|
1721
|
-
const
|
|
1722
|
-
if (
|
|
1723
|
-
|
|
1730
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1731
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1732
|
+
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1733
|
+
recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
|
|
1734
|
+
break;
|
|
1724
1735
|
}
|
|
1725
|
-
reject(ex);
|
|
1726
|
-
return;
|
|
1727
1736
|
}
|
|
1728
|
-
theMap.style.addSource(source);
|
|
1729
1737
|
resolve();
|
|
1730
1738
|
}
|
|
1731
1739
|
catch (ex) {
|
|
1732
1740
|
if (Trace.isEnabled()) {
|
|
1733
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1741
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnScrollListener: ' + ex);
|
|
1734
1742
|
}
|
|
1735
1743
|
reject(ex);
|
|
1736
1744
|
}
|
|
1737
1745
|
});
|
|
1738
1746
|
}
|
|
1739
|
-
|
|
1747
|
+
setOnMoveBeginListener(listener, nativeMap) {
|
|
1740
1748
|
return new Promise((resolve, reject) => {
|
|
1741
1749
|
try {
|
|
1742
1750
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1744,109 +1752,277 @@ export class Mapbox extends MapboxCommon {
|
|
|
1744
1752
|
reject('No map has been loaded');
|
|
1745
1753
|
return;
|
|
1746
1754
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1755
|
+
if (theMap['mapPanHandler'] === undefined) {
|
|
1756
|
+
theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 1, theMap);
|
|
1757
|
+
}
|
|
1758
|
+
else {
|
|
1759
|
+
theMap['mapPanHandler'].addListener(1, listener);
|
|
1760
|
+
}
|
|
1761
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1762
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1763
|
+
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1764
|
+
recognizer.addTargetAction(theMap['mapPanHandler'], 'panBegin');
|
|
1765
|
+
break;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
resolve();
|
|
1769
|
+
}
|
|
1770
|
+
catch (ex) {
|
|
1771
|
+
if (Trace.isEnabled()) {
|
|
1772
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMoveBeginListener: ' + ex);
|
|
1773
|
+
}
|
|
1774
|
+
reject(ex);
|
|
1775
|
+
}
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
setOnMoveEndListener(listener, nativeMap) {
|
|
1779
|
+
return new Promise((resolve, reject) => {
|
|
1780
|
+
try {
|
|
1781
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1782
|
+
if (!theMap) {
|
|
1783
|
+
reject('No map has been loaded');
|
|
1750
1784
|
return;
|
|
1751
1785
|
}
|
|
1752
|
-
theMap
|
|
1786
|
+
if (theMap['mapPanHandler'] === undefined) {
|
|
1787
|
+
theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 3, theMap);
|
|
1788
|
+
}
|
|
1789
|
+
else {
|
|
1790
|
+
theMap['mapPanHandler'].addListener(3, listener);
|
|
1791
|
+
}
|
|
1792
|
+
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1793
|
+
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1794
|
+
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1795
|
+
recognizer.addTargetAction(theMap['mapPanHandler'], 'panEnd');
|
|
1796
|
+
break;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1753
1799
|
resolve();
|
|
1754
1800
|
}
|
|
1755
1801
|
catch (ex) {
|
|
1756
1802
|
if (Trace.isEnabled()) {
|
|
1757
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1803
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMoveEndListener: ' + ex);
|
|
1758
1804
|
}
|
|
1759
1805
|
reject(ex);
|
|
1760
1806
|
}
|
|
1761
1807
|
});
|
|
1762
1808
|
}
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1809
|
+
setOnFlingListener(listener, nativeMap) {
|
|
1810
|
+
return Promise.reject("'setOnFlingListener' is not supported on iOS");
|
|
1811
|
+
}
|
|
1812
|
+
async setOnCameraMoveListener(listener, nativeMap) {
|
|
1813
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1814
|
+
if (theMap) {
|
|
1815
|
+
theMap.delegate.setCameraChangedListener(listener);
|
|
1769
1816
|
}
|
|
1770
1817
|
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
|
-
}
|
|
1818
|
+
return Promise.reject('No map has been loaded');
|
|
1780
1819
|
}
|
|
1781
|
-
theMap.style.addLayer(layer.getNativeInstance());
|
|
1782
1820
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
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.");
|
|
1821
|
+
setOnCameraMoveCancelListener(listener, nativeMap) {
|
|
1822
|
+
return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
|
|
1823
|
+
}
|
|
1824
|
+
async setOnCameraIdleListener(listener, nativeMap) {
|
|
1825
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1826
|
+
if (theMap) {
|
|
1827
|
+
theMap.delegate.setCameraIdledListener(listener);
|
|
1794
1828
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
|
|
1829
|
+
else {
|
|
1830
|
+
return Promise.reject('No map has been loaded');
|
|
1798
1831
|
}
|
|
1799
1832
|
}
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1833
|
+
getViewport(nativeMap) {
|
|
1834
|
+
return new Promise((resolve, reject) => {
|
|
1835
|
+
try {
|
|
1836
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1837
|
+
if (!theMap) {
|
|
1838
|
+
reject('No map has been loaded');
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
const visibleBounds = theMap.visibleCoordinateBounds;
|
|
1842
|
+
const bounds = {
|
|
1843
|
+
north: visibleBounds.ne.latitude,
|
|
1844
|
+
east: visibleBounds.ne.longitude,
|
|
1845
|
+
south: visibleBounds.sw.latitude,
|
|
1846
|
+
west: visibleBounds.sw.longitude
|
|
1847
|
+
};
|
|
1848
|
+
resolve({
|
|
1849
|
+
bounds,
|
|
1850
|
+
zoomLevel: theMap.zoomLevel
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1853
|
+
catch (ex) {
|
|
1854
|
+
if (Trace.isEnabled()) {
|
|
1855
|
+
CLog(CLogTypes.info, 'Error in mapbox.getViewport: ' + ex);
|
|
1856
|
+
}
|
|
1857
|
+
reject(ex);
|
|
1858
|
+
}
|
|
1859
|
+
});
|
|
1860
|
+
}
|
|
1861
|
+
setViewport(options, nativeMap) {
|
|
1862
|
+
return new Promise((resolve, reject) => {
|
|
1863
|
+
try {
|
|
1864
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1865
|
+
if (!theMap) {
|
|
1866
|
+
reject('No map has been loaded');
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1869
|
+
const bounds = {
|
|
1870
|
+
sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
|
|
1871
|
+
ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
|
|
1872
|
+
};
|
|
1873
|
+
const animated = options.animated === undefined || options.animated;
|
|
1874
|
+
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 };
|
|
1875
|
+
theMap.setVisibleCoordinateBoundsEdgePaddingAnimated(bounds, padding, animated);
|
|
1876
|
+
resolve();
|
|
1877
|
+
}
|
|
1878
|
+
catch (ex) {
|
|
1879
|
+
if (Trace.isEnabled()) {
|
|
1880
|
+
CLog(CLogTypes.info, 'Error in mapbox.setViewport: ' + ex);
|
|
1881
|
+
}
|
|
1882
|
+
reject(ex);
|
|
1883
|
+
}
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
downloadOfflineRegion(options) {
|
|
1887
|
+
return new Promise((resolve, reject) => {
|
|
1888
|
+
try {
|
|
1889
|
+
const styleURL = _getMapStyle(options.style);
|
|
1890
|
+
const swCoordinate = CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west);
|
|
1891
|
+
const neCoordinate = CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east);
|
|
1892
|
+
const bounds = {
|
|
1893
|
+
sw: swCoordinate,
|
|
1894
|
+
ne: neCoordinate
|
|
1895
|
+
};
|
|
1896
|
+
const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
|
|
1897
|
+
if (options.accessToken) {
|
|
1898
|
+
MGLAccountManager.accessToken = options.accessToken;
|
|
1899
|
+
}
|
|
1900
|
+
if (options.onProgress) {
|
|
1901
|
+
_addObserver(MGLOfflinePackProgressChangedNotification, (notification) => {
|
|
1902
|
+
const offlinePack = notification.object;
|
|
1903
|
+
const offlinePackProgress = offlinePack.progress;
|
|
1904
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1905
|
+
const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
|
|
1906
|
+
options.onProgress({
|
|
1907
|
+
name: userInfo.objectForKey('name'),
|
|
1908
|
+
completed: offlinePackProgress.countOfResourcesCompleted,
|
|
1909
|
+
expected: offlinePackProgress.countOfResourcesExpected,
|
|
1910
|
+
percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
|
|
1911
|
+
complete
|
|
1912
|
+
});
|
|
1913
|
+
if (complete) {
|
|
1914
|
+
resolve();
|
|
1915
|
+
}
|
|
1916
|
+
});
|
|
1917
|
+
}
|
|
1918
|
+
_addObserver(MGLOfflinePackErrorNotification, (notification) => {
|
|
1919
|
+
const offlinePack = notification.object;
|
|
1920
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1921
|
+
const error = notification.userInfo[MGLOfflinePackUserInfoKeyError];
|
|
1922
|
+
reject({
|
|
1923
|
+
name: userInfo.objectForKey('name'),
|
|
1924
|
+
error: 'Download error. ' + error
|
|
1925
|
+
});
|
|
1926
|
+
});
|
|
1927
|
+
_addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
|
|
1928
|
+
const offlinePack = notification.object;
|
|
1929
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1930
|
+
const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
|
|
1931
|
+
console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
|
|
1932
|
+
});
|
|
1933
|
+
const userInfo = { name: options.name };
|
|
1934
|
+
const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
|
|
1935
|
+
MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
|
|
1936
|
+
if (error) {
|
|
1937
|
+
reject(error.localizedFailureReason);
|
|
1938
|
+
}
|
|
1939
|
+
else {
|
|
1940
|
+
pack.resume();
|
|
1941
|
+
}
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1944
|
+
catch (ex) {
|
|
1945
|
+
if (Trace.isEnabled()) {
|
|
1946
|
+
CLog(CLogTypes.info, 'Error in mapbox.downloadOfflineRegion: ' + ex);
|
|
1947
|
+
}
|
|
1948
|
+
reject(ex);
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
listOfflineRegions(options) {
|
|
1953
|
+
return new Promise((resolve, reject) => {
|
|
1954
|
+
try {
|
|
1955
|
+
const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
|
|
1956
|
+
if (!packs) {
|
|
1957
|
+
reject('No packs found or Mapbox not ready yet');
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
const regions = [];
|
|
1961
|
+
for (let i = 0; i < packs.count; i++) {
|
|
1962
|
+
const pack = packs.objectAtIndex(i);
|
|
1963
|
+
const region = pack.region;
|
|
1964
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
|
|
1965
|
+
regions.push({
|
|
1966
|
+
name: userInfo.objectForKey('name'),
|
|
1967
|
+
style: '' + region.styleURL,
|
|
1968
|
+
minZoom: region.minimumZoomLevel,
|
|
1969
|
+
maxZoom: region.maximumZoomLevel,
|
|
1970
|
+
bounds: {
|
|
1971
|
+
north: region.bounds.ne.latitude,
|
|
1972
|
+
east: region.bounds.ne.longitude,
|
|
1973
|
+
south: region.bounds.sw.latitude,
|
|
1974
|
+
west: region.bounds.sw.longitude
|
|
1975
|
+
}
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1978
|
+
resolve(regions);
|
|
1979
|
+
}
|
|
1980
|
+
catch (ex) {
|
|
1981
|
+
if (Trace.isEnabled()) {
|
|
1982
|
+
CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
|
|
1983
|
+
}
|
|
1984
|
+
reject(ex);
|
|
1811
1985
|
}
|
|
1812
|
-
|
|
1813
|
-
const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
|
|
1814
|
-
const newCoordPointer = new interop.Reference(newCoord);
|
|
1815
|
-
lineFeature.appendCoordinatesCount(newCoordPointer, 1);
|
|
1816
|
-
lineSource.shape = lineFeature;
|
|
1817
|
-
}
|
|
1818
|
-
catch (error) {
|
|
1819
|
-
console.log(error);
|
|
1820
|
-
throw error;
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
addGeoJsonClustered(options, nativeMapViewInstance) {
|
|
1824
|
-
throw new Error('Method not implemented.');
|
|
1986
|
+
});
|
|
1825
1987
|
}
|
|
1826
|
-
|
|
1988
|
+
deleteOfflineRegion(options) {
|
|
1827
1989
|
return new Promise((resolve, reject) => {
|
|
1828
1990
|
try {
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
reject('No map has been loaded');
|
|
1991
|
+
if (!options || (!options.id && !options.name)) {
|
|
1992
|
+
reject("Pass in the 'id' or 'name' param");
|
|
1832
1993
|
return;
|
|
1833
1994
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1995
|
+
const packs = MGLOfflineStorage.sharedOfflineStorage.packs;
|
|
1996
|
+
let found = false;
|
|
1997
|
+
for (let i = 0; i < packs.count; i++) {
|
|
1998
|
+
const pack = packs.objectAtIndex(i);
|
|
1999
|
+
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(pack.context);
|
|
2000
|
+
const regionId = options.id ? userInfo.objectForKey('id') : userInfo.objectForKey('name');
|
|
2001
|
+
if (regionId === (options.id || options.name)) {
|
|
2002
|
+
found = true;
|
|
2003
|
+
MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
|
|
2004
|
+
if (error) {
|
|
2005
|
+
reject(error.localizedFailureReason);
|
|
2006
|
+
}
|
|
2007
|
+
else {
|
|
2008
|
+
resolve();
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
if (!found) {
|
|
2014
|
+
reject('Region not found');
|
|
1837
2015
|
}
|
|
1838
|
-
theMap.setUserTrackingModeAnimated(_getTrackingMode(options.mode), options.animated !== false);
|
|
1839
|
-
resolve();
|
|
1840
2016
|
}
|
|
1841
2017
|
catch (ex) {
|
|
1842
2018
|
if (Trace.isEnabled()) {
|
|
1843
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
2019
|
+
CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
|
|
1844
2020
|
}
|
|
1845
2021
|
reject(ex);
|
|
1846
2022
|
}
|
|
1847
2023
|
});
|
|
1848
2024
|
}
|
|
1849
|
-
|
|
2025
|
+
addExtrusion(options, nativeMap) {
|
|
1850
2026
|
return new Promise((resolve, reject) => {
|
|
1851
2027
|
try {
|
|
1852
2028
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1854,18 +2030,17 @@ export class Mapbox extends MapboxCommon {
|
|
|
1854
2030
|
reject('No map has been loaded');
|
|
1855
2031
|
return;
|
|
1856
2032
|
}
|
|
1857
|
-
|
|
1858
|
-
resolve(new Layer(layer));
|
|
2033
|
+
resolve();
|
|
1859
2034
|
}
|
|
1860
2035
|
catch (ex) {
|
|
1861
2036
|
if (Trace.isEnabled()) {
|
|
1862
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
2037
|
+
CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
|
|
1863
2038
|
}
|
|
1864
2039
|
reject(ex);
|
|
1865
2040
|
}
|
|
1866
2041
|
});
|
|
1867
2042
|
}
|
|
1868
|
-
|
|
2043
|
+
updateSource(id, options, nativeMap) {
|
|
1869
2044
|
return new Promise((resolve, reject) => {
|
|
1870
2045
|
try {
|
|
1871
2046
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1873,489 +2048,379 @@ export class Mapbox extends MapboxCommon {
|
|
|
1873
2048
|
reject('No map has been loaded');
|
|
1874
2049
|
return;
|
|
1875
2050
|
}
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
}
|
|
1881
|
-
resolve(result);
|
|
1882
|
-
}
|
|
1883
|
-
catch (ex) {
|
|
1884
|
-
if (Trace.isEnabled()) {
|
|
1885
|
-
CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
|
|
2051
|
+
const source = theMap.style.sourceWithIdentifier(id);
|
|
2052
|
+
if (!source) {
|
|
2053
|
+
reject('Source does not exists: ' + id);
|
|
2054
|
+
return;
|
|
1886
2055
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
const _addObserver = (eventName, callback) => NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback);
|
|
1898
|
-
function _downloadImage(marker) {
|
|
1899
|
-
return new Promise((resolve, reject) => {
|
|
1900
|
-
if (Trace.isEnabled()) {
|
|
1901
|
-
CLog(CLogTypes.info, '>> _downloadImage');
|
|
1902
|
-
}
|
|
1903
|
-
if (_markerIconDownloadCache[marker.icon]) {
|
|
1904
|
-
marker.iconDownloaded = _markerIconDownloadCache[marker.icon];
|
|
1905
|
-
if (Trace.isEnabled()) {
|
|
1906
|
-
CLog(CLogTypes.info, '>> marker.iconDownloaded: ' + marker.iconDownloaded);
|
|
1907
|
-
}
|
|
1908
|
-
resolve(marker);
|
|
1909
|
-
return;
|
|
1910
|
-
}
|
|
1911
|
-
getImage(marker.icon).then((output) => {
|
|
1912
|
-
marker.iconDownloaded = output.ios;
|
|
1913
|
-
_markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
|
|
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;
|
|
2056
|
+
switch (options.type) {
|
|
2057
|
+
case 'geojson':
|
|
2058
|
+
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
2059
|
+
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
2060
|
+
const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
2061
|
+
source.shape = geoJsonShape;
|
|
2062
|
+
break;
|
|
2063
|
+
default:
|
|
2064
|
+
reject('Invalid source type: ' + options['type']);
|
|
2065
|
+
return;
|
|
2074
2066
|
}
|
|
2075
2067
|
}
|
|
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
|
-
}
|
|
2068
|
+
catch (ex) {
|
|
2069
|
+
if (Trace.isEnabled()) {
|
|
2070
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2089
2071
|
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2072
|
+
reject(ex);
|
|
2073
|
+
}
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
addSource(id, options, nativeMap) {
|
|
2077
|
+
return new Promise((resolve, reject) => {
|
|
2078
|
+
try {
|
|
2079
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2080
|
+
let source;
|
|
2081
|
+
if (!theMap) {
|
|
2082
|
+
reject('No map has been loaded');
|
|
2083
|
+
return;
|
|
2084
|
+
}
|
|
2085
|
+
if (theMap.style.sourceWithIdentifier(id)) {
|
|
2086
|
+
reject('Source exists: ' + id);
|
|
2087
|
+
return;
|
|
2088
|
+
}
|
|
2089
|
+
switch (options.type) {
|
|
2090
|
+
case 'vector': {
|
|
2091
|
+
if (options.url) {
|
|
2092
|
+
source = MGLVectorTileSource.alloc().initWithIdentifierConfigurationURL(id, NSURL.URLWithString(options.url));
|
|
2093
|
+
}
|
|
2094
|
+
else {
|
|
2095
|
+
const sourceOptions = {};
|
|
2096
|
+
if (options.minzoom !== undefined) {
|
|
2097
|
+
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
2098
|
+
}
|
|
2099
|
+
if (options.maxzoom !== undefined) {
|
|
2100
|
+
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
2101
|
+
}
|
|
2102
|
+
if (options.scheme) {
|
|
2103
|
+
switch (options.scheme) {
|
|
2104
|
+
case 'xyz':
|
|
2105
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
2106
|
+
break;
|
|
2107
|
+
case 'tms':
|
|
2108
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
2109
|
+
break;
|
|
2110
|
+
default:
|
|
2111
|
+
throw new Error('Unknown raster tile scheme.');
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
if (options.bounds) {
|
|
2115
|
+
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
2116
|
+
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
2117
|
+
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
2118
|
+
});
|
|
2119
|
+
}
|
|
2120
|
+
source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
2121
|
+
}
|
|
2122
|
+
break;
|
|
2123
|
+
}
|
|
2124
|
+
case 'geojson':
|
|
2125
|
+
if (theMap.style.sourceWithIdentifier(id)) {
|
|
2126
|
+
reject("Remove the layer with this id first with 'removeLayer': " + id);
|
|
2127
|
+
return;
|
|
2128
|
+
}
|
|
2129
|
+
let geoJsonShape;
|
|
2130
|
+
if (options.data) {
|
|
2131
|
+
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
2132
|
+
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
2133
|
+
geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
2134
|
+
}
|
|
2135
|
+
const sourceOptions = {};
|
|
2136
|
+
if (options.minzoom !== undefined) {
|
|
2137
|
+
sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
2138
|
+
}
|
|
2139
|
+
if (options.maxzoom !== undefined) {
|
|
2140
|
+
sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
2141
|
+
}
|
|
2142
|
+
if (options.lineMetrics !== undefined) {
|
|
2143
|
+
sourceOptions[MGLShapeSourceOptionLineDistanceMetrics] = options.lineMetrics;
|
|
2144
|
+
}
|
|
2145
|
+
if (options.cluster) {
|
|
2146
|
+
sourceOptions[MGLShapeSourceOptionClustered] = true;
|
|
2147
|
+
sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
|
|
2148
|
+
sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
|
|
2149
|
+
if (options.cluster.properties) {
|
|
2150
|
+
const clusterProperties = {};
|
|
2151
|
+
for (const property of Object.keys(options.cluster.properties)) {
|
|
2152
|
+
let [operator, operand] = options.cluster.properties[property];
|
|
2153
|
+
if (!Array.isArray(operator)) {
|
|
2154
|
+
operator = [operator];
|
|
2155
|
+
}
|
|
2156
|
+
const expressions = Utils.ios.collections.jsArrayToNSArray([ExpressionParser.parseJson(operator), ExpressionParser.parseJson(operand)]);
|
|
2157
|
+
clusterProperties[property] = expressions;
|
|
2158
|
+
}
|
|
2159
|
+
sourceOptions[MGLShapeSourceOptionClusterProperties] = clusterProperties;
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
|
|
2163
|
+
break;
|
|
2164
|
+
case 'raster': {
|
|
2165
|
+
const sourceOptions = {
|
|
2166
|
+
[MGLTileSourceOptionTileSize]: options.tileSize || 256
|
|
2167
|
+
};
|
|
2168
|
+
if (options.minzoom !== undefined) {
|
|
2169
|
+
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
2170
|
+
}
|
|
2171
|
+
if (options.maxzoom !== undefined) {
|
|
2172
|
+
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
2173
|
+
}
|
|
2174
|
+
if (options.scheme) {
|
|
2175
|
+
switch (options.scheme || 'xyz') {
|
|
2176
|
+
case 'xyz':
|
|
2177
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
2178
|
+
break;
|
|
2179
|
+
case 'tms':
|
|
2180
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
2181
|
+
break;
|
|
2182
|
+
default:
|
|
2183
|
+
throw new Error('Unknown raster tile scheme.');
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
if (options.bounds) {
|
|
2187
|
+
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
2188
|
+
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
2189
|
+
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
2190
|
+
});
|
|
2191
|
+
}
|
|
2192
|
+
source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
2193
|
+
break;
|
|
2094
2194
|
}
|
|
2195
|
+
default:
|
|
2196
|
+
reject('Invalid source type: ' + options['type']);
|
|
2197
|
+
return;
|
|
2095
2198
|
}
|
|
2096
|
-
|
|
2199
|
+
if (!source) {
|
|
2200
|
+
const ex = 'No source to add';
|
|
2097
2201
|
if (Trace.isEnabled()) {
|
|
2098
|
-
CLog(CLogTypes.info, '
|
|
2202
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2099
2203
|
}
|
|
2204
|
+
reject(ex);
|
|
2205
|
+
return;
|
|
2100
2206
|
}
|
|
2207
|
+
theMap.style.addSource(source);
|
|
2208
|
+
resolve();
|
|
2101
2209
|
}
|
|
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);
|
|
2210
|
+
catch (ex) {
|
|
2211
|
+
if (Trace.isEnabled()) {
|
|
2212
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2110
2213
|
}
|
|
2214
|
+
reject(ex);
|
|
2111
2215
|
}
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
removeSource(id, nativeMap) {
|
|
2219
|
+
return new Promise((resolve, reject) => {
|
|
2220
|
+
try {
|
|
2221
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2222
|
+
if (!theMap) {
|
|
2223
|
+
reject('No map has been loaded');
|
|
2224
|
+
return;
|
|
2225
|
+
}
|
|
2226
|
+
const source = theMap.style.sourceWithIdentifier(id);
|
|
2227
|
+
if (!source) {
|
|
2228
|
+
reject('Source does not exist');
|
|
2229
|
+
return;
|
|
2230
|
+
}
|
|
2231
|
+
theMap.style.removeSource(source);
|
|
2232
|
+
resolve();
|
|
2129
2233
|
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2234
|
+
catch (ex) {
|
|
2235
|
+
if (Trace.isEnabled()) {
|
|
2236
|
+
CLog(CLogTypes.info, 'Error in mapbox.removeSource: ' + ex);
|
|
2237
|
+
}
|
|
2238
|
+
reject(ex);
|
|
2133
2239
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
async addLayer(style, belowLayerId, nativeMapView) {
|
|
2243
|
+
const theMap = nativeMapView || this._mapboxViewInstance;
|
|
2244
|
+
let source = null;
|
|
2245
|
+
if (typeof style.source != 'string') {
|
|
2246
|
+
await this.addSource(style.id + '_source', style.source);
|
|
2247
|
+
source = theMap.style.sourceWithIdentifier(style.id + '_source');
|
|
2139
2248
|
}
|
|
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);
|
|
2249
|
+
else {
|
|
2250
|
+
source = theMap.style.sourceWithIdentifier(style.source);
|
|
2148
2251
|
}
|
|
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;
|
|
2252
|
+
const layer = await LayerFactory.createLayer(style, source);
|
|
2253
|
+
if (belowLayerId) {
|
|
2254
|
+
const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
|
|
2255
|
+
if (belowlayer) {
|
|
2256
|
+
theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
|
|
2257
|
+
return;
|
|
2164
2258
|
}
|
|
2165
2259
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
|
|
2260
|
+
theMap.style.addLayer(layer.getNativeInstance());
|
|
2261
|
+
}
|
|
2262
|
+
async removeLayer(id, nativeMapViewInstance) {
|
|
2263
|
+
const theMap = nativeMapViewInstance || this._mapboxViewInstance;
|
|
2171
2264
|
if (Trace.isEnabled()) {
|
|
2172
|
-
CLog(CLogTypes.info,
|
|
2173
|
-
}
|
|
2174
|
-
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
2175
|
-
this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init();
|
|
2176
|
-
return this.userLocationAnnotationView;
|
|
2265
|
+
CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
|
|
2177
2266
|
}
|
|
2178
|
-
|
|
2179
|
-
};
|
|
2180
|
-
MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
|
|
2267
|
+
const layer = theMap.style.layerWithIdentifier(id);
|
|
2181
2268
|
if (Trace.isEnabled()) {
|
|
2182
|
-
CLog(CLogTypes.info, '
|
|
2269
|
+
CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
|
|
2183
2270
|
}
|
|
2184
|
-
if (
|
|
2185
|
-
|
|
2271
|
+
if (!layer) {
|
|
2272
|
+
throw new Error("Layer '" + id + "' not found when attempting to remove it.");
|
|
2186
2273
|
}
|
|
2187
|
-
|
|
2188
|
-
MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
|
|
2274
|
+
theMap.style.removeLayer(layer);
|
|
2189
2275
|
if (Trace.isEnabled()) {
|
|
2190
|
-
CLog(CLogTypes.info, '
|
|
2191
|
-
}
|
|
2192
|
-
if (this.cameraChangedListener) {
|
|
2193
|
-
this.cameraChangedListener(reason, animated);
|
|
2276
|
+
CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
|
|
2194
2277
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2278
|
+
}
|
|
2279
|
+
async addLinePoint(id, lnglat, sourceId, nativeMapView) {
|
|
2280
|
+
const theMap = nativeMapView || this._mapboxViewInstance;
|
|
2281
|
+
const sId = !!sourceId ? sourceId : id + '_source';
|
|
2282
|
+
const lineSource = theMap.style.sourceWithIdentifier(sId);
|
|
2283
|
+
if (!lineSource) {
|
|
2284
|
+
throw new Error(`no source found with id: ${sId}`);
|
|
2197
2285
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2286
|
+
try {
|
|
2287
|
+
const lineFeatures = lineSource.featuresMatchingPredicate(ExpressionParser.parseJson(['==', '$type', 'LineString']));
|
|
2288
|
+
if (lineFeatures.count === 0) {
|
|
2289
|
+
throw new Error('no line string feature found');
|
|
2290
|
+
}
|
|
2291
|
+
const lineFeature = lineFeatures.objectAtIndex(0);
|
|
2292
|
+
const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
|
|
2293
|
+
const newCoordPointer = new interop.Reference(newCoord);
|
|
2294
|
+
lineFeature.appendCoordinatesCount(newCoordPointer, 1);
|
|
2295
|
+
lineSource.shape = lineFeature;
|
|
2202
2296
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2297
|
+
catch (error) {
|
|
2298
|
+
console.log(error);
|
|
2299
|
+
throw error;
|
|
2205
2300
|
}
|
|
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
2301
|
}
|
|
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;
|
|
2302
|
+
addGeoJsonClustered(options, nativeMapViewInstance) {
|
|
2303
|
+
throw new Error('Method not implemented.');
|
|
2239
2304
|
}
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2305
|
+
trackUser(options, nativeMap) {
|
|
2306
|
+
return new Promise((resolve, reject) => {
|
|
2307
|
+
try {
|
|
2308
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2309
|
+
if (!theMap) {
|
|
2310
|
+
reject('No map has been loaded');
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2313
|
+
if (!theMap.showsUserLocation) {
|
|
2314
|
+
reject('The map is not currently showing the user location');
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2317
|
+
theMap.setUserTrackingModeAnimated(_getTrackingMode(options.cameraMode), options.animated !== false);
|
|
2318
|
+
resolve();
|
|
2319
|
+
}
|
|
2320
|
+
catch (ex) {
|
|
2321
|
+
if (Trace.isEnabled()) {
|
|
2322
|
+
CLog(CLogTypes.info, 'Error in mapbox.trackUser: ' + ex);
|
|
2323
|
+
}
|
|
2324
|
+
reject(ex);
|
|
2325
|
+
}
|
|
2253
2326
|
});
|
|
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
2327
|
}
|
|
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) {
|
|
2328
|
+
getLayer(name, nativeMap) {
|
|
2329
|
+
return new Promise((resolve, reject) => {
|
|
2330
|
+
try {
|
|
2331
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2332
|
+
if (!theMap) {
|
|
2333
|
+
reject('No map has been loaded');
|
|
2334
|
+
return;
|
|
2335
|
+
}
|
|
2336
|
+
const layer = theMap.style.layerWithIdentifier(name);
|
|
2337
|
+
resolve(new Layer(layer));
|
|
2338
|
+
}
|
|
2339
|
+
catch (ex) {
|
|
2287
2340
|
if (Trace.isEnabled()) {
|
|
2288
|
-
CLog(CLogTypes.info, '
|
|
2341
|
+
CLog(CLogTypes.info, 'Error in mapbox.getLayer: ' + ex);
|
|
2289
2342
|
}
|
|
2290
|
-
|
|
2291
|
-
lat: panCoordinate.latitude,
|
|
2292
|
-
lng: panCoordinate.longitude
|
|
2293
|
-
});
|
|
2343
|
+
reject(ex);
|
|
2294
2344
|
}
|
|
2295
|
-
return;
|
|
2296
|
-
}
|
|
2297
|
-
this._listener({
|
|
2298
|
-
lat: panCoordinate.latitude,
|
|
2299
|
-
lng: panCoordinate.longitude
|
|
2300
2345
|
});
|
|
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
2346
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2347
|
+
getLayers(nativeMap) {
|
|
2348
|
+
return new Promise((resolve, reject) => {
|
|
2349
|
+
try {
|
|
2350
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2351
|
+
if (!theMap) {
|
|
2352
|
+
reject('No map has been loaded');
|
|
2353
|
+
return;
|
|
2354
|
+
}
|
|
2355
|
+
const layers = theMap.style.layers;
|
|
2356
|
+
const result = [];
|
|
2357
|
+
for (let i = 0; i < layers.count; i++) {
|
|
2358
|
+
result.push(new Layer(layers[i]));
|
|
2359
|
+
}
|
|
2360
|
+
resolve(result);
|
|
2361
|
+
}
|
|
2362
|
+
catch (ex) {
|
|
2363
|
+
if (Trace.isEnabled()) {
|
|
2364
|
+
CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
|
|
2365
|
+
}
|
|
2366
|
+
reject(ex);
|
|
2367
|
+
}
|
|
2325
2368
|
});
|
|
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
2369
|
}
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
this.instance.visible = false;
|
|
2370
|
+
project(data) {
|
|
2371
|
+
const theMap = this._mapboxViewInstance;
|
|
2372
|
+
const { x, y } = theMap.convertCoordinateToPointToView({ latitude: data.lat, longitude: data.lng }, theMap);
|
|
2373
|
+
return { x, y };
|
|
2345
2374
|
}
|
|
2346
|
-
|
|
2347
|
-
|
|
2375
|
+
projectBack(screenCoordinate) {
|
|
2376
|
+
const theMap = this._mapboxViewInstance;
|
|
2377
|
+
const cgPoint = {
|
|
2378
|
+
x: screenCoordinate.x,
|
|
2379
|
+
y: screenCoordinate.y
|
|
2380
|
+
};
|
|
2381
|
+
const coordinate = theMap.convertPointToCoordinateFromView(cgPoint, theMap);
|
|
2382
|
+
return {
|
|
2383
|
+
lat: coordinate.latitude,
|
|
2384
|
+
lng: coordinate.longitude
|
|
2385
|
+
};
|
|
2348
2386
|
}
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2387
|
+
}
|
|
2388
|
+
const _addObserver = (eventName, callback) => NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback);
|
|
2389
|
+
function _downloadImage(marker) {
|
|
2390
|
+
return new Promise((resolve, reject) => {
|
|
2391
|
+
if (Trace.isEnabled()) {
|
|
2392
|
+
CLog(CLogTypes.info, '>> _downloadImage');
|
|
2352
2393
|
}
|
|
2353
|
-
|
|
2354
|
-
|
|
2394
|
+
if (_markerIconDownloadCache[marker.icon]) {
|
|
2395
|
+
marker.iconDownloaded = _markerIconDownloadCache[marker.icon];
|
|
2396
|
+
if (Trace.isEnabled()) {
|
|
2397
|
+
CLog(CLogTypes.info, '>> marker.iconDownloaded: ' + marker.iconDownloaded);
|
|
2398
|
+
}
|
|
2399
|
+
resolve(marker);
|
|
2400
|
+
return;
|
|
2355
2401
|
}
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2402
|
+
Http.getImage(marker.icon).then((output) => {
|
|
2403
|
+
marker.iconDownloaded = output.ios;
|
|
2404
|
+
_markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
|
|
2405
|
+
resolve(marker);
|
|
2406
|
+
}, (ignoredError) => {
|
|
2407
|
+
console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
|
|
2408
|
+
resolve(marker);
|
|
2409
|
+
});
|
|
2410
|
+
});
|
|
2360
2411
|
}
|
|
2361
|
-
|
|
2412
|
+
const _downloadMarkerImages = (markers) => {
|
|
2413
|
+
const iterations = [];
|
|
2414
|
+
const result = [];
|
|
2415
|
+
markers.forEach((marker) => {
|
|
2416
|
+
if (marker.icon && marker.icon.startsWith('http')) {
|
|
2417
|
+
const p = _downloadImage(marker).then((mark) => result.push(mark));
|
|
2418
|
+
iterations.push(p);
|
|
2419
|
+
}
|
|
2420
|
+
else {
|
|
2421
|
+
result.push(marker);
|
|
2422
|
+
}
|
|
2423
|
+
});
|
|
2424
|
+
return Promise.all(iterations).then(() => result);
|
|
2425
|
+
};
|
|
2426
|
+
//# sourceMappingURL=index.ios.js.map
|