mobility-toolbox-js 2.0.0-beta.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/api/index.js +0 -1
- package/api/tralis/TralisAPI.js +1 -1
- package/common/controls/Control.js +4 -1
- package/common/layers/Layer.js +18 -49
- package/common/layers/Layer.test.js +2 -106
- package/common/mixins/SearchMixin.js +1 -1
- package/common/mixins/TralisLayerMixin.js +549 -21
- package/common/styles/index.js +4 -0
- package/common/{utils/delayTrackerStyle.js → styles/trackerDefaultStyle.js} +8 -8
- package/common/styles/trackerDelayStyle.js +17 -0
- package/common/styles/trackerSimpleStyle.js +22 -0
- package/common/trackerConfig.test.js +0 -13
- package/common/utils/getMapboxMapCopyrights.js +1 -0
- package/common/utils/index.js +2 -3
- package/common/utils/sortByDelay.js +23 -0
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/mapbox/controls/CopyrightControl.js +5 -1
- package/mapbox/index.js +0 -2
- package/mapbox/layers/Layer.test.js +2 -2
- package/mapbox/layers/TralisLayer.js +270 -5
- package/mapbox/layers/TralisLayer.test.js +40 -0
- package/module.js +1 -9
- package/ol/controls/CopyrightControl.js +4 -4
- package/ol/controls/CopyrightControl.test.js +16 -16
- package/ol/controls/RoutingControl.js +9 -7
- package/ol/controls/RoutingControl.test.js +1 -1
- package/ol/controls/StopFinderControl.js +8 -6
- package/ol/controls/StopFinderControl.test.js +1 -1
- package/ol/index.js +3 -3
- package/ol/layers/Layer.js +9 -0
- package/ol/layers/Layer.test.js +22 -7
- package/ol/layers/MapboxLayer.js +39 -44
- package/ol/layers/MapboxLayer.test.js +5 -5
- package/ol/layers/MapboxStyleLayer.js +0 -6
- package/ol/layers/MapboxStyleLayer.test.js +22 -6
- package/ol/layers/MaplibreLayer.js +280 -0
- package/ol/layers/RoutingLayer.test.js +1 -1
- package/ol/layers/TralisLayer.js +258 -76
- package/ol/layers/TralisLayer.test.js +1 -49
- package/ol/layers/VectorLayer.test.js +1 -1
- package/ol/layers/WMSLayer.test.js +6 -2
- package/ol/styles/fullTrajectoryDelayStyle.js +35 -0
- package/ol/styles/fullTrajectoryStyle.js +51 -0
- package/ol/styles/index.js +2 -0
- package/package.json +16 -8
- package/api/trajserv/TrajservAPI.js +0 -71
- package/api/trajserv/TrajservAPI.test.js +0 -171
- package/api/trajserv/TrajservAPIUtils.js +0 -191
- package/api/trajserv/TrajservAPIUtils.test.js +0 -40
- package/api/trajserv/typedefs.js +0 -44
- package/common/mixins/MapMixin.js +0 -103
- package/common/mixins/TrackerLayerMixin.js +0 -745
- package/common/mixins/TrajservLayerMixin.js +0 -544
- package/common/utils/simpleTrackerStyle.js +0 -18
- package/mapbox/Map.js +0 -87
- package/mapbox/layers/TrackerLayer.js +0 -282
- package/mapbox/layers/TrackerLayer.test.js +0 -68
- package/mapbox/layers/TrajservLayer.js +0 -114
- package/mapbox/layers/TrajservLayer.test.js +0 -90
- package/ol/Map.js +0 -109
- package/ol/Map.test.js +0 -34
- package/ol/layers/TrackerLayer.js +0 -296
- package/ol/layers/TrackerLayer.test.js +0 -70
- package/ol/layers/TrajservLayer.js +0 -190
- package/ol/layers/TrajservLayer.test.js +0 -113
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { fromLonLat } from 'ol/proj';
|
|
2
|
-
import { unByKey } from 'ol/Observable';
|
|
3
|
-
import { getWidth, getHeight } from 'ol/extent';
|
|
4
|
-
import transformRotate from '@turf/transform-rotate';
|
|
5
|
-
import { point } from '@turf/helpers';
|
|
6
|
-
import Layer from './Layer';
|
|
7
|
-
import mixin from '../../common/mixins/TrackerLayerMixin';
|
|
8
|
-
import { getSourceCoordinates, getMercatorResolution } from '../utils';
|
|
9
|
-
/**
|
|
10
|
-
* Responsible for loading tracker data.
|
|
11
|
-
*
|
|
12
|
-
* @classproperty {mapboxgl.Map} map - The map where the layer is displayed.
|
|
13
|
-
* @extends {Layer}
|
|
14
|
-
* @implements {TrackerLayerInterface}
|
|
15
|
-
*/
|
|
16
|
-
class TrackerLayer extends mixin(Layer) {
|
|
17
|
-
constructor(options = {}) {
|
|
18
|
-
super({
|
|
19
|
-
...options,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
/** @ignore */
|
|
23
|
-
this.onMove = this.onMove.bind(this);
|
|
24
|
-
|
|
25
|
-
/** @ignore */
|
|
26
|
-
this.onMoveEnd = this.onMoveEnd.bind(this);
|
|
27
|
-
|
|
28
|
-
/** @ignore */
|
|
29
|
-
this.onZoomEnd = this.onZoomEnd.bind(this);
|
|
30
|
-
|
|
31
|
-
/** @ignore */
|
|
32
|
-
this.onVisibilityChange = this.onVisibilityChange.bind(this);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Initialize the layer.
|
|
37
|
-
*
|
|
38
|
-
* @param {mapboxgl.Map} map A [mapbox Map](https://docs.mapbox.com/mapbox-gl-js/api/map/).
|
|
39
|
-
* @param {string} beforeId Layer's id before which we want to add the new layer.
|
|
40
|
-
* @override
|
|
41
|
-
*/
|
|
42
|
-
init(map, beforeId) {
|
|
43
|
-
if (!map) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const canvas = map.getCanvas();
|
|
48
|
-
|
|
49
|
-
super.init(map, {
|
|
50
|
-
width: canvas.width / this.pixelRatio,
|
|
51
|
-
height: canvas.height / this.pixelRatio,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const source = {
|
|
55
|
-
type: 'canvas',
|
|
56
|
-
canvas: this.tracker.canvas,
|
|
57
|
-
coordinates: getSourceCoordinates(map, this.pixelRatio),
|
|
58
|
-
// Set to true if the canvas source is animated. If the canvas is static, animate should be set to false to improve performance.
|
|
59
|
-
animate: true,
|
|
60
|
-
attribution: this.copyrights && this.copyrights.join(', '),
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
this.beforeId = beforeId;
|
|
64
|
-
this.layer = {
|
|
65
|
-
id: this.key,
|
|
66
|
-
type: 'raster',
|
|
67
|
-
source: this.key,
|
|
68
|
-
layout: {
|
|
69
|
-
visibility: this.visible ? 'visible' : 'none',
|
|
70
|
-
},
|
|
71
|
-
paint: {
|
|
72
|
-
'raster-opacity': 1,
|
|
73
|
-
'raster-fade-duration': 0,
|
|
74
|
-
'raster-resampling': 'nearest', // important otherwise it looks blurry
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
map.addSource(this.key, source);
|
|
78
|
-
map.addLayer(this.layer, this.beforeId);
|
|
79
|
-
|
|
80
|
-
this.listeners = [this.on('change:visible', this.onVisibilityChange)];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Remove listeners from the Mapbox Map.
|
|
85
|
-
*/
|
|
86
|
-
terminate() {
|
|
87
|
-
if (this.map) {
|
|
88
|
-
this.listeners.forEach((listener) => {
|
|
89
|
-
unByKey(listener);
|
|
90
|
-
});
|
|
91
|
-
if (this.map.getLayer(this.key)) {
|
|
92
|
-
this.map.removeLayer(this.key);
|
|
93
|
-
}
|
|
94
|
-
if (this.map.getSource(this.key)) {
|
|
95
|
-
this.map.removeSource(this.key);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
super.terminate();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Start updating vehicles position.
|
|
103
|
-
*
|
|
104
|
-
* @listens {mapboxgl.map.event:zoomend} Listen to zoom end event.
|
|
105
|
-
* @listens {mapboxgl.map.event:mousemove} Listen to mousemove end.
|
|
106
|
-
* @override
|
|
107
|
-
*/
|
|
108
|
-
start() {
|
|
109
|
-
super.start();
|
|
110
|
-
|
|
111
|
-
this.map.on('move', this.onMove);
|
|
112
|
-
this.map.on('moveend', this.onMoveEnd);
|
|
113
|
-
this.map.on('zoomend', this.onZoomEnd);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Stop updating vehicles position, and unlisten events.
|
|
118
|
-
*
|
|
119
|
-
* @override
|
|
120
|
-
*/
|
|
121
|
-
stop() {
|
|
122
|
-
super.stop();
|
|
123
|
-
if (this.map) {
|
|
124
|
-
this.map.off('move', this.onMove);
|
|
125
|
-
this.map.off('moveend', this.onMoveEnd);
|
|
126
|
-
this.map.off('zoomend', this.onZoomEnd);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Function triggered when the user click the map.
|
|
132
|
-
* @override
|
|
133
|
-
*/
|
|
134
|
-
onUserClickCallback(evt) {
|
|
135
|
-
super.onUserClickCallback({
|
|
136
|
-
coordinate: fromLonLat(evt.lngLat.toArray()),
|
|
137
|
-
...evt,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Function triggered when the user moves the cursor over the map.
|
|
143
|
-
* @override
|
|
144
|
-
*/
|
|
145
|
-
onUserMoveCallback(evt) {
|
|
146
|
-
super.onUserMoveCallback({
|
|
147
|
-
coordinate: fromLonLat(evt.lngLat.toArray()),
|
|
148
|
-
...evt,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Render the trajectories using current map's size, resolution and rotation.
|
|
154
|
-
* @param {boolean} noInterpolate if true, renders the vehicles without interpolating theirs positions.
|
|
155
|
-
* @overrides
|
|
156
|
-
*/
|
|
157
|
-
renderTrajectories(noInterpolate) {
|
|
158
|
-
const { width, height } = this.map.getCanvas();
|
|
159
|
-
const center = this.map.getCenter();
|
|
160
|
-
|
|
161
|
-
// We use turf here to have good transform.
|
|
162
|
-
const leftBottom = this.map.unproject({
|
|
163
|
-
x: 0,
|
|
164
|
-
y: height / this.pixelRatio,
|
|
165
|
-
}); // southWest
|
|
166
|
-
const rightTop = this.map.unproject({ x: width / this.pixelRatio, y: 0 }); // north east
|
|
167
|
-
|
|
168
|
-
const coord0 = transformRotate(
|
|
169
|
-
point([leftBottom.lng, leftBottom.lat]),
|
|
170
|
-
-this.map.getBearing(),
|
|
171
|
-
{
|
|
172
|
-
pivot: [center.lng, center.lat],
|
|
173
|
-
},
|
|
174
|
-
).geometry.coordinates;
|
|
175
|
-
const coord1 = transformRotate(
|
|
176
|
-
point([rightTop.lng, rightTop.lat]),
|
|
177
|
-
-this.map.getBearing(),
|
|
178
|
-
{
|
|
179
|
-
pivot: [center.lng, center.lat],
|
|
180
|
-
},
|
|
181
|
-
).geometry.coordinates;
|
|
182
|
-
|
|
183
|
-
const bounds = [...fromLonLat(coord0), ...fromLonLat(coord1)];
|
|
184
|
-
const xResolution = getWidth(bounds) / (width / this.pixelRatio);
|
|
185
|
-
const yResolution = getHeight(bounds) / (height / this.pixelRatio);
|
|
186
|
-
const res = Math.max(xResolution, yResolution);
|
|
187
|
-
|
|
188
|
-
// Coordinate of trajectories are in mercator so we have to pass the proper resolution and center in mercator.
|
|
189
|
-
const viewState = {
|
|
190
|
-
size: [width / this.pixelRatio, height / this.pixelRatio],
|
|
191
|
-
center: fromLonLat([center.lng, center.lat]),
|
|
192
|
-
extent: bounds,
|
|
193
|
-
resolution: res,
|
|
194
|
-
zoom: this.map.getZoom(),
|
|
195
|
-
rotation: -(this.map.getBearing() * Math.PI) / 180,
|
|
196
|
-
pixelRatio: this.pixelRatio,
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
super.renderTrajectories(viewState, noInterpolate);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Return the delay in ms before the next rendering.
|
|
204
|
-
*/
|
|
205
|
-
getRefreshTimeInMs() {
|
|
206
|
-
return super.getRefreshTimeInMs(this.map.getZoom());
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Returns an array of vehicles located at the given coordinate.
|
|
211
|
-
*
|
|
212
|
-
* @param {Array<number>} coordinate
|
|
213
|
-
* @param {number} nb Number of vehicles to return;
|
|
214
|
-
* @return {Array<ol/Feature~Feature>} Array of vehicle.
|
|
215
|
-
* @override
|
|
216
|
-
*/
|
|
217
|
-
getVehiclesAtCoordinate(coordinate, nb) {
|
|
218
|
-
const resolution = getMercatorResolution(this.map);
|
|
219
|
-
return super.getVehiclesAtCoordinate(coordinate, resolution, nb);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
getFeatureInfoAtCoordinate(coordinate, options = {}) {
|
|
223
|
-
const resolution = getMercatorResolution(this.map);
|
|
224
|
-
return super.getFeatureInfoAtCoordinate(coordinate, {
|
|
225
|
-
resolution,
|
|
226
|
-
...options,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
onVisibilityChange() {
|
|
231
|
-
if (this.visible && !this.map.getLayer(this.key)) {
|
|
232
|
-
this.map.addLayer(this.layer, this.beforeId);
|
|
233
|
-
} else if (this.map.getLayer(this.key)) {
|
|
234
|
-
this.map.removeLayer(this.key);
|
|
235
|
-
}
|
|
236
|
-
// We can't use setLayoutProperty it triggers an error probably a bug in mapbox
|
|
237
|
-
// this.map.setLayoutProperty(
|
|
238
|
-
// this.key,
|
|
239
|
-
// 'visibilty',
|
|
240
|
-
// this.visible ? 'visible' : 'none',
|
|
241
|
-
// );
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Callback on 'move' event.
|
|
246
|
-
*
|
|
247
|
-
* @private
|
|
248
|
-
*/
|
|
249
|
-
onMove() {
|
|
250
|
-
const extent = getSourceCoordinates(this.map, this.pixelRatio);
|
|
251
|
-
const source = this.map.getSource(this.key);
|
|
252
|
-
if (source) {
|
|
253
|
-
source.setCoordinates(extent);
|
|
254
|
-
}
|
|
255
|
-
this.renderTrajectories();
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Callback on 'moveend' event.
|
|
260
|
-
*
|
|
261
|
-
* @private
|
|
262
|
-
*/
|
|
263
|
-
// eslint-disable-next-line class-methods-use-this
|
|
264
|
-
onMoveEnd() {
|
|
265
|
-
this.renderTrajectories();
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Update the cursor style when hovering a vehicle.
|
|
270
|
-
*
|
|
271
|
-
* @private
|
|
272
|
-
* @override
|
|
273
|
-
*/
|
|
274
|
-
onFeatureHover(features, layer, coordinate) {
|
|
275
|
-
super.onFeatureHover(features, layer, coordinate);
|
|
276
|
-
this.map.getCanvasContainer().style.cursor = features.length
|
|
277
|
-
? 'pointer'
|
|
278
|
-
: 'auto';
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
export default TrackerLayer;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import maplibre from 'maplibre-gl';
|
|
2
|
-
import { toLonLat } from 'ol/proj';
|
|
3
|
-
import TrackerLayer from './TrackerLayer';
|
|
4
|
-
|
|
5
|
-
let layer;
|
|
6
|
-
let onClick;
|
|
7
|
-
|
|
8
|
-
describe('TrackerLayer', () => {
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
onClick = jest.fn();
|
|
11
|
-
layer = new TrackerLayer({
|
|
12
|
-
onClick,
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('should be instanced.', () => {
|
|
17
|
-
expect(layer).toBeInstanceOf(TrackerLayer);
|
|
18
|
-
expect(layer.clickCallbacks[0]).toBe(onClick);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('should called terminate on initalization.', () => {
|
|
22
|
-
const spy = jest.spyOn(layer, 'terminate');
|
|
23
|
-
|
|
24
|
-
const mapElement = document.createElement('div');
|
|
25
|
-
const { style } = mapElement;
|
|
26
|
-
style.position = 'absolute';
|
|
27
|
-
style.left = '0px';
|
|
28
|
-
style.top = '0px';
|
|
29
|
-
style.width = '400px';
|
|
30
|
-
style.height = '400px';
|
|
31
|
-
mapElement.setAttribute('id', 'map');
|
|
32
|
-
document.body.appendChild(mapElement);
|
|
33
|
-
|
|
34
|
-
layer.init(
|
|
35
|
-
new maplibre.Map({
|
|
36
|
-
container: document.getElementById('map'),
|
|
37
|
-
style: `path/to/style`,
|
|
38
|
-
center: toLonLat([831634, 5933959]),
|
|
39
|
-
zoom: 9,
|
|
40
|
-
}),
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
expect(spy).toHaveBeenCalledTimes(1);
|
|
44
|
-
document.body.removeChild(mapElement);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('#onClick', () => {
|
|
48
|
-
const f = () => {};
|
|
49
|
-
layer.onClick(f);
|
|
50
|
-
expect(layer.clickCallbacks[1]).toBe(f);
|
|
51
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
52
|
-
layer.onClick(f);
|
|
53
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test('#unClick', () => {
|
|
57
|
-
const foo = () => {};
|
|
58
|
-
const bar = () => {};
|
|
59
|
-
layer.onClick(foo);
|
|
60
|
-
layer.onClick(bar);
|
|
61
|
-
expect(layer.clickCallbacks[1]).toBe(foo);
|
|
62
|
-
expect(layer.clickCallbacks[2]).toBe(bar);
|
|
63
|
-
expect(layer.clickCallbacks.length).toBe(3);
|
|
64
|
-
layer.unClick(foo);
|
|
65
|
-
expect(layer.clickCallbacks[1]).toBe(bar);
|
|
66
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { fromLonLat } from 'ol/proj';
|
|
2
|
-
import { buffer, getWidth } from 'ol/extent';
|
|
3
|
-
import { unByKey } from 'ol/Observable';
|
|
4
|
-
import TrackerLayer from './TrackerLayer';
|
|
5
|
-
import mixin from '../../common/mixins/TrajservLayerMixin';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Responsible for loading and display data from a Trajserv service.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* import { TrajservLayer } from 'mobility-toolbox-js/mapbox';
|
|
12
|
-
*
|
|
13
|
-
* const layer = new TrajservLayer({
|
|
14
|
-
* url: 'https://api.geops.io/tracker/v1',
|
|
15
|
-
* apiKey: [yourApiKey],
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* @see <a href="/api/class/src/api/trajserv/TrajservAPI%20js~TrajservAPI%20html">TrajservAPI</a>
|
|
19
|
-
* @see <a href="/example/mapbox-tracker">Mapbox tracker example</a>
|
|
20
|
-
*
|
|
21
|
-
* @extends {TrackerLayer}
|
|
22
|
-
* @implements {TrajservLayerInterface}
|
|
23
|
-
* @deprecated
|
|
24
|
-
*/
|
|
25
|
-
class TrajservLayer extends mixin(TrackerLayer) {
|
|
26
|
-
constructor(options = {}) {
|
|
27
|
-
super({ ...options });
|
|
28
|
-
this.onMove = this.onMove.bind(this);
|
|
29
|
-
this.onMoveEnd = this.onMoveEnd.bind(this);
|
|
30
|
-
this.onVisibilityChange = this.onVisibilityChange.bind(this);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Remove the mapbox layer and the mapbox source.
|
|
35
|
-
*
|
|
36
|
-
* @override
|
|
37
|
-
*/
|
|
38
|
-
terminate() {
|
|
39
|
-
if (this.map) {
|
|
40
|
-
this.listeners.forEach((listener) => {
|
|
41
|
-
unByKey(listener);
|
|
42
|
-
});
|
|
43
|
-
this.map.removeLayer(this.key);
|
|
44
|
-
this.map.removeSource(this.key);
|
|
45
|
-
}
|
|
46
|
-
super.terminate();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
start() {
|
|
50
|
-
if (!this.map) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
super.start();
|
|
54
|
-
this.map.on('move', this.onMove);
|
|
55
|
-
this.map.on('moveend', this.onMoveEnd);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
stop() {
|
|
59
|
-
if (this.map) {
|
|
60
|
-
this.map.off('move', this.onMove);
|
|
61
|
-
this.map.off('moveend', this.onMoveEnd);
|
|
62
|
-
}
|
|
63
|
-
super.stop();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Callback on 'moveend' event.
|
|
68
|
-
* @private
|
|
69
|
-
*/
|
|
70
|
-
onMoveEnd() {
|
|
71
|
-
this.updateTrajectories();
|
|
72
|
-
if (this.selectedVehicleId && this.journeyId) {
|
|
73
|
-
this.highlightTrajectory();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Returns the URL parameters.
|
|
79
|
-
* @param {Object} extraParams Extra parameters
|
|
80
|
-
* @return {Object}
|
|
81
|
-
* @private
|
|
82
|
-
*/
|
|
83
|
-
getParams(extraParams = {}) {
|
|
84
|
-
const bounds = this.map.getBounds().toArray();
|
|
85
|
-
const southWest = fromLonLat(bounds[0]);
|
|
86
|
-
const northEast = fromLonLat(bounds[1]);
|
|
87
|
-
const ext = [...southWest, ...northEast];
|
|
88
|
-
const bbox = buffer(ext, getWidth(ext) / 10).join(',');
|
|
89
|
-
const zoom = this.map.getZoom();
|
|
90
|
-
|
|
91
|
-
return super.getParams({
|
|
92
|
-
...extraParams,
|
|
93
|
-
bbox,
|
|
94
|
-
s: zoom < 10 ? 1 : 0,
|
|
95
|
-
z: zoom,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Draw the trajectory as a line with points for each stop.
|
|
101
|
-
*
|
|
102
|
-
* @param {Array} stationsCoords Array of station coordinates in EPSG:4326.
|
|
103
|
-
* @param {Array<ol/coordinate~Coordinate>} lineCoords A list of coordinates in EPSG:3857.
|
|
104
|
-
* @param {string} color The color of the line.
|
|
105
|
-
* @private
|
|
106
|
-
*/
|
|
107
|
-
// eslint-disable-next-line no-unused-vars,class-methods-use-this
|
|
108
|
-
drawFullTrajectory(stationsCoords, lineCoords, color) {
|
|
109
|
-
// eslint-disable-next-line no-console
|
|
110
|
-
console.log('to be implemented');
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export default TrajservLayer;
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import maplibre from 'maplibre-gl';
|
|
2
|
-
import fetch from 'jest-fetch-mock';
|
|
3
|
-
import { toLonLat } from 'ol/proj';
|
|
4
|
-
import TrajservLayer from './TrajservLayer';
|
|
5
|
-
|
|
6
|
-
let layer;
|
|
7
|
-
let onClick;
|
|
8
|
-
|
|
9
|
-
describe('TrajservLayer', () => {
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
global.fetch = fetch;
|
|
12
|
-
fetch.resetMocks();
|
|
13
|
-
|
|
14
|
-
onClick = jest.fn();
|
|
15
|
-
layer = new TrajservLayer({
|
|
16
|
-
apiKey: 'foo',
|
|
17
|
-
onClick,
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test('should be instanced.', () => {
|
|
22
|
-
expect(layer).toBeInstanceOf(TrajservLayer);
|
|
23
|
-
expect(layer.clickCallbacks[0]).toBe(onClick);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('should called terminate on initalization.', () => {
|
|
27
|
-
const spy = jest.spyOn(layer, 'terminate');
|
|
28
|
-
|
|
29
|
-
fetch.mockResponseOnce(JSON.stringify(global.fetchTrajectoriesResponse));
|
|
30
|
-
|
|
31
|
-
const mapElement = document.createElement('div');
|
|
32
|
-
const { style } = mapElement;
|
|
33
|
-
style.position = 'absolute';
|
|
34
|
-
style.left = '0px';
|
|
35
|
-
style.top = '0px';
|
|
36
|
-
style.width = '400px';
|
|
37
|
-
style.height = '400px';
|
|
38
|
-
mapElement.setAttribute('id', 'map');
|
|
39
|
-
document.body.appendChild(mapElement);
|
|
40
|
-
|
|
41
|
-
layer.init(
|
|
42
|
-
new maplibre.Map({
|
|
43
|
-
container: document.getElementById('map'),
|
|
44
|
-
style: `path/to/style`,
|
|
45
|
-
center: toLonLat([831634, 5933959]),
|
|
46
|
-
zoom: 9,
|
|
47
|
-
}),
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
expect(spy).toHaveBeenCalledTimes(1);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('#onClick', () => {
|
|
54
|
-
const f = () => {};
|
|
55
|
-
layer.onClick(f);
|
|
56
|
-
expect(layer.clickCallbacks[1]).toBe(f);
|
|
57
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
58
|
-
layer.onClick(f);
|
|
59
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('#unClick', () => {
|
|
63
|
-
const foo = () => {};
|
|
64
|
-
const bar = () => {};
|
|
65
|
-
layer.onClick(foo);
|
|
66
|
-
layer.onClick(bar);
|
|
67
|
-
expect(layer.clickCallbacks[1]).toBe(foo);
|
|
68
|
-
expect(layer.clickCallbacks[2]).toBe(bar);
|
|
69
|
-
expect(layer.clickCallbacks.length).toBe(3);
|
|
70
|
-
layer.unClick(foo);
|
|
71
|
-
expect(layer.clickCallbacks[1]).toBe(bar);
|
|
72
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('should create a default api with default url.', () => {
|
|
76
|
-
expect(layer).toBeInstanceOf(TrajservLayer);
|
|
77
|
-
expect(layer.api.url).toBe('https://api.geops.io/tracker/v1');
|
|
78
|
-
expect(layer.api.apiKey).toBe('foo');
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test('should create an api with custom url and apiKey.', () => {
|
|
82
|
-
const layr = new TrajservLayer({
|
|
83
|
-
url: 'https:foo.ch',
|
|
84
|
-
apiKey: 'bar',
|
|
85
|
-
});
|
|
86
|
-
expect(layr).toBeInstanceOf(TrajservLayer);
|
|
87
|
-
expect(layr.api.url).toBe('https:foo.ch');
|
|
88
|
-
expect(layr.api.apiKey).toBe('bar');
|
|
89
|
-
});
|
|
90
|
-
});
|
package/ol/Map.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import OLMap from 'ol/Map';
|
|
2
|
-
import { defaults as defaultControls } from 'ol/control';
|
|
3
|
-
import Layer from './layers/Layer';
|
|
4
|
-
import mixin from '../common/mixins/MapMixin';
|
|
5
|
-
import CopyrightControl from './controls/CopyrightControl';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* An OpenLayers map for handling mobility layers and controls.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* import { Map } from 'mobility-toolbox-js/ol';
|
|
12
|
-
*
|
|
13
|
-
* const map = new Map({
|
|
14
|
-
* target: 'map',
|
|
15
|
-
* view: new View({
|
|
16
|
-
* center: [0, 0],
|
|
17
|
-
* zoom: 1,
|
|
18
|
-
* }),
|
|
19
|
-
* });
|
|
20
|
-
*
|
|
21
|
-
* @see <a href="/example/ol-map">Map example</a>
|
|
22
|
-
*
|
|
23
|
-
* @extends {ol/Map~Map}
|
|
24
|
-
*/
|
|
25
|
-
class Map extends mixin(OLMap) {
|
|
26
|
-
/**
|
|
27
|
-
* Constructor.
|
|
28
|
-
*
|
|
29
|
-
* @param {Object} options See [ol/Map~Map](https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html) options documentation.
|
|
30
|
-
* @param {Array<Layer|ol/layer/Layer~Layer>} [options.layers] Array of layers.
|
|
31
|
-
*/
|
|
32
|
-
constructor(options = {}) {
|
|
33
|
-
super({
|
|
34
|
-
controls: [
|
|
35
|
-
...defaultControls({ attribution: false }).getArray(),
|
|
36
|
-
new CopyrightControl(),
|
|
37
|
-
],
|
|
38
|
-
...options,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get the HTML element containing the map.
|
|
44
|
-
*
|
|
45
|
-
* @return {HTMLElement} The HTML element of the container.
|
|
46
|
-
*/
|
|
47
|
-
getContainer() {
|
|
48
|
-
return this.getTargetElement();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Adds a layer to the map.
|
|
53
|
-
* @param {Layer|ol/layer/Layer~Layer} layer The layer to add.
|
|
54
|
-
*/
|
|
55
|
-
addLayer(layer) {
|
|
56
|
-
if (layer instanceof Layer) {
|
|
57
|
-
// layer is an mobility layer
|
|
58
|
-
layer.init(this);
|
|
59
|
-
this.mobilityLayers.push(layer);
|
|
60
|
-
|
|
61
|
-
if (layer.olLayer) {
|
|
62
|
-
super.addLayer(layer.olLayer);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
this.dispatchEvent({
|
|
66
|
-
type: 'change:mobilityLayers',
|
|
67
|
-
target: this,
|
|
68
|
-
});
|
|
69
|
-
} else {
|
|
70
|
-
// layer is an OpenLayer layer
|
|
71
|
-
super.addLayer(layer);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Removes a given layer from the map.
|
|
77
|
-
* @param {Layer|ol/layer/Layer~Layer} layer The layer to remove.
|
|
78
|
-
*/
|
|
79
|
-
removeLayer(layer) {
|
|
80
|
-
if (layer instanceof Layer) {
|
|
81
|
-
layer.terminate();
|
|
82
|
-
this.mobilityLayers = this.mobilityLayers.filter((l) => l !== layer);
|
|
83
|
-
if (layer.olLayer) {
|
|
84
|
-
super.removeLayer(layer);
|
|
85
|
-
}
|
|
86
|
-
} else {
|
|
87
|
-
// layer is an OpenLayer layer
|
|
88
|
-
super.removeLayer(layer);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Adds a given control to the map.
|
|
94
|
-
* @param {Control|ol/control/Control~Control} control The control to add.
|
|
95
|
-
*/
|
|
96
|
-
addControl(control) {
|
|
97
|
-
super.addControl(control);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Removes a given control to the map.
|
|
102
|
-
* @param {Control|ol/control/Control~Control} control The control to remove.
|
|
103
|
-
*/
|
|
104
|
-
removeControl(control) {
|
|
105
|
-
super.removeControl(control);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export default Map;
|
package/ol/Map.test.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import VectorLayer from 'ol/layer/Vector';
|
|
2
|
-
import VectorSource from 'ol/source/Vector';
|
|
3
|
-
import Map from './Map';
|
|
4
|
-
import Layer from './layers/Layer';
|
|
5
|
-
|
|
6
|
-
const olLayer = new VectorLayer({ source: new VectorSource() });
|
|
7
|
-
|
|
8
|
-
describe('Map', () => {
|
|
9
|
-
let map;
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
map = new Map({ target: document.body });
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test('should init layer on add.', () => {
|
|
16
|
-
const layer = new Layer({ name: 'Layer', olLayer });
|
|
17
|
-
const spy = jest.spyOn(layer, 'init');
|
|
18
|
-
map.addLayer(layer);
|
|
19
|
-
expect(spy).toHaveBeenCalledTimes(1);
|
|
20
|
-
expect(map.getLayers().getLength()).toBe(1);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('should terminate layer on remove.', () => {
|
|
24
|
-
const layer = new Layer({ name: 'Layer', olLayer });
|
|
25
|
-
const spy = jest.spyOn(layer, 'terminate');
|
|
26
|
-
map.addLayer(layer);
|
|
27
|
-
expect(map.getLayers().getLength()).toBe(1);
|
|
28
|
-
expect(spy).toHaveBeenCalledTimes(1);
|
|
29
|
-
map.removeLayer(layer);
|
|
30
|
-
expect(spy).toHaveBeenCalledTimes(2);
|
|
31
|
-
expect(layer.visible).toBe(true);
|
|
32
|
-
expect(map.getLayers().getLength()).toBe(1);
|
|
33
|
-
});
|
|
34
|
-
});
|