@nativescript-community/ui-mapbox 6.2.8 → 6.2.12
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} +17 -3
- package/{mapbox.common.js → common.js} +18 -1
- package/filter/filter-parser.d.ts +4 -0
- package/{mapbox.android.d.ts → index.android.d.ts} +5 -14
- package/{mapbox.android.js → index.android.js} +130 -64
- package/index.d.ts +98 -6
- package/{mapbox.ios.d.ts → index.ios.d.ts} +3 -30
- package/{mapbox.ios.js → index.ios.js} +1926 -1893
- package/layers/layer-factory.android.d.ts +14 -1
- package/layers/layer-factory.android.js +33 -2
- package/layers/layer-factory.d.ts +15 -1
- package/layers/layer-factory.ios.d.ts +14 -1
- package/layers/layer-factory.ios.js +42 -2
- package/layers/parser/property-parser.android.d.ts +1 -0
- package/layers/parser/property-parser.android.js +25 -0
- package/layers/parser/property-parser.d.ts +4 -0
- package/layers/parser/property-parser.ios.d.ts +1 -0
- package/layers/parser/property-parser.ios.js +21 -0
- package/package.json +55 -49
- package/platforms/android/include.gradle +4 -1
- package/platforms/android/ui_mapbox.aar +0 -0
- package/platforms/ios/Podfile +2 -2
- package/LICENSE +0 -21
- package/pnpm-lock.yaml +0 -10
- package/typings/index.d.ts +0 -8
|
@@ -1,1227 +1,1289 @@
|
|
|
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 { FilterParser } from './filter/filter-parser';
|
|
5
|
+
var MGLMapViewDelegateImpl = /** @class */ (function (_super) {
|
|
6
|
+
__extends(MGLMapViewDelegateImpl, _super);
|
|
7
|
+
function MGLMapViewDelegateImpl() {
|
|
8
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
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
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
514
|
+
setConfig(settings) {
|
|
515
|
+
if (Trace.isEnabled()) {
|
|
516
|
+
CLog(CLogTypes.info, 'setConfig(): settings:', settings);
|
|
517
|
+
}
|
|
518
|
+
this.settings = settings;
|
|
519
|
+
}
|
|
520
|
+
getNativeMapView() {
|
|
521
|
+
return this.nativeMapView;
|
|
522
|
+
}
|
|
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?');
|
|
706
571
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
theMap.style.setImageForName(img.ios, imageId);
|
|
710
|
-
resolve();
|
|
572
|
+
if (this.initCountHack > 50) {
|
|
573
|
+
return;
|
|
711
574
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
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()');
|
|
718
591
|
}
|
|
719
|
-
|
|
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');
|
|
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
|
+
});
|
|
613
|
+
});
|
|
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();
|
|
693
|
+
}
|
|
694
|
+
if (this.userLocationRenderMode === 'GPS') {
|
|
695
|
+
this.updateHeading();
|
|
696
|
+
}
|
|
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 = {};
|
|
720
876
|
}
|
|
721
|
-
|
|
722
|
-
|
|
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
|
-
});
|
|
877
|
+
setMapboxViewInstance(mapboxViewInstance) {
|
|
878
|
+
this._mapboxViewInstance = mapboxViewInstance;
|
|
740
879
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
880
|
+
initEventHandlerShim(settings, mapboxNativeViewInstance) {
|
|
881
|
+
if (Trace.isEnabled()) {
|
|
882
|
+
CLog(CLogTypes.info, 'Mapbox:initEventHandlerShim(): top');
|
|
883
|
+
}
|
|
884
|
+
this.setOnMapClickListener((point) => this.checkForClickEvent(point), mapboxNativeViewInstance);
|
|
885
|
+
}
|
|
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
|
|
754
893
|
});
|
|
755
894
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
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);
|
|
900
|
+
}
|
|
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);
|
|
764
911
|
}
|
|
912
|
+
})
|
|
913
|
+
.catch((err) => {
|
|
914
|
+
console.error('click error ', eventListener.id, err);
|
|
765
915
|
});
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
else {
|
|
770
|
-
_markers = [];
|
|
771
|
-
}
|
|
772
|
-
if (markersToRemove.length > 0) {
|
|
773
|
-
theMap.removeAnnotations(markersToRemove);
|
|
774
|
-
}
|
|
775
|
-
resolve();
|
|
776
|
-
}
|
|
777
|
-
catch (ex) {
|
|
778
|
-
if (Trace.isEnabled()) {
|
|
779
|
-
CLog(CLogTypes.info, 'Error in mapbox.removeMarkers: ' + ex);
|
|
780
|
-
}
|
|
781
|
-
reject(ex);
|
|
782
|
-
}
|
|
783
|
-
});
|
|
916
|
+
});
|
|
917
|
+
this.view && this.view.notify({ eventName: 'mapClick', object: this.view, point });
|
|
918
|
+
return false;
|
|
784
919
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
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);
|
|
920
|
+
_addMarkers(markers, nativeMap) {
|
|
921
|
+
if (!markers) {
|
|
922
|
+
if (Trace.isEnabled()) {
|
|
923
|
+
CLog(CLogTypes.info, 'No markers passed');
|
|
799
924
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
806
|
-
const coordinate = theMap.centerCoordinate;
|
|
807
|
-
resolve({
|
|
808
|
-
lat: coordinate.latitude,
|
|
809
|
-
lng: coordinate.longitude
|
|
810
|
-
});
|
|
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'}]");
|
|
811
930
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
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);
|
|
815
946
|
}
|
|
816
|
-
|
|
817
|
-
|
|
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
|
+
});
|
|
818
975
|
});
|
|
819
976
|
}
|
|
820
|
-
|
|
977
|
+
show(options) {
|
|
978
|
+
if (Trace.isEnabled()) {
|
|
979
|
+
CLog(CLogTypes.info, 'show(): top with options:', options);
|
|
980
|
+
}
|
|
821
981
|
return new Promise((resolve, reject) => {
|
|
822
982
|
try {
|
|
823
|
-
const
|
|
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);
|
|
983
|
+
const settings = Mapbox.merge(options, Mapbox.defaults);
|
|
984
|
+
if (settings.accessToken === undefined) {
|
|
985
|
+
reject("Please set the 'accessToken' parameter");
|
|
986
|
+
return;
|
|
837
987
|
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
});
|
|
841
|
-
}
|
|
842
|
-
getZoomLevel(nativeMap) {
|
|
843
|
-
return new Promise((resolve, reject) => {
|
|
844
|
-
try {
|
|
845
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
846
|
-
resolve(theMap.zoomLevel);
|
|
847
|
-
}
|
|
848
|
-
catch (ex) {
|
|
849
|
-
if (Trace.isEnabled()) {
|
|
850
|
-
CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
|
|
988
|
+
if (this._mapboxViewInstance) {
|
|
989
|
+
this._mapboxViewInstance.removeFromSuperview();
|
|
851
990
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
|
|
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);
|
|
864
1002
|
setTimeout(() => {
|
|
865
|
-
|
|
866
|
-
},
|
|
1003
|
+
view.addSubview(this._mapboxViewInstance);
|
|
1004
|
+
}, 500);
|
|
867
1005
|
}
|
|
868
1006
|
catch (ex) {
|
|
869
1007
|
if (Trace.isEnabled()) {
|
|
870
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1008
|
+
CLog(CLogTypes.info, 'Error in mapbox.show: ' + ex);
|
|
871
1009
|
}
|
|
872
1010
|
reject(ex);
|
|
873
1011
|
}
|
|
874
1012
|
});
|
|
875
1013
|
}
|
|
876
|
-
|
|
1014
|
+
hide() {
|
|
877
1015
|
return new Promise((resolve, reject) => {
|
|
878
1016
|
try {
|
|
879
|
-
|
|
880
|
-
|
|
1017
|
+
if (this._mapboxViewInstance) {
|
|
1018
|
+
this._mapboxViewInstance.removeFromSuperview();
|
|
1019
|
+
}
|
|
1020
|
+
resolve();
|
|
881
1021
|
}
|
|
882
1022
|
catch (ex) {
|
|
883
1023
|
if (Trace.isEnabled()) {
|
|
884
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1024
|
+
CLog(CLogTypes.info, 'Error in mapbox.hide: ' + ex);
|
|
885
1025
|
}
|
|
886
1026
|
reject(ex);
|
|
887
1027
|
}
|
|
888
1028
|
});
|
|
889
1029
|
}
|
|
890
|
-
|
|
1030
|
+
unhide() {
|
|
891
1031
|
return new Promise((resolve, reject) => {
|
|
892
1032
|
try {
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1033
|
+
if (this._mapboxViewInstance) {
|
|
1034
|
+
const view = UIApplication.sharedApplication.keyWindow.rootViewController.view;
|
|
1035
|
+
view.addSubview(this._mapboxViewInstance);
|
|
1036
|
+
resolve();
|
|
897
1037
|
}
|
|
898
1038
|
else {
|
|
899
|
-
|
|
1039
|
+
reject('No map found');
|
|
900
1040
|
}
|
|
901
1041
|
}
|
|
902
1042
|
catch (ex) {
|
|
903
1043
|
if (Trace.isEnabled()) {
|
|
904
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1044
|
+
CLog(CLogTypes.info, 'Error in mapbox.unhide: ' + ex);
|
|
905
1045
|
}
|
|
906
1046
|
reject(ex);
|
|
907
1047
|
}
|
|
908
1048
|
});
|
|
909
1049
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
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
|
-
}
|
|
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
|
+
});
|
|
933
1059
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
switch (mode) {
|
|
937
|
-
case 'NORMAL':
|
|
938
|
-
return 'NORMAL';
|
|
939
|
-
case 'COMPASS':
|
|
940
|
-
return 'COMPASS';
|
|
941
|
-
case 'GPS':
|
|
942
|
-
return 'GPS';
|
|
943
|
-
}
|
|
1060
|
+
onStart(nativeMap) {
|
|
1061
|
+
return Promise.resolve();
|
|
944
1062
|
}
|
|
945
|
-
|
|
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) {
|
|
946
1079
|
return new Promise((resolve, reject) => {
|
|
947
1080
|
try {
|
|
948
1081
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
949
|
-
theMap.showsUserLocation = true;
|
|
950
|
-
theMap.userTrackingMode = this._stringToCameraMode(options.cameraMode);
|
|
951
|
-
theMap.showsUserHeadingIndicator = true;
|
|
952
|
-
this.userLocationRenderMode = this._stringToRenderMode(options.renderMode);
|
|
953
1082
|
const delegate = theMap.delegate;
|
|
954
|
-
delegate.
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
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);
|
|
959
1090
|
}
|
|
960
1091
|
catch (ex) {
|
|
961
1092
|
if (Trace.isEnabled()) {
|
|
962
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1093
|
+
CLog(CLogTypes.info, 'Error in mapbox.setMapStyle: ' + ex);
|
|
963
1094
|
}
|
|
964
1095
|
reject(ex);
|
|
965
1096
|
}
|
|
966
1097
|
});
|
|
967
1098
|
}
|
|
968
|
-
|
|
1099
|
+
async getImage(imageId, nativeMap) {
|
|
969
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
|
+
}
|
|
970
1106
|
try {
|
|
971
|
-
|
|
1107
|
+
const nativeImage = theMap.style.imageForName(imageId);
|
|
1108
|
+
const img = new ImageSource(nativeImage);
|
|
1109
|
+
resolve(img);
|
|
972
1110
|
}
|
|
973
1111
|
catch (ex) {
|
|
1112
|
+
reject('Error during getImage: ' + ex);
|
|
974
1113
|
if (Trace.isEnabled()) {
|
|
975
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1114
|
+
CLog(CLogTypes.info, 'Error in mapbox.getImage: ' + ex);
|
|
976
1115
|
}
|
|
977
|
-
|
|
1116
|
+
throw ex;
|
|
978
1117
|
}
|
|
979
1118
|
});
|
|
980
1119
|
}
|
|
981
|
-
|
|
1120
|
+
async addImage(imageId, image, nativeMap) {
|
|
982
1121
|
return new Promise((resolve, reject) => {
|
|
1122
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1123
|
+
if (!theMap) {
|
|
1124
|
+
reject('No map has been loaded');
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
if (!image.startsWith('res://')) {
|
|
1128
|
+
const appPath = knownFolders.currentApp().path;
|
|
1129
|
+
image = appPath + '/' + image.replace('~/', '');
|
|
1130
|
+
}
|
|
1131
|
+
const img = ImageSource.fromFileOrResourceSync(image);
|
|
983
1132
|
try {
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
CLog(CLogTypes.info, "Mapbox::changeUserLocationMarkerMode(): changing renderMode to '" + renderModeString + "' cameraMode '" + cameraModeString + "'");
|
|
987
|
-
}
|
|
988
|
-
theMap.userTrackingMode = this._stringToCameraMode(cameraModeString);
|
|
989
|
-
const delegate = theMap.delegate;
|
|
990
|
-
const renderMode = this._stringToRenderMode(renderModeString);
|
|
991
|
-
delegate.changeUserLocationRenderMode(renderMode);
|
|
1133
|
+
theMap.style.setImageForName(img.ios, imageId);
|
|
1134
|
+
resolve();
|
|
992
1135
|
}
|
|
993
1136
|
catch (ex) {
|
|
1137
|
+
reject('Error during addImage: ' + ex);
|
|
994
1138
|
if (Trace.isEnabled()) {
|
|
995
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1139
|
+
CLog(CLogTypes.info, 'Error in mapbox.addImage: ' + ex);
|
|
996
1140
|
}
|
|
997
|
-
|
|
1141
|
+
throw ex;
|
|
998
1142
|
}
|
|
999
1143
|
});
|
|
1000
1144
|
}
|
|
1001
|
-
|
|
1002
|
-
queryRenderedFeatures(options, nativeMap) {
|
|
1145
|
+
async removeImage(imageId, nativeMap) {
|
|
1003
1146
|
return new Promise((resolve, reject) => {
|
|
1147
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1148
|
+
if (!theMap) {
|
|
1149
|
+
reject('No map has been loaded');
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1004
1152
|
try {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
reject("Please set the 'point' parameter");
|
|
1008
|
-
return;
|
|
1009
|
-
}
|
|
1010
|
-
if (!options) {
|
|
1011
|
-
options = {};
|
|
1012
|
-
}
|
|
1013
|
-
const { x, y } = theMap.convertCoordinateToPointToView({ latitude: options.point.lat, longitude: options.point.lng }, theMap);
|
|
1014
|
-
const queryLayerIds = options.layers ? NSSet.setWithArray(iOSNativeHelper.collections.jsArrayToNSArray(options.layers)) : null;
|
|
1015
|
-
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
|
|
1016
|
-
const features = theMap.visibleFeaturesAtPointInStyleLayersWithIdentifiersPredicate({ x, y }, queryLayerIds, queryFilter);
|
|
1017
|
-
const result = [];
|
|
1018
|
-
for (let i = 0; i < features.count; i++) {
|
|
1019
|
-
const feature = features.objectAtIndex(i);
|
|
1020
|
-
const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
|
|
1021
|
-
result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
|
|
1022
|
-
}
|
|
1023
|
-
resolve(result);
|
|
1153
|
+
theMap.style.removeImageForName(imageId);
|
|
1154
|
+
resolve();
|
|
1024
1155
|
}
|
|
1025
1156
|
catch (ex) {
|
|
1157
|
+
reject('Error during removeImage: ' + ex);
|
|
1026
1158
|
if (Trace.isEnabled()) {
|
|
1027
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1159
|
+
CLog(CLogTypes.info, 'Error in mapbox.removeImage: ' + ex);
|
|
1028
1160
|
}
|
|
1029
|
-
|
|
1161
|
+
throw ex;
|
|
1030
1162
|
}
|
|
1031
1163
|
});
|
|
1032
1164
|
}
|
|
1033
|
-
|
|
1165
|
+
addMarkers(markers, nativeMap) {
|
|
1034
1166
|
return new Promise((resolve, reject) => {
|
|
1035
1167
|
try {
|
|
1036
1168
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
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);
|
|
1169
|
+
this._addMarkers(markers, theMap);
|
|
1170
|
+
resolve();
|
|
1066
1171
|
}
|
|
1067
1172
|
catch (ex) {
|
|
1068
1173
|
if (Trace.isEnabled()) {
|
|
1069
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1174
|
+
CLog(CLogTypes.info, 'Error in mapbox.addMarkers: ' + ex);
|
|
1070
1175
|
}
|
|
1071
1176
|
reject(ex);
|
|
1072
1177
|
}
|
|
1073
1178
|
});
|
|
1074
1179
|
}
|
|
1075
|
-
|
|
1180
|
+
removeMarkers(ids, nativeMap) {
|
|
1076
1181
|
return new Promise((resolve, reject) => {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
const coordinateArray = [];
|
|
1084
|
-
points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
|
|
1085
|
-
const polygonID = `polygon_${options.id || new Date().getTime()}`;
|
|
1086
|
-
if (theMap.style.sourceWithIdentifier(polygonID)) {
|
|
1087
|
-
reject("Remove the polygon with this id first with 'removePolygons': " + polygonID);
|
|
1088
|
-
return;
|
|
1089
|
-
}
|
|
1090
|
-
const geoJSON = `{
|
|
1091
|
-
"type": "FeatureCollection",
|
|
1092
|
-
"features": [
|
|
1093
|
-
{
|
|
1094
|
-
"id": ${JSON.stringify(polygonID)},
|
|
1095
|
-
"type": "Feature",
|
|
1096
|
-
"properties": {
|
|
1097
|
-
},
|
|
1098
|
-
"geometry": {
|
|
1099
|
-
"type": "Polygon",
|
|
1100
|
-
"coordinates": [${JSON.stringify(coordinateArray)}]
|
|
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);
|
|
1101
1188
|
}
|
|
1189
|
+
});
|
|
1190
|
+
if (ids) {
|
|
1191
|
+
_markers = _markers.filter((marker) => ids.indexOf(marker.id) < 0);
|
|
1102
1192
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
strokeLayer.lineOpacity = NSExpression.expressionForConstantValue(options.strokeOpacity === undefined ? 1 : options.strokeOpacity);
|
|
1117
|
-
theMap.style.addLayer(strokeLayer);
|
|
1193
|
+
else {
|
|
1194
|
+
_markers = [];
|
|
1195
|
+
}
|
|
1196
|
+
if (markersToRemove.length > 0) {
|
|
1197
|
+
theMap.removeAnnotations(markersToRemove);
|
|
1198
|
+
}
|
|
1199
|
+
resolve();
|
|
1200
|
+
}
|
|
1201
|
+
catch (ex) {
|
|
1202
|
+
if (Trace.isEnabled()) {
|
|
1203
|
+
CLog(CLogTypes.info, 'Error in mapbox.removeMarkers: ' + ex);
|
|
1204
|
+
}
|
|
1205
|
+
reject(ex);
|
|
1118
1206
|
}
|
|
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
1207
|
});
|
|
1125
1208
|
}
|
|
1126
|
-
|
|
1209
|
+
setCenter(options, nativeMap) {
|
|
1127
1210
|
return new Promise((resolve, reject) => {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
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();
|
|
1133
1217
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
reject(
|
|
1139
|
-
return;
|
|
1218
|
+
catch (ex) {
|
|
1219
|
+
if (Trace.isEnabled()) {
|
|
1220
|
+
CLog(CLogTypes.info, 'Error in mapbox.setCenter: ' + ex);
|
|
1221
|
+
}
|
|
1222
|
+
reject(ex);
|
|
1140
1223
|
}
|
|
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
1224
|
});
|
|
1156
1225
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1174
|
-
ids.forEach((id) => this.removePolyById(theMap, polyType + id));
|
|
1175
|
-
resolve();
|
|
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
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
catch (ex) {
|
|
1237
|
+
if (Trace.isEnabled()) {
|
|
1238
|
+
CLog(CLogTypes.info, 'Error in mapbox.getCenter: ' + ex);
|
|
1239
|
+
}
|
|
1240
|
+
reject(ex);
|
|
1241
|
+
}
|
|
1176
1242
|
});
|
|
1177
1243
|
}
|
|
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) {
|
|
1244
|
+
setZoomLevel(options, nativeMap) {
|
|
1185
1245
|
return new Promise((resolve, reject) => {
|
|
1186
1246
|
try {
|
|
1187
1247
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
left: padding,
|
|
1194
|
-
bottom: padding,
|
|
1195
|
-
right: padding
|
|
1196
|
-
};
|
|
1197
|
-
const bounds = {
|
|
1198
|
-
sw: CLLocationCoordinate2DMake(options.bounds.south, options.bounds.west),
|
|
1199
|
-
ne: CLLocationCoordinate2DMake(options.bounds.north, options.bounds.east)
|
|
1200
|
-
};
|
|
1201
|
-
cam = theMap.cameraThatFitsCoordinateBoundsEdgePadding(bounds, insets);
|
|
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();
|
|
1202
1253
|
}
|
|
1203
1254
|
else {
|
|
1204
|
-
|
|
1205
|
-
if (target === undefined) {
|
|
1206
|
-
reject("Please set the 'target' parameter");
|
|
1207
|
-
return;
|
|
1208
|
-
}
|
|
1209
|
-
cam = theMap.camera;
|
|
1210
|
-
cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
|
|
1211
|
-
}
|
|
1212
|
-
if (options.altitude) {
|
|
1213
|
-
cam.altitude = options.altitude;
|
|
1214
|
-
}
|
|
1215
|
-
if (options.bearing) {
|
|
1216
|
-
cam.heading = options.bearing;
|
|
1255
|
+
reject('invalid ZoomLevel, use any double value from 0 to 20 (like 8.3)');
|
|
1217
1256
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1257
|
+
}
|
|
1258
|
+
catch (ex) {
|
|
1259
|
+
if (Trace.isEnabled()) {
|
|
1260
|
+
CLog(CLogTypes.info, 'Error in mapbox.setZoomLevel: ' + ex);
|
|
1220
1261
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1262
|
+
reject(ex);
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
getZoomLevel(nativeMap) {
|
|
1267
|
+
return new Promise((resolve, reject) => {
|
|
1268
|
+
try {
|
|
1269
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1270
|
+
resolve(theMap.zoomLevel);
|
|
1271
|
+
}
|
|
1272
|
+
catch (ex) {
|
|
1273
|
+
if (Trace.isEnabled()) {
|
|
1274
|
+
CLog(CLogTypes.info, 'Error in mapbox.getZoomLevel: ' + ex);
|
|
1223
1275
|
}
|
|
1224
|
-
|
|
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;
|
|
1225
1287
|
theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
|
|
1226
1288
|
setTimeout(() => {
|
|
1227
1289
|
resolve();
|
|
@@ -1229,341 +1291,375 @@ export class Mapbox extends MapboxCommon {
|
|
|
1229
1291
|
}
|
|
1230
1292
|
catch (ex) {
|
|
1231
1293
|
if (Trace.isEnabled()) {
|
|
1232
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1294
|
+
CLog(CLogTypes.info, 'Error in mapbox.setTilt: ' + ex);
|
|
1233
1295
|
}
|
|
1234
1296
|
reject(ex);
|
|
1235
1297
|
}
|
|
1236
1298
|
});
|
|
1237
1299
|
}
|
|
1238
|
-
|
|
1300
|
+
getTilt(nativeMap) {
|
|
1239
1301
|
return new Promise((resolve, reject) => {
|
|
1240
1302
|
try {
|
|
1241
1303
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1242
|
-
|
|
1243
|
-
reject('No map has been loaded');
|
|
1244
|
-
return;
|
|
1245
|
-
}
|
|
1246
|
-
theMap['mapTapHandler'] = MapTapHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
|
|
1247
|
-
const tapGestureRecognizer = UITapGestureRecognizer.alloc().initWithTargetAction(theMap['mapTapHandler'], 'tap');
|
|
1248
|
-
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1249
|
-
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1250
|
-
if (recognizer instanceof UITapGestureRecognizer) {
|
|
1251
|
-
tapGestureRecognizer.requireGestureRecognizerToFail(recognizer);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
theMap.addGestureRecognizer(tapGestureRecognizer);
|
|
1255
|
-
resolve();
|
|
1304
|
+
resolve(theMap.camera.pitch);
|
|
1256
1305
|
}
|
|
1257
1306
|
catch (ex) {
|
|
1258
1307
|
if (Trace.isEnabled()) {
|
|
1259
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1308
|
+
CLog(CLogTypes.info, 'Error in mapbox.getTilt: ' + ex);
|
|
1260
1309
|
}
|
|
1261
1310
|
reject(ex);
|
|
1262
1311
|
}
|
|
1263
1312
|
});
|
|
1264
1313
|
}
|
|
1265
|
-
|
|
1314
|
+
getUserLocation(nativeMap) {
|
|
1266
1315
|
return new Promise((resolve, reject) => {
|
|
1267
1316
|
try {
|
|
1268
1317
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1318
|
+
const loc = theMap.userLocation;
|
|
1319
|
+
if (loc === null) {
|
|
1320
|
+
reject('Location not available');
|
|
1272
1321
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1276
|
-
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1277
|
-
if (recognizer instanceof UILongPressGestureRecognizer) {
|
|
1278
|
-
longPressGestureRecognizer.requireGestureRecognizerToFail(recognizer);
|
|
1279
|
-
}
|
|
1322
|
+
else {
|
|
1323
|
+
resolve(_getLocation(loc));
|
|
1280
1324
|
}
|
|
1281
|
-
theMap.addGestureRecognizer(longPressGestureRecognizer);
|
|
1282
|
-
resolve();
|
|
1283
1325
|
}
|
|
1284
1326
|
catch (ex) {
|
|
1285
1327
|
if (Trace.isEnabled()) {
|
|
1286
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1328
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1287
1329
|
}
|
|
1288
1330
|
reject(ex);
|
|
1289
1331
|
}
|
|
1290
1332
|
});
|
|
1291
1333
|
}
|
|
1292
|
-
|
|
1334
|
+
_stringToCameraMode(mode) {
|
|
1335
|
+
switch (mode) {
|
|
1336
|
+
case 'NONE':
|
|
1337
|
+
return 0;
|
|
1338
|
+
case 'NONE_COMPASS':
|
|
1339
|
+
if (Trace.isEnabled()) {
|
|
1340
|
+
CLog(CLogTypes.info, '_stringToCameraMode(): NONE_COMPASS unsupported on iOS');
|
|
1341
|
+
}
|
|
1342
|
+
return 0;
|
|
1343
|
+
case 'NONE_GPS':
|
|
1344
|
+
if (Trace.isEnabled()) {
|
|
1345
|
+
CLog(CLogTypes.info, '_stringToCameraMode(): NONE_GPS unsupported on iOS');
|
|
1346
|
+
}
|
|
1347
|
+
return 0;
|
|
1348
|
+
case 'TRACKING':
|
|
1349
|
+
return 1;
|
|
1350
|
+
case 'TRACKING_COMPASS':
|
|
1351
|
+
return 2;
|
|
1352
|
+
case 'TRACKING_GPS':
|
|
1353
|
+
return 1;
|
|
1354
|
+
case 'TRACKING_GPS_NORTH':
|
|
1355
|
+
return 3;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
_stringToRenderMode(mode) {
|
|
1359
|
+
let renderMode;
|
|
1360
|
+
switch (mode) {
|
|
1361
|
+
case 'NORMAL':
|
|
1362
|
+
return 'NORMAL';
|
|
1363
|
+
case 'COMPASS':
|
|
1364
|
+
return 'COMPASS';
|
|
1365
|
+
case 'GPS':
|
|
1366
|
+
return 'GPS';
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
showUserLocationMarker(options, nativeMap) {
|
|
1293
1370
|
return new Promise((resolve, reject) => {
|
|
1294
1371
|
try {
|
|
1295
1372
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
recognizer.addTargetAction(theMap['mapPanHandler'], 'pan');
|
|
1305
|
-
break;
|
|
1306
|
-
}
|
|
1373
|
+
theMap.showsUserLocation = true;
|
|
1374
|
+
theMap.userTrackingMode = this._stringToCameraMode(options.cameraMode);
|
|
1375
|
+
theMap.showsUserHeadingIndicator = true;
|
|
1376
|
+
this.userLocationRenderMode = this._stringToRenderMode(options.renderMode);
|
|
1377
|
+
const delegate = theMap.delegate;
|
|
1378
|
+
delegate.changeUserLocationRenderMode(this.userLocationRenderMode);
|
|
1379
|
+
if (typeof options.clickListener != 'undefined') {
|
|
1380
|
+
delegate.setUserLocationClickListener(options.clickListener);
|
|
1307
1381
|
}
|
|
1308
1382
|
resolve();
|
|
1309
1383
|
}
|
|
1310
1384
|
catch (ex) {
|
|
1311
1385
|
if (Trace.isEnabled()) {
|
|
1312
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1386
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1313
1387
|
}
|
|
1314
1388
|
reject(ex);
|
|
1315
1389
|
}
|
|
1316
1390
|
});
|
|
1317
1391
|
}
|
|
1318
|
-
|
|
1392
|
+
hideUserLocationMarker(nativeMap) {
|
|
1319
1393
|
return new Promise((resolve, reject) => {
|
|
1320
1394
|
try {
|
|
1321
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1322
|
-
if (!theMap) {
|
|
1323
|
-
reject('No map has been loaded');
|
|
1324
|
-
return;
|
|
1325
|
-
}
|
|
1326
|
-
theMap['mapOnMoveBeginHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, theMap);
|
|
1327
|
-
theMap['mapOnMoveBeginHandler'].setOnMoveBegin();
|
|
1328
|
-
for (let i = 0; i < theMap.gestureRecognizers.count; i++) {
|
|
1329
|
-
const recognizer = theMap.gestureRecognizers.objectAtIndex(i);
|
|
1330
|
-
if (recognizer instanceof UIPanGestureRecognizer) {
|
|
1331
|
-
recognizer.addTargetAction(theMap['mapOnMoveBeginHandler'], 'pan');
|
|
1332
|
-
break;
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
1395
|
resolve();
|
|
1336
1396
|
}
|
|
1337
1397
|
catch (ex) {
|
|
1338
1398
|
if (Trace.isEnabled()) {
|
|
1339
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1399
|
+
CLog(CLogTypes.info, 'Error in mapbox.getUserLocation: ' + ex);
|
|
1340
1400
|
}
|
|
1341
1401
|
reject(ex);
|
|
1342
1402
|
}
|
|
1343
1403
|
});
|
|
1344
1404
|
}
|
|
1345
|
-
|
|
1346
|
-
return Promise.reject("'setOnFlingListener' is not supported on iOS");
|
|
1347
|
-
}
|
|
1348
|
-
async setOnCameraMoveListener(listener, nativeMap) {
|
|
1349
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1350
|
-
if (theMap) {
|
|
1351
|
-
theMap.delegate.setCameraChangedListener(listener);
|
|
1352
|
-
}
|
|
1353
|
-
else {
|
|
1354
|
-
return Promise.reject('No map has been loaded');
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
setOnCameraMoveCancelListener(listener, nativeMap) {
|
|
1358
|
-
return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
|
|
1359
|
-
}
|
|
1360
|
-
async setOnCameraIdleListener(listener, nativeMap) {
|
|
1361
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1362
|
-
if (theMap) {
|
|
1363
|
-
theMap.delegate.setCameraIdledListener(listener);
|
|
1364
|
-
}
|
|
1365
|
-
else {
|
|
1366
|
-
return Promise.reject('No map has been loaded');
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
getViewport(nativeMap) {
|
|
1405
|
+
changeUserLocationMarkerMode(renderModeString, cameraModeString, nativeMap) {
|
|
1370
1406
|
return new Promise((resolve, reject) => {
|
|
1371
1407
|
try {
|
|
1372
1408
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1373
|
-
if (
|
|
1374
|
-
|
|
1375
|
-
return;
|
|
1409
|
+
if (Trace.isEnabled()) {
|
|
1410
|
+
CLog(CLogTypes.info, "Mapbox::changeUserLocationMarkerMode(): changing renderMode to '" + renderModeString + "' cameraMode '" + cameraModeString + "'");
|
|
1376
1411
|
}
|
|
1377
|
-
|
|
1378
|
-
const
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
south: visibleBounds.sw.latitude,
|
|
1382
|
-
west: visibleBounds.sw.longitude
|
|
1383
|
-
};
|
|
1384
|
-
resolve({
|
|
1385
|
-
bounds,
|
|
1386
|
-
zoomLevel: theMap.zoomLevel
|
|
1387
|
-
});
|
|
1412
|
+
theMap.userTrackingMode = this._stringToCameraMode(cameraModeString);
|
|
1413
|
+
const delegate = theMap.delegate;
|
|
1414
|
+
const renderMode = this._stringToRenderMode(renderModeString);
|
|
1415
|
+
delegate.changeUserLocationRenderMode(renderMode);
|
|
1388
1416
|
}
|
|
1389
1417
|
catch (ex) {
|
|
1390
1418
|
if (Trace.isEnabled()) {
|
|
1391
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1419
|
+
CLog(CLogTypes.info, 'Error in mapbox.showUserLocationMarker: ' + ex);
|
|
1392
1420
|
}
|
|
1393
1421
|
reject(ex);
|
|
1394
1422
|
}
|
|
1395
1423
|
});
|
|
1396
1424
|
}
|
|
1397
|
-
|
|
1425
|
+
forceUserLocationUpdate(location, nativeMap) { }
|
|
1426
|
+
queryRenderedFeatures(options, nativeMap) {
|
|
1398
1427
|
return new Promise((resolve, reject) => {
|
|
1399
1428
|
try {
|
|
1400
1429
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1401
|
-
if (
|
|
1402
|
-
reject(
|
|
1430
|
+
if (options.point === undefined) {
|
|
1431
|
+
reject("Please set the 'point' parameter");
|
|
1403
1432
|
return;
|
|
1404
1433
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
};
|
|
1409
|
-
const
|
|
1410
|
-
const
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1434
|
+
if (!options) {
|
|
1435
|
+
options = {};
|
|
1436
|
+
}
|
|
1437
|
+
const { x, y } = theMap.convertCoordinateToPointToView({ latitude: options.point.lat, longitude: options.point.lng }, theMap);
|
|
1438
|
+
const queryLayerIds = options.layers ? NSSet.setWithArray(Utils.ios.collections.jsArrayToNSArray(options.layers)) : null;
|
|
1439
|
+
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
|
|
1440
|
+
const features = theMap.visibleFeaturesAtPointInStyleLayersWithIdentifiersPredicate({ x, y }, queryLayerIds, queryFilter);
|
|
1441
|
+
const result = [];
|
|
1442
|
+
for (let i = 0; i < features.count; i++) {
|
|
1443
|
+
const feature = features.objectAtIndex(i);
|
|
1444
|
+
const featureJson = NSJSONSerialization.dataWithJSONObjectOptionsError(feature.geoJSONDictionary(), 0);
|
|
1445
|
+
result.push(JSON.parse(NSString.alloc().initWithDataEncoding(featureJson, NSUTF8StringEncoding)));
|
|
1446
|
+
}
|
|
1447
|
+
resolve(result);
|
|
1418
1448
|
}
|
|
1419
1449
|
catch (ex) {
|
|
1420
1450
|
if (Trace.isEnabled()) {
|
|
1421
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1451
|
+
CLog(CLogTypes.info, 'Error in mapbox.queryRenderedFeatures: ' + ex);
|
|
1422
1452
|
}
|
|
1423
1453
|
reject(ex);
|
|
1424
1454
|
}
|
|
1425
1455
|
});
|
|
1426
1456
|
}
|
|
1427
|
-
|
|
1457
|
+
querySourceFeatures(sourceId, options, nativeMap) {
|
|
1428
1458
|
return new Promise((resolve, reject) => {
|
|
1429
1459
|
try {
|
|
1430
|
-
const
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
const bounds = {
|
|
1434
|
-
sw: swCoordinate,
|
|
1435
|
-
ne: neCoordinate
|
|
1436
|
-
};
|
|
1437
|
-
const region = MGLTilePyramidOfflineRegion.alloc().initWithStyleURLBoundsFromZoomLevelToZoomLevel(styleURL, bounds, options.minZoom, options.maxZoom);
|
|
1438
|
-
if (options.accessToken) {
|
|
1439
|
-
MGLAccountManager.accessToken = options.accessToken;
|
|
1460
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1461
|
+
if (!options) {
|
|
1462
|
+
options = {};
|
|
1440
1463
|
}
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
const offlinePackProgress = offlinePack.progress;
|
|
1445
|
-
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1446
|
-
const complete = offlinePackProgress.countOfResourcesCompleted === offlinePackProgress.countOfResourcesExpected;
|
|
1447
|
-
options.onProgress({
|
|
1448
|
-
name: userInfo.objectForKey('name'),
|
|
1449
|
-
completed: offlinePackProgress.countOfResourcesCompleted,
|
|
1450
|
-
expected: offlinePackProgress.countOfResourcesExpected,
|
|
1451
|
-
percentage: Math.round((offlinePackProgress.countOfResourcesCompleted / offlinePackProgress.countOfResourcesExpected) * 10000) / 100,
|
|
1452
|
-
complete
|
|
1453
|
-
});
|
|
1454
|
-
if (complete) {
|
|
1455
|
-
resolve();
|
|
1456
|
-
}
|
|
1457
|
-
});
|
|
1464
|
+
const source = theMap.style.sourceWithIdentifier(sourceId);
|
|
1465
|
+
if (!source) {
|
|
1466
|
+
throw new Error(`Source with id "${sourceId}" not found.`);
|
|
1458
1467
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
});
|
|
1468
|
-
_addObserver(MGLOfflinePackMaximumMapboxTilesReachedNotification, (notification) => {
|
|
1469
|
-
const offlinePack = notification.object;
|
|
1470
|
-
const userInfo = NSKeyedUnarchiver.unarchiveObjectWithData(offlinePack.context);
|
|
1471
|
-
const maximumCount = notification.userInfo[MGLOfflinePackUserInfoKeyMaximumCount];
|
|
1472
|
-
console.log(`Offline region '${userInfo.objectForKey('name')}' reached the tile limit of ${maximumCount}`);
|
|
1473
|
-
});
|
|
1474
|
-
const userInfo = { name: options.name };
|
|
1475
|
-
const context = NSKeyedArchiver.archivedDataWithRootObject(userInfo);
|
|
1476
|
-
MGLOfflineStorage.sharedOfflineStorage.addPackForRegionWithContextCompletionHandler(region, context, (pack, error) => {
|
|
1477
|
-
if (error) {
|
|
1478
|
-
reject(error.localizedFailureReason);
|
|
1479
|
-
}
|
|
1480
|
-
else {
|
|
1481
|
-
pack.resume();
|
|
1468
|
+
let features;
|
|
1469
|
+
const queryFilter = options.filter ? FilterParser.parseJson(options.filter) : null;
|
|
1470
|
+
if (source instanceof MGLShapeSource) {
|
|
1471
|
+
features = source.featuresMatchingPredicate(queryFilter);
|
|
1472
|
+
}
|
|
1473
|
+
else if (source instanceof MGLVectorTileSource) {
|
|
1474
|
+
if (!options.sourceLayer) {
|
|
1475
|
+
throw new Error('The option "sourceLayer" is required for vector sources.');
|
|
1482
1476
|
}
|
|
1483
|
-
|
|
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);
|
|
1484
1490
|
}
|
|
1485
1491
|
catch (ex) {
|
|
1486
1492
|
if (Trace.isEnabled()) {
|
|
1487
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1493
|
+
CLog(CLogTypes.info, 'Error in mapbox.querySourceFeatures: ' + ex);
|
|
1488
1494
|
}
|
|
1489
1495
|
reject(ex);
|
|
1490
1496
|
}
|
|
1491
1497
|
});
|
|
1492
1498
|
}
|
|
1493
|
-
|
|
1499
|
+
addPolygon(options, nativeMap) {
|
|
1494
1500
|
return new Promise((resolve, reject) => {
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
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
|
+
}
|
|
1518
1526
|
}
|
|
1519
|
-
|
|
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;
|
|
1520
1557
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
reject(
|
|
1558
|
+
const coordinateArray = [];
|
|
1559
|
+
points.forEach((point) => coordinateArray.push([point.lng, point.lat]));
|
|
1560
|
+
const polylineID = 'polyline_' + (options.id || new Date().getTime());
|
|
1561
|
+
if (theMap.style.sourceWithIdentifier(polylineID)) {
|
|
1562
|
+
reject("Remove the polyline with this id first with 'removePolylines': " + polylineID);
|
|
1563
|
+
return;
|
|
1526
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();
|
|
1527
1579
|
});
|
|
1528
1580
|
}
|
|
1529
|
-
|
|
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) {
|
|
1530
1609
|
return new Promise((resolve, reject) => {
|
|
1531
1610
|
try {
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
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);
|
|
1535
1626
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
const name = userInfo.objectForKey('name');
|
|
1542
|
-
if (name === options.name) {
|
|
1543
|
-
found = true;
|
|
1544
|
-
MGLOfflineStorage.sharedOfflineStorage.removePackWithCompletionHandler(pack, (error) => {
|
|
1545
|
-
if (error) {
|
|
1546
|
-
reject(error.localizedFailureReason);
|
|
1547
|
-
}
|
|
1548
|
-
else {
|
|
1549
|
-
resolve();
|
|
1550
|
-
}
|
|
1551
|
-
});
|
|
1627
|
+
else {
|
|
1628
|
+
const target = options.target;
|
|
1629
|
+
if (target === undefined) {
|
|
1630
|
+
reject("Please set the 'target' parameter");
|
|
1631
|
+
return;
|
|
1552
1632
|
}
|
|
1633
|
+
cam = theMap.camera;
|
|
1634
|
+
cam.centerCoordinate = CLLocationCoordinate2DMake(target.lat, target.lng);
|
|
1553
1635
|
}
|
|
1554
|
-
if (
|
|
1555
|
-
|
|
1636
|
+
if (options.altitude) {
|
|
1637
|
+
cam.altitude = options.altitude;
|
|
1638
|
+
}
|
|
1639
|
+
if (options.bearing) {
|
|
1640
|
+
cam.heading = options.bearing;
|
|
1641
|
+
}
|
|
1642
|
+
if (options.tilt) {
|
|
1643
|
+
cam.pitch = options.tilt;
|
|
1644
|
+
}
|
|
1645
|
+
if (options.zoomLevel && options.target) {
|
|
1646
|
+
cam.altitude = MGLAltitudeForZoomLevel(options.zoomLevel, cam.pitch, options.target.lat, theMap.frame.size);
|
|
1556
1647
|
}
|
|
1648
|
+
const durationMs = options.duration ? options.duration : 10000;
|
|
1649
|
+
theMap.setCameraWithDurationAnimationTimingFunction(cam, durationMs / 1000, CAMediaTimingFunction.functionWithName(kCAMediaTimingFunctionEaseInEaseOut));
|
|
1650
|
+
setTimeout(() => {
|
|
1651
|
+
resolve();
|
|
1652
|
+
}, durationMs);
|
|
1557
1653
|
}
|
|
1558
1654
|
catch (ex) {
|
|
1559
1655
|
if (Trace.isEnabled()) {
|
|
1560
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1656
|
+
CLog(CLogTypes.info, 'Error in mapbox.animateCamera: ' + ex);
|
|
1561
1657
|
}
|
|
1562
1658
|
reject(ex);
|
|
1563
1659
|
}
|
|
1564
1660
|
});
|
|
1565
1661
|
}
|
|
1566
|
-
|
|
1662
|
+
setOnMapClickListener(listener, nativeMap) {
|
|
1567
1663
|
return new Promise((resolve, reject) => {
|
|
1568
1664
|
try {
|
|
1569
1665
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1571,17 +1667,26 @@ export class Mapbox extends MapboxCommon {
|
|
|
1571
1667
|
reject('No map has been loaded');
|
|
1572
1668
|
return;
|
|
1573
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);
|
|
1574
1679
|
resolve();
|
|
1575
1680
|
}
|
|
1576
1681
|
catch (ex) {
|
|
1577
1682
|
if (Trace.isEnabled()) {
|
|
1578
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1683
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
|
|
1579
1684
|
}
|
|
1580
1685
|
reject(ex);
|
|
1581
1686
|
}
|
|
1582
1687
|
});
|
|
1583
1688
|
}
|
|
1584
|
-
|
|
1689
|
+
setOnMapLongClickListener(listener, nativeMap) {
|
|
1585
1690
|
return new Promise((resolve, reject) => {
|
|
1586
1691
|
try {
|
|
1587
1692
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1589,159 +1694,88 @@ export class Mapbox extends MapboxCommon {
|
|
|
1589
1694
|
reject('No map has been loaded');
|
|
1590
1695
|
return;
|
|
1591
1696
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
1600
|
-
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1601
|
-
const geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
1602
|
-
source.shape = geoJsonShape;
|
|
1603
|
-
break;
|
|
1604
|
-
default:
|
|
1605
|
-
reject('Invalid source type: ' + options['type']);
|
|
1606
|
-
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
|
+
}
|
|
1607
1704
|
}
|
|
1705
|
+
theMap.addGestureRecognizer(longPressGestureRecognizer);
|
|
1706
|
+
resolve();
|
|
1608
1707
|
}
|
|
1609
1708
|
catch (ex) {
|
|
1610
1709
|
if (Trace.isEnabled()) {
|
|
1611
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1710
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMapClickListener: ' + ex);
|
|
1612
1711
|
}
|
|
1613
1712
|
reject(ex);
|
|
1614
1713
|
}
|
|
1615
|
-
});
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
|
-
return new Promise((resolve, reject) => {
|
|
1619
|
-
try {
|
|
1620
|
-
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
else {
|
|
1636
|
-
const sourceOptions = {};
|
|
1637
|
-
if (options.minzoom !== undefined) {
|
|
1638
|
-
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
1639
|
-
}
|
|
1640
|
-
if (options.maxzoom !== undefined) {
|
|
1641
|
-
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
1642
|
-
}
|
|
1643
|
-
if (options.scheme) {
|
|
1644
|
-
switch (options.scheme) {
|
|
1645
|
-
case 'xyz':
|
|
1646
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
1647
|
-
break;
|
|
1648
|
-
case 'tms':
|
|
1649
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
1650
|
-
break;
|
|
1651
|
-
default:
|
|
1652
|
-
throw new Error('Unknown raster tile scheme.');
|
|
1653
|
-
}
|
|
1654
|
-
}
|
|
1655
|
-
if (options.bounds) {
|
|
1656
|
-
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
1657
|
-
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
1658
|
-
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
1659
|
-
});
|
|
1660
|
-
}
|
|
1661
|
-
source = MGLVectorTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
1662
|
-
}
|
|
1663
|
-
break;
|
|
1664
|
-
}
|
|
1665
|
-
case 'geojson':
|
|
1666
|
-
if (theMap.style.sourceWithIdentifier(id)) {
|
|
1667
|
-
reject("Remove the layer with this id first with 'removeLayer': " + id);
|
|
1668
|
-
return;
|
|
1669
|
-
}
|
|
1670
|
-
let geoJsonShape;
|
|
1671
|
-
if (options.data) {
|
|
1672
|
-
const content = NSString.stringWithString(JSON.stringify(options.data));
|
|
1673
|
-
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
|
|
1674
|
-
geoJsonShape = MGLShape.shapeWithDataEncodingError(nsData, NSUTF8StringEncoding);
|
|
1675
|
-
}
|
|
1676
|
-
const sourceOptions = {};
|
|
1677
|
-
if (options.minzoom !== undefined) {
|
|
1678
|
-
sourceOptions[MGLShapeSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
1679
|
-
}
|
|
1680
|
-
if (options.maxzoom !== undefined) {
|
|
1681
|
-
sourceOptions[MGLShapeSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
1682
|
-
}
|
|
1683
|
-
if (options.cluster) {
|
|
1684
|
-
sourceOptions[MGLShapeSourceOptionClustered] = true;
|
|
1685
|
-
sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
|
|
1686
|
-
sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
|
|
1687
|
-
}
|
|
1688
|
-
source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
|
|
1689
|
-
break;
|
|
1690
|
-
case 'raster': {
|
|
1691
|
-
const sourceOptions = {
|
|
1692
|
-
[MGLTileSourceOptionTileSize]: options.tileSize || 256
|
|
1693
|
-
};
|
|
1694
|
-
if (options.minzoom !== undefined) {
|
|
1695
|
-
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
1696
|
-
}
|
|
1697
|
-
if (options.maxzoom !== undefined) {
|
|
1698
|
-
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
1699
|
-
}
|
|
1700
|
-
if (options.scheme) {
|
|
1701
|
-
switch (options.scheme || 'xyz') {
|
|
1702
|
-
case 'xyz':
|
|
1703
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
1704
|
-
break;
|
|
1705
|
-
case 'tms':
|
|
1706
|
-
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
1707
|
-
break;
|
|
1708
|
-
default:
|
|
1709
|
-
throw new Error('Unknown raster tile scheme.');
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
if (options.bounds) {
|
|
1713
|
-
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
1714
|
-
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
1715
|
-
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
1716
|
-
});
|
|
1717
|
-
}
|
|
1718
|
-
source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
setOnScrollListener(listener, nativeMap) {
|
|
1717
|
+
return new Promise((resolve, reject) => {
|
|
1718
|
+
try {
|
|
1719
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1720
|
+
if (!theMap) {
|
|
1721
|
+
reject('No map has been loaded');
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
if (theMap['mapPanHandler'] === undefined) {
|
|
1725
|
+
theMap['mapPanHandler'] = MapPanHandlerImpl.initWithOwnerAndListenerForMap(new WeakRef(this), listener, 2, theMap);
|
|
1726
|
+
}
|
|
1727
|
+
else {
|
|
1728
|
+
theMap['mapPanHandler'].addListener(2, listener);
|
|
1729
|
+
}
|
|
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');
|
|
1719
1734
|
break;
|
|
1720
1735
|
}
|
|
1721
|
-
default:
|
|
1722
|
-
reject('Invalid source type: ' + options['type']);
|
|
1723
|
-
return;
|
|
1724
1736
|
}
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1737
|
+
resolve();
|
|
1738
|
+
}
|
|
1739
|
+
catch (ex) {
|
|
1740
|
+
if (Trace.isEnabled()) {
|
|
1741
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnScrollListener: ' + ex);
|
|
1742
|
+
}
|
|
1743
|
+
reject(ex);
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
setOnMoveBeginListener(listener, nativeMap) {
|
|
1748
|
+
return new Promise((resolve, reject) => {
|
|
1749
|
+
try {
|
|
1750
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1751
|
+
if (!theMap) {
|
|
1752
|
+
reject('No map has been loaded');
|
|
1731
1753
|
return;
|
|
1732
1754
|
}
|
|
1733
|
-
theMap
|
|
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
|
+
}
|
|
1734
1768
|
resolve();
|
|
1735
1769
|
}
|
|
1736
1770
|
catch (ex) {
|
|
1737
1771
|
if (Trace.isEnabled()) {
|
|
1738
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1772
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMoveBeginListener: ' + ex);
|
|
1739
1773
|
}
|
|
1740
1774
|
reject(ex);
|
|
1741
1775
|
}
|
|
1742
1776
|
});
|
|
1743
1777
|
}
|
|
1744
|
-
|
|
1778
|
+
setOnMoveEndListener(listener, nativeMap) {
|
|
1745
1779
|
return new Promise((resolve, reject) => {
|
|
1746
1780
|
try {
|
|
1747
1781
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1749,86 +1783,82 @@ export class Mapbox extends MapboxCommon {
|
|
|
1749
1783
|
reject('No map has been loaded');
|
|
1750
1784
|
return;
|
|
1751
1785
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
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
|
+
}
|
|
1756
1798
|
}
|
|
1757
|
-
theMap.style.removeSource(source);
|
|
1758
1799
|
resolve();
|
|
1759
1800
|
}
|
|
1760
1801
|
catch (ex) {
|
|
1761
1802
|
if (Trace.isEnabled()) {
|
|
1762
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1803
|
+
CLog(CLogTypes.info, 'Error in mapbox.setOnMoveEndListener: ' + ex);
|
|
1763
1804
|
}
|
|
1764
1805
|
reject(ex);
|
|
1765
1806
|
}
|
|
1766
1807
|
});
|
|
1767
1808
|
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
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);
|
|
1774
1816
|
}
|
|
1775
1817
|
else {
|
|
1776
|
-
|
|
1777
|
-
}
|
|
1778
|
-
const layer = await LayerFactory.createLayer(style, source);
|
|
1779
|
-
if (belowLayerId) {
|
|
1780
|
-
const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
|
|
1781
|
-
if (belowlayer) {
|
|
1782
|
-
theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
|
|
1783
|
-
return;
|
|
1784
|
-
}
|
|
1818
|
+
return Promise.reject('No map has been loaded');
|
|
1785
1819
|
}
|
|
1786
|
-
theMap.style.addLayer(layer.getNativeInstance());
|
|
1787
1820
|
}
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
if (Trace.isEnabled()) {
|
|
1791
|
-
CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
|
|
1792
|
-
}
|
|
1793
|
-
const layer = theMap.style.layerWithIdentifier(id);
|
|
1794
|
-
if (Trace.isEnabled()) {
|
|
1795
|
-
CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
|
|
1796
|
-
}
|
|
1797
|
-
if (!layer) {
|
|
1798
|
-
throw new Error("Layer '" + id + "' not found when attempting to remove it.");
|
|
1799
|
-
}
|
|
1800
|
-
theMap.style.removeLayer(layer);
|
|
1801
|
-
if (Trace.isEnabled()) {
|
|
1802
|
-
CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
|
|
1803
|
-
}
|
|
1821
|
+
setOnCameraMoveCancelListener(listener, nativeMap) {
|
|
1822
|
+
return Promise.reject("'setOnCameraMoveCancelListener' not currently supported on iOS");
|
|
1804
1823
|
}
|
|
1805
|
-
async
|
|
1806
|
-
const theMap =
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
if (!lineSource) {
|
|
1810
|
-
throw new Error(`no source found with id: ${sId}`);
|
|
1811
|
-
}
|
|
1812
|
-
try {
|
|
1813
|
-
const lineFeatures = lineSource.featuresMatchingPredicate(FilterParser.parseJson(['==', '$type', 'LineString']));
|
|
1814
|
-
if (lineFeatures.count === 0) {
|
|
1815
|
-
throw new Error('no line string feature found');
|
|
1816
|
-
}
|
|
1817
|
-
const lineFeature = lineFeatures.objectAtIndex(0);
|
|
1818
|
-
const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
|
|
1819
|
-
const newCoordPointer = new interop.Reference(newCoord);
|
|
1820
|
-
lineFeature.appendCoordinatesCount(newCoordPointer, 1);
|
|
1821
|
-
lineSource.shape = lineFeature;
|
|
1824
|
+
async setOnCameraIdleListener(listener, nativeMap) {
|
|
1825
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
1826
|
+
if (theMap) {
|
|
1827
|
+
theMap.delegate.setCameraIdledListener(listener);
|
|
1822
1828
|
}
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
throw error;
|
|
1829
|
+
else {
|
|
1830
|
+
return Promise.reject('No map has been loaded');
|
|
1826
1831
|
}
|
|
1827
1832
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
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
|
+
});
|
|
1830
1860
|
}
|
|
1831
|
-
|
|
1861
|
+
setViewport(options, nativeMap) {
|
|
1832
1862
|
return new Promise((resolve, reject) => {
|
|
1833
1863
|
try {
|
|
1834
1864
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1836,41 +1866,163 @@ export class Mapbox extends MapboxCommon {
|
|
|
1836
1866
|
reject('No map has been loaded');
|
|
1837
1867
|
return;
|
|
1838
1868
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
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
|
+
});
|
|
1842
1977
|
}
|
|
1843
|
-
|
|
1844
|
-
resolve();
|
|
1978
|
+
resolve(regions);
|
|
1845
1979
|
}
|
|
1846
1980
|
catch (ex) {
|
|
1847
1981
|
if (Trace.isEnabled()) {
|
|
1848
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
1982
|
+
CLog(CLogTypes.info, 'Error in mapbox.listOfflineRegions: ' + ex);
|
|
1849
1983
|
}
|
|
1850
1984
|
reject(ex);
|
|
1851
1985
|
}
|
|
1852
1986
|
});
|
|
1853
1987
|
}
|
|
1854
|
-
|
|
1988
|
+
deleteOfflineRegion(options) {
|
|
1855
1989
|
return new Promise((resolve, reject) => {
|
|
1856
1990
|
try {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
reject('No map has been loaded');
|
|
1991
|
+
if (!options || (!options.id && !options.name)) {
|
|
1992
|
+
reject("Pass in the 'id' or 'name' param");
|
|
1860
1993
|
return;
|
|
1861
1994
|
}
|
|
1862
|
-
const
|
|
1863
|
-
|
|
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');
|
|
2015
|
+
}
|
|
1864
2016
|
}
|
|
1865
2017
|
catch (ex) {
|
|
1866
2018
|
if (Trace.isEnabled()) {
|
|
1867
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
2019
|
+
CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
|
|
1868
2020
|
}
|
|
1869
2021
|
reject(ex);
|
|
1870
2022
|
}
|
|
1871
2023
|
});
|
|
1872
2024
|
}
|
|
1873
|
-
|
|
2025
|
+
addExtrusion(options, nativeMap) {
|
|
1874
2026
|
return new Promise((resolve, reject) => {
|
|
1875
2027
|
try {
|
|
1876
2028
|
const theMap = nativeMap || this._mapboxViewInstance;
|
|
@@ -1878,489 +2030,370 @@ export class Mapbox extends MapboxCommon {
|
|
|
1878
2030
|
reject('No map has been loaded');
|
|
1879
2031
|
return;
|
|
1880
2032
|
}
|
|
1881
|
-
|
|
1882
|
-
const result = [];
|
|
1883
|
-
for (let i = 0; i < layers.count; i++) {
|
|
1884
|
-
result.push(new Layer(layers[i]));
|
|
1885
|
-
}
|
|
1886
|
-
resolve(result);
|
|
2033
|
+
resolve();
|
|
1887
2034
|
}
|
|
1888
2035
|
catch (ex) {
|
|
1889
2036
|
if (Trace.isEnabled()) {
|
|
1890
|
-
CLog(CLogTypes.info, 'Error in mapbox.
|
|
2037
|
+
CLog(CLogTypes.info, 'Error in mapbox.deleteOfflineRegion: ' + ex);
|
|
1891
2038
|
}
|
|
1892
2039
|
reject(ex);
|
|
1893
2040
|
}
|
|
1894
2041
|
});
|
|
1895
2042
|
}
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
resolve(marker);
|
|
1920
|
-
}, (ignoredError) => {
|
|
1921
|
-
console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
|
|
1922
|
-
resolve(marker);
|
|
1923
|
-
});
|
|
1924
|
-
});
|
|
1925
|
-
}
|
|
1926
|
-
const _downloadMarkerImages = (markers) => {
|
|
1927
|
-
const iterations = [];
|
|
1928
|
-
const result = [];
|
|
1929
|
-
markers.forEach((marker) => {
|
|
1930
|
-
if (marker.icon && marker.icon.startsWith('http')) {
|
|
1931
|
-
const p = _downloadImage(marker).then((mark) => result.push(mark));
|
|
1932
|
-
iterations.push(p);
|
|
1933
|
-
}
|
|
1934
|
-
else {
|
|
1935
|
-
result.push(marker);
|
|
1936
|
-
}
|
|
1937
|
-
});
|
|
1938
|
-
return Promise.all(iterations).then(() => result);
|
|
1939
|
-
};
|
|
1940
|
-
var MGLMapViewDelegateImpl = /** @class */ (function (_super) {
|
|
1941
|
-
__extends(MGLMapViewDelegateImpl, _super);
|
|
1942
|
-
function MGLMapViewDelegateImpl() {
|
|
1943
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1944
|
-
}
|
|
1945
|
-
MGLMapViewDelegateImpl.new = function () {
|
|
1946
|
-
return _super.new.call(this);
|
|
1947
|
-
};
|
|
1948
|
-
/**
|
|
1949
|
-
* initialize with the mapReady callback
|
|
1950
|
-
*/
|
|
1951
|
-
MGLMapViewDelegateImpl.prototype.initWithCallback = function (mapLoadedCallback) {
|
|
1952
|
-
if (Trace.isEnabled()) {
|
|
1953
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::initWithCallback()');
|
|
1954
|
-
}
|
|
1955
|
-
this.mapLoadedCallback = mapLoadedCallback;
|
|
1956
|
-
return this;
|
|
1957
|
-
};
|
|
1958
|
-
/**
|
|
1959
|
-
* set a reference to the mapboxAPI instance
|
|
1960
|
-
*/
|
|
1961
|
-
MGLMapViewDelegateImpl.prototype.setMapboxApi = function (api) {
|
|
1962
|
-
this.mapboxApi = api;
|
|
1963
|
-
};
|
|
1964
|
-
/**
|
|
1965
|
-
* set the user location click listener callback
|
|
1966
|
-
*/
|
|
1967
|
-
MGLMapViewDelegateImpl.prototype.setUserLocationClickListener = function (callback) {
|
|
1968
|
-
this.userLocationClickListener = callback;
|
|
1969
|
-
};
|
|
1970
|
-
/**
|
|
1971
|
-
* set the user location click listener callback
|
|
1972
|
-
*/
|
|
1973
|
-
MGLMapViewDelegateImpl.prototype.setUserLocationChangedistener = function (callback) {
|
|
1974
|
-
this.userLocationChangedListener = callback;
|
|
1975
|
-
};
|
|
1976
|
-
/**
|
|
1977
|
-
* set user location marker modes
|
|
1978
|
-
*/
|
|
1979
|
-
MGLMapViewDelegateImpl.prototype.changeUserLocationRenderMode = function (userLocationRenderMode) {
|
|
1980
|
-
this.userLocationAnnotationView.changeUserLocationRenderMode(userLocationRenderMode);
|
|
1981
|
-
};
|
|
1982
|
-
/**
|
|
1983
|
-
* set the camera changd listener callback
|
|
1984
|
-
*/
|
|
1985
|
-
MGLMapViewDelegateImpl.prototype.setCameraChangedListener = function (callback) {
|
|
1986
|
-
this.cameraChangedListener = callback;
|
|
1987
|
-
};
|
|
1988
|
-
/**
|
|
1989
|
-
* set the camera idled listener callback
|
|
1990
|
-
*/
|
|
1991
|
-
MGLMapViewDelegateImpl.prototype.setCameraIdledListener = function (callback) {
|
|
1992
|
-
this.cameraIdledListener = callback;
|
|
1993
|
-
};
|
|
1994
|
-
/**
|
|
1995
|
-
* set style loaded callback.
|
|
1996
|
-
*
|
|
1997
|
-
* set an optional callback to be invoked when a style set with
|
|
1998
|
-
* setMapStyle() is finished loading
|
|
1999
|
-
*
|
|
2000
|
-
* @param {function} callback function with loaded style as parameter.
|
|
2001
|
-
*
|
|
2002
|
-
* @see Mapbox:setMapStyle()
|
|
2003
|
-
*/
|
|
2004
|
-
MGLMapViewDelegateImpl.prototype.setStyleLoadedCallback = function (callback) {
|
|
2005
|
-
this.styleLoadedCallback = callback;
|
|
2006
|
-
};
|
|
2007
|
-
/**
|
|
2008
|
-
* map ready callback
|
|
2009
|
-
*/
|
|
2010
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingMap = function (mapView) {
|
|
2011
|
-
if (Trace.isEnabled()) {
|
|
2012
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingMap(): top');
|
|
2013
|
-
}
|
|
2014
|
-
if (this.mapLoadedCallback !== undefined) {
|
|
2015
|
-
this.mapLoadedCallback(mapView);
|
|
2016
|
-
// this should be fired only once, but it's also fired when the style changes, so just remove the callback
|
|
2017
|
-
this.mapLoadedCallback = undefined;
|
|
2018
|
-
}
|
|
2019
|
-
};
|
|
2020
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFinishRenderingMapFullyRendered = function (mapView, fullyRendered) {
|
|
2021
|
-
if (Trace.isEnabled()) {
|
|
2022
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishRenderingMapFullyRendered(): rendered is:', fullyRendered);
|
|
2023
|
-
}
|
|
2024
|
-
};
|
|
2025
|
-
/**
|
|
2026
|
-
* Callback when the style has been loaded.
|
|
2027
|
-
*
|
|
2028
|
-
* Based on my testing, it looks like this callback is invoked multiple times.
|
|
2029
|
-
*
|
|
2030
|
-
* @see Mapbox:setMapStyle()
|
|
2031
|
-
*
|
|
2032
|
-
* @link https://mapbox.github.io/mapbox-gl-native/macos/0.3.0/Protocols/MGLMapViewDelegate.html#/c:objc(pl)MGLMapViewDelegate(im)mapView:didFinishLoadingStyle:
|
|
2033
|
-
*/
|
|
2034
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFinishLoadingStyle = function (mapView, style) {
|
|
2035
|
-
if (Trace.isEnabled()) {
|
|
2036
|
-
CLog(CLogTypes.info, 'MGLMapViewDelegateImpl:mapViewDidFinishLoadingStyle(): callback called.');
|
|
2037
|
-
}
|
|
2038
|
-
if (this.styleLoadedCallback !== undefined) {
|
|
2039
|
-
this.styleLoadedCallback(mapView, style);
|
|
2040
|
-
// to avoid multiple calls. This is only invoked from setMapStyle().
|
|
2041
|
-
this.styleLoadedCallback = undefined;
|
|
2042
|
-
}
|
|
2043
|
-
};
|
|
2044
|
-
/**
|
|
2045
|
-
* disable the default user location callout
|
|
2046
|
-
*
|
|
2047
|
-
* This took forever to find. The default iOS click handler for the user location
|
|
2048
|
-
* marker is about useless. It just displays "You Are Here". The examples do not
|
|
2049
|
-
* show how to disable it.
|
|
2050
|
-
*/
|
|
2051
|
-
MGLMapViewDelegateImpl.prototype.mapViewAnnotationCanShowCallout = function (mapView, annotation) {
|
|
2052
|
-
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
2053
|
-
return false;
|
|
2054
|
-
}
|
|
2055
|
-
else {
|
|
2056
|
-
return true;
|
|
2057
|
-
}
|
|
2058
|
-
};
|
|
2059
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidFailLoadingMapWithError = function (mapView, error) {
|
|
2060
|
-
if (Trace.isEnabled()) {
|
|
2061
|
-
CLog(CLogTypes.info, 'mapViewDidFailLoadingMapWithError: ' + error);
|
|
2062
|
-
}
|
|
2063
|
-
};
|
|
2064
|
-
MGLMapViewDelegateImpl.prototype.mapViewDidChangeUserTrackingModeAnimated = function (mapView, mode, animated) {
|
|
2065
|
-
if (Trace.isEnabled()) {
|
|
2066
|
-
CLog(CLogTypes.info, 'mapViewDidChangeUserTrackingModeAnimated: ' + mode);
|
|
2067
|
-
}
|
|
2068
|
-
};
|
|
2069
|
-
/**
|
|
2070
|
-
* fired when the marker icon is about to be rendered - return null for the default icon
|
|
2071
|
-
*/
|
|
2072
|
-
MGLMapViewDelegateImpl.prototype.mapViewImageForAnnotation = function (mapView, annotation) {
|
|
2073
|
-
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
2074
|
-
if (cachedMarker) {
|
|
2075
|
-
if (cachedMarker.reuseIdentifier) {
|
|
2076
|
-
var reusedImage = mapView.dequeueReusableAnnotationImageWithIdentifier(cachedMarker.reuseIdentifier);
|
|
2077
|
-
if (reusedImage) {
|
|
2078
|
-
return reusedImage;
|
|
2043
|
+
updateSource(id, options, nativeMap) {
|
|
2044
|
+
return new Promise((resolve, reject) => {
|
|
2045
|
+
try {
|
|
2046
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2047
|
+
if (!theMap) {
|
|
2048
|
+
reject('No map has been loaded');
|
|
2049
|
+
return;
|
|
2050
|
+
}
|
|
2051
|
+
const source = theMap.style.sourceWithIdentifier(id);
|
|
2052
|
+
if (!source) {
|
|
2053
|
+
reject('Source does not exists: ' + id);
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
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;
|
|
2079
2066
|
}
|
|
2080
2067
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
if (cachedMarker.icon.startsWith('res://')) {
|
|
2085
|
-
var resourceName = cachedMarker.icon.substring('res://'.length);
|
|
2086
|
-
var imageSource = ImageSource.fromResourceSync(resourceName);
|
|
2087
|
-
if (imageSource === null) {
|
|
2088
|
-
console.log("Unable to locate " + resourceName);
|
|
2089
|
-
}
|
|
2090
|
-
else {
|
|
2091
|
-
cachedMarker.reuseIdentifier = cachedMarker.icon;
|
|
2092
|
-
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(imageSource.ios, cachedMarker.reuseIdentifier);
|
|
2093
|
-
}
|
|
2068
|
+
catch (ex) {
|
|
2069
|
+
if (Trace.isEnabled()) {
|
|
2070
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2094
2071
|
}
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
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.cluster) {
|
|
2143
|
+
sourceOptions[MGLShapeSourceOptionClustered] = true;
|
|
2144
|
+
sourceOptions[MGLShapeSourceOptionClusterRadius] = options.cluster.radius || 40;
|
|
2145
|
+
sourceOptions[MGLShapeSourceOptionMaximumZoomLevelForClustering] = options.cluster.maxZoom || 13;
|
|
2146
|
+
}
|
|
2147
|
+
source = MGLShapeSource.alloc().initWithIdentifierShapeOptions(id, geoJsonShape, sourceOptions);
|
|
2148
|
+
break;
|
|
2149
|
+
case 'raster': {
|
|
2150
|
+
const sourceOptions = {
|
|
2151
|
+
[MGLTileSourceOptionTileSize]: options.tileSize || 256
|
|
2152
|
+
};
|
|
2153
|
+
if (options.minzoom !== undefined) {
|
|
2154
|
+
sourceOptions[MGLTileSourceOptionMinimumZoomLevel] = options.minzoom;
|
|
2155
|
+
}
|
|
2156
|
+
if (options.maxzoom !== undefined) {
|
|
2157
|
+
sourceOptions[MGLTileSourceOptionMaximumZoomLevel] = options.maxzoom;
|
|
2158
|
+
}
|
|
2159
|
+
if (options.scheme) {
|
|
2160
|
+
switch (options.scheme || 'xyz') {
|
|
2161
|
+
case 'xyz':
|
|
2162
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 0;
|
|
2163
|
+
break;
|
|
2164
|
+
case 'tms':
|
|
2165
|
+
sourceOptions[MGLTileSourceOptionTileCoordinateSystem] = 1;
|
|
2166
|
+
break;
|
|
2167
|
+
default:
|
|
2168
|
+
throw new Error('Unknown raster tile scheme.');
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
if (options.bounds) {
|
|
2172
|
+
sourceOptions[MGLTileSourceOptionCoordinateBounds] = NSValue.valueWithMGLCoordinateBounds({
|
|
2173
|
+
sw: CLLocationCoordinate2DMake(options.bounds[1], options.bounds[0]),
|
|
2174
|
+
ne: CLLocationCoordinate2DMake(options.bounds[3], options.bounds[2])
|
|
2175
|
+
});
|
|
2176
|
+
}
|
|
2177
|
+
source = MGLRasterTileSource.alloc().initWithIdentifierTileURLTemplatesOptions(id, options.tiles, sourceOptions);
|
|
2178
|
+
break;
|
|
2099
2179
|
}
|
|
2180
|
+
default:
|
|
2181
|
+
reject('Invalid source type: ' + options['type']);
|
|
2182
|
+
return;
|
|
2100
2183
|
}
|
|
2101
|
-
|
|
2184
|
+
if (!source) {
|
|
2185
|
+
const ex = 'No source to add';
|
|
2102
2186
|
if (Trace.isEnabled()) {
|
|
2103
|
-
CLog(CLogTypes.info, '
|
|
2187
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2104
2188
|
}
|
|
2189
|
+
reject(ex);
|
|
2190
|
+
return;
|
|
2105
2191
|
}
|
|
2192
|
+
theMap.style.addSource(source);
|
|
2193
|
+
resolve();
|
|
2106
2194
|
}
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
if (File.exists(iconFullPath)) {
|
|
2111
|
-
var image = ImageSource.fromFileSync(iconFullPath).ios;
|
|
2112
|
-
// perhaps add resize options for nice retina rendering (although you can now use the 'icon' param instead)
|
|
2113
|
-
cachedMarker.reuseIdentifier = cachedMarker.iconPath;
|
|
2114
|
-
return MGLAnnotationImage.annotationImageWithImageReuseIdentifier(image, cachedMarker.reuseIdentifier);
|
|
2195
|
+
catch (ex) {
|
|
2196
|
+
if (Trace.isEnabled()) {
|
|
2197
|
+
CLog(CLogTypes.info, 'Error in mapbox.addSource: ' + ex);
|
|
2115
2198
|
}
|
|
2199
|
+
reject(ex);
|
|
2116
2200
|
}
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
2203
|
+
removeSource(id, nativeMap) {
|
|
2204
|
+
return new Promise((resolve, reject) => {
|
|
2205
|
+
try {
|
|
2206
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2207
|
+
if (!theMap) {
|
|
2208
|
+
reject('No map has been loaded');
|
|
2209
|
+
return;
|
|
2210
|
+
}
|
|
2211
|
+
const source = theMap.style.sourceWithIdentifier(id);
|
|
2212
|
+
if (!source) {
|
|
2213
|
+
reject('Source does not exist');
|
|
2214
|
+
return;
|
|
2215
|
+
}
|
|
2216
|
+
theMap.style.removeSource(source);
|
|
2217
|
+
resolve();
|
|
2134
2218
|
}
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2219
|
+
catch (ex) {
|
|
2220
|
+
if (Trace.isEnabled()) {
|
|
2221
|
+
CLog(CLogTypes.info, 'Error in mapbox.removeSource: ' + ex);
|
|
2222
|
+
}
|
|
2223
|
+
reject(ex);
|
|
2138
2224
|
}
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
async addLayer(style, belowLayerId, nativeMapView) {
|
|
2228
|
+
const theMap = nativeMapView || this._mapboxViewInstance;
|
|
2229
|
+
let source = null;
|
|
2230
|
+
if (typeof style.source != 'string') {
|
|
2231
|
+
await this.addSource(style.id + '_source', style.source);
|
|
2232
|
+
source = theMap.style.sourceWithIdentifier(style.id + '_source');
|
|
2144
2233
|
}
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
* fired when a callout is tapped
|
|
2148
|
-
*/
|
|
2149
|
-
MGLMapViewDelegateImpl.prototype.mapViewTapOnCalloutForAnnotation = function (mapView, annotation) {
|
|
2150
|
-
var cachedMarker = this.getTappedMarkerDetails(annotation);
|
|
2151
|
-
if (cachedMarker && cachedMarker.onCalloutTap) {
|
|
2152
|
-
cachedMarker.onCalloutTap(cachedMarker);
|
|
2234
|
+
else {
|
|
2235
|
+
source = theMap.style.sourceWithIdentifier(style.source);
|
|
2153
2236
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
// eslint-disable-next-line eqeqeq
|
|
2161
|
-
cached.lat == tapped.coordinate.latitude &&
|
|
2162
|
-
// eslint-disable-next-line eqeqeq
|
|
2163
|
-
cached.lng == tapped.coordinate.longitude &&
|
|
2164
|
-
// eslint-disable-next-line eqeqeq
|
|
2165
|
-
cached.title == tapped.title &&
|
|
2166
|
-
// eslint-disable-next-line eqeqeq
|
|
2167
|
-
cached.subtitle == tapped.subtitle) {
|
|
2168
|
-
return cached;
|
|
2237
|
+
const layer = await LayerFactory.createLayer(style, source);
|
|
2238
|
+
if (belowLayerId) {
|
|
2239
|
+
const belowlayer = theMap.style.layerWithIdentifier(belowLayerId);
|
|
2240
|
+
if (belowlayer) {
|
|
2241
|
+
theMap.style.insertLayerBelowLayer(layer.getNativeInstance(), belowlayer);
|
|
2242
|
+
return;
|
|
2169
2243
|
}
|
|
2170
2244
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
MGLMapViewDelegateImpl.prototype.mapViewViewForAnnotation = function (mapView, annotation) {
|
|
2245
|
+
theMap.style.addLayer(layer.getNativeInstance());
|
|
2246
|
+
}
|
|
2247
|
+
async removeLayer(id, nativeMapViewInstance) {
|
|
2248
|
+
const theMap = nativeMapViewInstance || this._mapboxViewInstance;
|
|
2176
2249
|
if (Trace.isEnabled()) {
|
|
2177
|
-
CLog(CLogTypes.info,
|
|
2178
|
-
}
|
|
2179
|
-
if (annotation.isKindOfClass(MGLUserLocation.class())) {
|
|
2180
|
-
this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init();
|
|
2181
|
-
return this.userLocationAnnotationView;
|
|
2250
|
+
CLog(CLogTypes.info, "Mapbox::removeLayer(): attempting to remove layer '" + id + "'");
|
|
2182
2251
|
}
|
|
2183
|
-
|
|
2184
|
-
};
|
|
2185
|
-
MGLMapViewDelegateImpl.prototype.mapViewRegionIsChangingWithReason = function (mapView, reason) {
|
|
2252
|
+
const layer = theMap.style.layerWithIdentifier(id);
|
|
2186
2253
|
if (Trace.isEnabled()) {
|
|
2187
|
-
CLog(CLogTypes.info, '
|
|
2254
|
+
CLog(CLogTypes.info, 'Mapbox:removeLayer(): got layer object: ', layer);
|
|
2188
2255
|
}
|
|
2189
|
-
if (
|
|
2190
|
-
|
|
2256
|
+
if (!layer) {
|
|
2257
|
+
throw new Error("Layer '" + id + "' not found when attempting to remove it.");
|
|
2191
2258
|
}
|
|
2192
|
-
|
|
2193
|
-
MGLMapViewDelegateImpl.prototype.mapViewRegionDidChangeWithReasonAnimated = function (mapView, reason, animated) {
|
|
2259
|
+
theMap.style.removeLayer(layer);
|
|
2194
2260
|
if (Trace.isEnabled()) {
|
|
2195
|
-
CLog(CLogTypes.info, '
|
|
2196
|
-
}
|
|
2197
|
-
if (this.cameraChangedListener) {
|
|
2198
|
-
this.cameraChangedListener(reason, animated);
|
|
2261
|
+
CLog(CLogTypes.info, 'Mapbox:removeLayer(): after removing layer ' + id);
|
|
2199
2262
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2263
|
+
}
|
|
2264
|
+
async addLinePoint(id, lnglat, sourceId, nativeMapView) {
|
|
2265
|
+
const theMap = nativeMapView || this._mapboxViewInstance;
|
|
2266
|
+
const sId = !!sourceId ? sourceId : id + '_source';
|
|
2267
|
+
const lineSource = theMap.style.sourceWithIdentifier(sId);
|
|
2268
|
+
if (!lineSource) {
|
|
2269
|
+
throw new Error(`no source found with id: ${sId}`);
|
|
2202
2270
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2271
|
+
try {
|
|
2272
|
+
const lineFeatures = lineSource.featuresMatchingPredicate(FilterParser.parseJson(['==', '$type', 'LineString']));
|
|
2273
|
+
if (lineFeatures.count === 0) {
|
|
2274
|
+
throw new Error('no line string feature found');
|
|
2275
|
+
}
|
|
2276
|
+
const lineFeature = lineFeatures.objectAtIndex(0);
|
|
2277
|
+
const newCoord = CLLocationCoordinate2DMake(lnglat[1], lnglat[0]);
|
|
2278
|
+
const newCoordPointer = new interop.Reference(newCoord);
|
|
2279
|
+
lineFeature.appendCoordinatesCount(newCoordPointer, 1);
|
|
2280
|
+
lineSource.shape = lineFeature;
|
|
2207
2281
|
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2282
|
+
catch (error) {
|
|
2283
|
+
console.log(error);
|
|
2284
|
+
throw error;
|
|
2210
2285
|
}
|
|
2211
|
-
};
|
|
2212
|
-
MGLMapViewDelegateImpl.ObjCProtocols = [MGLMapViewDelegate];
|
|
2213
|
-
return MGLMapViewDelegateImpl;
|
|
2214
|
-
}(NSObject));
|
|
2215
|
-
var MapTapHandlerImpl = /** @class */ (function (_super) {
|
|
2216
|
-
__extends(MapTapHandlerImpl, _super);
|
|
2217
|
-
function MapTapHandlerImpl() {
|
|
2218
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2219
2286
|
}
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
handler._owner = owner;
|
|
2223
|
-
handler._listener = listener;
|
|
2224
|
-
handler._mapView = mapView;
|
|
2225
|
-
return handler;
|
|
2226
|
-
};
|
|
2227
|
-
MapTapHandlerImpl.prototype.tap = function (recognizer) {
|
|
2228
|
-
var tapPoint = recognizer.locationInView(this._mapView);
|
|
2229
|
-
var tapCoordinate = this._mapView.convertPointToCoordinateFromView(tapPoint, this._mapView);
|
|
2230
|
-
this._listener({
|
|
2231
|
-
lat: tapCoordinate.latitude,
|
|
2232
|
-
lng: tapCoordinate.longitude
|
|
2233
|
-
});
|
|
2234
|
-
};
|
|
2235
|
-
MapTapHandlerImpl.ObjCExposedMethods = {
|
|
2236
|
-
tap: { returns: interop.types.void, params: [interop.types.id] }
|
|
2237
|
-
};
|
|
2238
|
-
return MapTapHandlerImpl;
|
|
2239
|
-
}(NSObject));
|
|
2240
|
-
var MapLongPressHandlerImpl = /** @class */ (function (_super) {
|
|
2241
|
-
__extends(MapLongPressHandlerImpl, _super);
|
|
2242
|
-
function MapLongPressHandlerImpl() {
|
|
2243
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2287
|
+
addGeoJsonClustered(options, nativeMapViewInstance) {
|
|
2288
|
+
throw new Error('Method not implemented.');
|
|
2244
2289
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2290
|
+
trackUser(options, nativeMap) {
|
|
2291
|
+
return new Promise((resolve, reject) => {
|
|
2292
|
+
try {
|
|
2293
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2294
|
+
if (!theMap) {
|
|
2295
|
+
reject('No map has been loaded');
|
|
2296
|
+
return;
|
|
2297
|
+
}
|
|
2298
|
+
if (!theMap.showsUserLocation) {
|
|
2299
|
+
reject('The map is not currently showing the user location');
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
theMap.setUserTrackingModeAnimated(_getTrackingMode(options.cameraMode), options.animated !== false);
|
|
2303
|
+
resolve();
|
|
2304
|
+
}
|
|
2305
|
+
catch (ex) {
|
|
2306
|
+
if (Trace.isEnabled()) {
|
|
2307
|
+
CLog(CLogTypes.info, 'Error in mapbox.trackUser: ' + ex);
|
|
2308
|
+
}
|
|
2309
|
+
reject(ex);
|
|
2310
|
+
}
|
|
2258
2311
|
});
|
|
2259
|
-
};
|
|
2260
|
-
MapLongPressHandlerImpl.ObjCExposedMethods = {
|
|
2261
|
-
longPress: { returns: interop.types.void, params: [interop.types.id] }
|
|
2262
|
-
};
|
|
2263
|
-
return MapLongPressHandlerImpl;
|
|
2264
|
-
}(NSObject));
|
|
2265
|
-
var MapPanHandlerImpl = /** @class */ (function (_super) {
|
|
2266
|
-
__extends(MapPanHandlerImpl, _super);
|
|
2267
|
-
function MapPanHandlerImpl() {
|
|
2268
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2269
2312
|
}
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
var panPoint = recognizer.locationInView(this._mapView);
|
|
2283
|
-
var panCoordinate = this._mapView.convertPointToCoordinateFromView(panPoint, this._mapView);
|
|
2284
|
-
if (Trace.isEnabled()) {
|
|
2285
|
-
CLog(CLogTypes.info, 'MapPanHandlerImpl::pan(): top with state:', recognizer.state);
|
|
2286
|
-
}
|
|
2287
|
-
// if this is the beginning of the pan simulate the Android onMoveBegin
|
|
2288
|
-
//
|
|
2289
|
-
// See the objc platform declarations in objc!UIKit.d.ts. It doesn't quite match the apple documention
|
|
2290
|
-
if (this.onMoveBegin) {
|
|
2291
|
-
if (recognizer.state === UIGestureRecognizerState.Began) {
|
|
2313
|
+
getLayer(name, nativeMap) {
|
|
2314
|
+
return new Promise((resolve, reject) => {
|
|
2315
|
+
try {
|
|
2316
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2317
|
+
if (!theMap) {
|
|
2318
|
+
reject('No map has been loaded');
|
|
2319
|
+
return;
|
|
2320
|
+
}
|
|
2321
|
+
const layer = theMap.style.layerWithIdentifier(name);
|
|
2322
|
+
resolve(new Layer(layer));
|
|
2323
|
+
}
|
|
2324
|
+
catch (ex) {
|
|
2292
2325
|
if (Trace.isEnabled()) {
|
|
2293
|
-
CLog(CLogTypes.info, '
|
|
2326
|
+
CLog(CLogTypes.info, 'Error in mapbox.getLayer: ' + ex);
|
|
2294
2327
|
}
|
|
2295
|
-
|
|
2296
|
-
lat: panCoordinate.latitude,
|
|
2297
|
-
lng: panCoordinate.longitude
|
|
2298
|
-
});
|
|
2328
|
+
reject(ex);
|
|
2299
2329
|
}
|
|
2300
|
-
return;
|
|
2301
|
-
}
|
|
2302
|
-
this._listener({
|
|
2303
|
-
lat: panCoordinate.latitude,
|
|
2304
|
-
lng: panCoordinate.longitude
|
|
2305
2330
|
});
|
|
2306
|
-
};
|
|
2307
|
-
MapPanHandlerImpl.ObjCExposedMethods = {
|
|
2308
|
-
pan: { returns: interop.types.void, params: [interop.types.id] }
|
|
2309
|
-
};
|
|
2310
|
-
return MapPanHandlerImpl;
|
|
2311
|
-
}(NSObject));
|
|
2312
|
-
var MapSwipeHandlerImpl = /** @class */ (function (_super) {
|
|
2313
|
-
__extends(MapSwipeHandlerImpl, _super);
|
|
2314
|
-
function MapSwipeHandlerImpl() {
|
|
2315
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
2316
2331
|
}
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2332
|
+
getLayers(nativeMap) {
|
|
2333
|
+
return new Promise((resolve, reject) => {
|
|
2334
|
+
try {
|
|
2335
|
+
const theMap = nativeMap || this._mapboxViewInstance;
|
|
2336
|
+
if (!theMap) {
|
|
2337
|
+
reject('No map has been loaded');
|
|
2338
|
+
return;
|
|
2339
|
+
}
|
|
2340
|
+
const layers = theMap.style.layers;
|
|
2341
|
+
const result = [];
|
|
2342
|
+
for (let i = 0; i < layers.count; i++) {
|
|
2343
|
+
result.push(new Layer(layers[i]));
|
|
2344
|
+
}
|
|
2345
|
+
resolve(result);
|
|
2346
|
+
}
|
|
2347
|
+
catch (ex) {
|
|
2348
|
+
if (Trace.isEnabled()) {
|
|
2349
|
+
CLog(CLogTypes.info, 'Error in mapbox.getLayers: ' + ex);
|
|
2350
|
+
}
|
|
2351
|
+
reject(ex);
|
|
2352
|
+
}
|
|
2330
2353
|
});
|
|
2331
|
-
};
|
|
2332
|
-
MapSwipeHandlerImpl.ObjCExposedMethods = {
|
|
2333
|
-
swipe: { returns: interop.types.void, params: [interop.types.id] }
|
|
2334
|
-
};
|
|
2335
|
-
return MapSwipeHandlerImpl;
|
|
2336
|
-
}(NSObject));
|
|
2337
|
-
export class Layer {
|
|
2338
|
-
constructor(instance) {
|
|
2339
|
-
this.instance = instance;
|
|
2340
|
-
this.id = instance.identifier;
|
|
2341
|
-
}
|
|
2342
|
-
visibility() {
|
|
2343
|
-
return this.instance.visible;
|
|
2344
|
-
}
|
|
2345
|
-
show() {
|
|
2346
|
-
this.instance.visible = true;
|
|
2347
2354
|
}
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
return this.instance;
|
|
2355
|
+
project(data) {
|
|
2356
|
+
const theMap = this._mapboxViewInstance;
|
|
2357
|
+
const { x, y } = theMap.convertCoordinateToPointToView({ latitude: data.lat, longitude: data.lng }, theMap);
|
|
2358
|
+
return { x, y };
|
|
2353
2359
|
}
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2360
|
+
}
|
|
2361
|
+
const _addObserver = (eventName, callback) => NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(eventName, null, NSOperationQueue.mainQueue, callback);
|
|
2362
|
+
function _downloadImage(marker) {
|
|
2363
|
+
return new Promise((resolve, reject) => {
|
|
2364
|
+
if (Trace.isEnabled()) {
|
|
2365
|
+
CLog(CLogTypes.info, '>> _downloadImage');
|
|
2357
2366
|
}
|
|
2358
|
-
|
|
2359
|
-
|
|
2367
|
+
if (_markerIconDownloadCache[marker.icon]) {
|
|
2368
|
+
marker.iconDownloaded = _markerIconDownloadCache[marker.icon];
|
|
2369
|
+
if (Trace.isEnabled()) {
|
|
2370
|
+
CLog(CLogTypes.info, '>> marker.iconDownloaded: ' + marker.iconDownloaded);
|
|
2371
|
+
}
|
|
2372
|
+
resolve(marker);
|
|
2373
|
+
return;
|
|
2360
2374
|
}
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2375
|
+
Http.getImage(marker.icon).then((output) => {
|
|
2376
|
+
marker.iconDownloaded = output.ios;
|
|
2377
|
+
_markerIconDownloadCache[marker.icon] = marker.iconDownloaded;
|
|
2378
|
+
resolve(marker);
|
|
2379
|
+
}, (ignoredError) => {
|
|
2380
|
+
console.log(`Download failed for ${marker.icon} with error: ${ignoredError}`);
|
|
2381
|
+
resolve(marker);
|
|
2382
|
+
});
|
|
2383
|
+
});
|
|
2365
2384
|
}
|
|
2366
|
-
|
|
2385
|
+
const _downloadMarkerImages = (markers) => {
|
|
2386
|
+
const iterations = [];
|
|
2387
|
+
const result = [];
|
|
2388
|
+
markers.forEach((marker) => {
|
|
2389
|
+
if (marker.icon && marker.icon.startsWith('http')) {
|
|
2390
|
+
const p = _downloadImage(marker).then((mark) => result.push(mark));
|
|
2391
|
+
iterations.push(p);
|
|
2392
|
+
}
|
|
2393
|
+
else {
|
|
2394
|
+
result.push(marker);
|
|
2395
|
+
}
|
|
2396
|
+
});
|
|
2397
|
+
return Promise.all(iterations).then(() => result);
|
|
2398
|
+
};
|
|
2399
|
+
//# sourceMappingURL=index.ios.js.map
|