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,296 +0,0 @@
|
|
|
1
|
-
import { Layer as OLLayer, Group, Vector as VectorLayer } from 'ol/layer';
|
|
2
|
-
import Source from 'ol/source/Source';
|
|
3
|
-
import { composeCssTransform } from 'ol/transform';
|
|
4
|
-
import { Vector as VectorSource } from 'ol/source';
|
|
5
|
-
import mixin from '../../common/mixins/TrackerLayerMixin';
|
|
6
|
-
|
|
7
|
-
import Layer from './Layer';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Responsible for loading tracker data.
|
|
11
|
-
*
|
|
12
|
-
* @classproperty {ol/Map~Map} map - The map where the layer is displayed.
|
|
13
|
-
* @extends {Layer}
|
|
14
|
-
* @implements {TrackerLayerInterface}
|
|
15
|
-
*/
|
|
16
|
-
class TrackerLayer extends mixin(Layer) {
|
|
17
|
-
/**
|
|
18
|
-
* Constructor.
|
|
19
|
-
*
|
|
20
|
-
* @param {Object} options
|
|
21
|
-
* @param {boolean} options.useDelayStyle Set the delay style.
|
|
22
|
-
* @private
|
|
23
|
-
*/
|
|
24
|
-
constructor(options = {}) {
|
|
25
|
-
// We use a group to be able to add custom vector layer in extended class.
|
|
26
|
-
// For example TrajservLayer use a vectorLayer to display the complete trajectory.
|
|
27
|
-
super({
|
|
28
|
-
...options,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
/** @ignore */
|
|
32
|
-
this.olLayer =
|
|
33
|
-
options.olLayer ||
|
|
34
|
-
new Group({
|
|
35
|
-
layers: [
|
|
36
|
-
new VectorLayer({
|
|
37
|
-
source: new VectorSource({ features: [] }),
|
|
38
|
-
}),
|
|
39
|
-
new OLLayer({
|
|
40
|
-
source: new Source({}),
|
|
41
|
-
render: (frameState) => {
|
|
42
|
-
if (!this.tracker || !this.tracker.canvas) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!this.container) {
|
|
47
|
-
this.container = document.createElement('div');
|
|
48
|
-
this.container.style.position = 'absolute';
|
|
49
|
-
this.container.style.width = '100%';
|
|
50
|
-
this.container.style.height = '100%';
|
|
51
|
-
this.transformContainer = document.createElement('div');
|
|
52
|
-
this.transformContainer.style.position = 'absolute';
|
|
53
|
-
this.transformContainer.style.width = '100%';
|
|
54
|
-
this.transformContainer.style.height = '100%';
|
|
55
|
-
this.container.appendChild(this.transformContainer);
|
|
56
|
-
this.tracker.canvas.style.position = 'absolute';
|
|
57
|
-
this.tracker.canvas.style.top = '0';
|
|
58
|
-
this.tracker.canvas.style.left = '0';
|
|
59
|
-
this.tracker.canvas.style.transformOrigin = 'top left';
|
|
60
|
-
this.transformContainer.appendChild(this.tracker.canvas);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (this.renderedViewState) {
|
|
64
|
-
const { center, resolution, rotation } = frameState.viewState;
|
|
65
|
-
const {
|
|
66
|
-
center: renderedCenter,
|
|
67
|
-
resolution: renderedResolution,
|
|
68
|
-
rotation: renderedRotation,
|
|
69
|
-
} = this.renderedViewState;
|
|
70
|
-
|
|
71
|
-
if (renderedResolution / resolution >= 3) {
|
|
72
|
-
// Avoid having really big points when zooming fast.
|
|
73
|
-
const { canvas } = this.tracker;
|
|
74
|
-
const context = canvas.getContext('2d');
|
|
75
|
-
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
76
|
-
} else {
|
|
77
|
-
const pixelCenterRendered =
|
|
78
|
-
this.map.getPixelFromCoordinate(renderedCenter);
|
|
79
|
-
const pixelCenter = this.map.getPixelFromCoordinate(center);
|
|
80
|
-
this.transformContainer.style.transform = composeCssTransform(
|
|
81
|
-
pixelCenterRendered[0] - pixelCenter[0],
|
|
82
|
-
pixelCenterRendered[1] - pixelCenter[1],
|
|
83
|
-
renderedResolution / resolution,
|
|
84
|
-
renderedResolution / resolution,
|
|
85
|
-
rotation - renderedRotation,
|
|
86
|
-
0,
|
|
87
|
-
0,
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return this.container;
|
|
92
|
-
},
|
|
93
|
-
}),
|
|
94
|
-
],
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// We store the layer used to highlight the full Trajectory
|
|
98
|
-
this.vectorLayer = this.olLayer.getLayers().item(0);
|
|
99
|
-
|
|
100
|
-
// Options the last render run did happen. If something changes
|
|
101
|
-
// we have to render again
|
|
102
|
-
/** @ignore */
|
|
103
|
-
this.renderState = {
|
|
104
|
-
center: [0, 0],
|
|
105
|
-
zoom: null,
|
|
106
|
-
rotation: 0,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
init(map) {
|
|
111
|
-
super.init(map);
|
|
112
|
-
if (this.map) {
|
|
113
|
-
this.olListenersKeys.push(
|
|
114
|
-
this.map.on('moveend', (evt) => {
|
|
115
|
-
const view = this.map.getView();
|
|
116
|
-
if (view.getAnimating() || view.getInteracting()) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const zoom = view.getZoom();
|
|
120
|
-
|
|
121
|
-
// Update the interval between render updates
|
|
122
|
-
if (this.currentZoom !== zoom) {
|
|
123
|
-
this.onZoomEnd(evt);
|
|
124
|
-
}
|
|
125
|
-
this.currentZoom = zoom;
|
|
126
|
-
|
|
127
|
-
this.onMoveEnd(evt);
|
|
128
|
-
}),
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Destroy the container of the tracker.
|
|
135
|
-
*/
|
|
136
|
-
terminate() {
|
|
137
|
-
super.terminate();
|
|
138
|
-
this.container = null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Detect in the canvas if there is data to query at a specific coordinate.
|
|
143
|
-
* @param {ol/coordinate~Coordinate} coordinate The coordinate to test
|
|
144
|
-
* @returns
|
|
145
|
-
*/
|
|
146
|
-
hasFeatureInfoAtCoordinate(coordinate) {
|
|
147
|
-
if (this.map && this.tracker && this.tracker.canvas) {
|
|
148
|
-
const context = this.tracker.canvas.getContext('2d');
|
|
149
|
-
const pixel = this.map.getPixelFromCoordinate(coordinate);
|
|
150
|
-
return !!context.getImageData(
|
|
151
|
-
pixel[0] * this.pixelRatio,
|
|
152
|
-
pixel[1] * this.pixelRatio,
|
|
153
|
-
1,
|
|
154
|
-
1,
|
|
155
|
-
).data[3];
|
|
156
|
-
}
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Render the trajectories using current map's size, resolution and rotation.
|
|
162
|
-
* @param {boolean} noInterpolate if true, renders the vehicles without interpolating theirs positions.
|
|
163
|
-
* @overrides
|
|
164
|
-
*/
|
|
165
|
-
renderTrajectories(noInterpolate) {
|
|
166
|
-
const view = this.map.getView();
|
|
167
|
-
super.renderTrajectories(
|
|
168
|
-
{
|
|
169
|
-
size: this.map.getSize(),
|
|
170
|
-
center: this.map.getView().getCenter(),
|
|
171
|
-
extent: view.calculateExtent(),
|
|
172
|
-
resolution: view.getResolution(),
|
|
173
|
-
rotation: view.getRotation(),
|
|
174
|
-
zoom: view.getZoom(),
|
|
175
|
-
pixelRatio: this.pixelRatio,
|
|
176
|
-
},
|
|
177
|
-
noInterpolate,
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Launch renderTrajectories. it avoids duplicating code in renderTrajectories methhod.
|
|
183
|
-
* @private
|
|
184
|
-
* @override
|
|
185
|
-
*/
|
|
186
|
-
renderTrajectoriesInternal(viewState, noInterpolate) {
|
|
187
|
-
let isRendered = false;
|
|
188
|
-
|
|
189
|
-
const blockRendering =
|
|
190
|
-
this.map.getView().getAnimating() || this.map.getView().getInteracting();
|
|
191
|
-
|
|
192
|
-
// Don't render the map when the map is animating or interacting.
|
|
193
|
-
isRendered = blockRendering
|
|
194
|
-
? false
|
|
195
|
-
: super.renderTrajectoriesInternal(viewState, noInterpolate);
|
|
196
|
-
|
|
197
|
-
// We update the current render state.
|
|
198
|
-
if (isRendered) {
|
|
199
|
-
this.renderedViewState = { ...viewState };
|
|
200
|
-
|
|
201
|
-
if (this.transformContainer) {
|
|
202
|
-
this.transformContainer.style.transform = '';
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Return the delay in ms before the next rendering.
|
|
209
|
-
*/
|
|
210
|
-
getRefreshTimeInMs() {
|
|
211
|
-
return super.getRefreshTimeInMs(this.map.getView().getZoom());
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Returns the vehicle which are at the given coordinates.
|
|
216
|
-
* Returns null when no vehicle is located at the given coordinates.
|
|
217
|
-
* @param {ol/coordinate~Coordinate} coordinate
|
|
218
|
-
* @param {number} nb Number of vehicles to return;
|
|
219
|
-
* @return {Array<ol/Feature~Feature>} Vehicle feature.
|
|
220
|
-
* @override
|
|
221
|
-
*/
|
|
222
|
-
getVehiclesAtCoordinate(coordinate, nb) {
|
|
223
|
-
const resolution = this.map.getView().getResolution();
|
|
224
|
-
return super.getVehiclesAtCoordinate(coordinate, resolution, nb);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
getFeatureInfoAtCoordinate(coordinate, options = {}) {
|
|
228
|
-
if (!this.hasFeatureInfoAtCoordinate(coordinate)) {
|
|
229
|
-
return Promise.resolve({ features: [], layer: this, coordinate });
|
|
230
|
-
}
|
|
231
|
-
const resolution = this.map.getView().getResolution();
|
|
232
|
-
return super.getFeatureInfoAtCoordinate(coordinate, {
|
|
233
|
-
resolution,
|
|
234
|
-
...options,
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Function called on moveend event.
|
|
240
|
-
* To be defined in inherited classes
|
|
241
|
-
*
|
|
242
|
-
* @param {ol/MapEvent~MapEvent} evt Moveend event.
|
|
243
|
-
* @private
|
|
244
|
-
*/
|
|
245
|
-
// eslint-disable-next-line no-unused-vars,class-methods-use-this
|
|
246
|
-
onMoveEnd(evt) {}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Function called on moveend event only when the zoom has changed.
|
|
250
|
-
*
|
|
251
|
-
* @param {ol/MapEvent~MapEvent} evt Moveend event.
|
|
252
|
-
* @private
|
|
253
|
-
* @override
|
|
254
|
-
*/
|
|
255
|
-
// eslint-disable-next-line no-unused-vars
|
|
256
|
-
onZoomEnd(evt) {
|
|
257
|
-
super.onZoomEnd(evt);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Update the cursor style when hovering a vehicle.
|
|
262
|
-
*
|
|
263
|
-
* @private
|
|
264
|
-
* @override
|
|
265
|
-
*/
|
|
266
|
-
onFeatureHover(features, layer, coordinate) {
|
|
267
|
-
super.onFeatureHover(features, layer, coordinate);
|
|
268
|
-
this.map.getTargetElement().style.cursor = features.length
|
|
269
|
-
? 'pointer'
|
|
270
|
-
: 'auto';
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Display the complete trajectory of the vehicle.
|
|
275
|
-
*
|
|
276
|
-
* @private
|
|
277
|
-
* @override
|
|
278
|
-
*/
|
|
279
|
-
onFeatureClick(features, layer, coordinate) {
|
|
280
|
-
super.onFeatureClick(features, layer, coordinate);
|
|
281
|
-
if (!features.length && this.vectorLayer) {
|
|
282
|
-
this.vectorLayer.getSource().clear();
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Create a copy of the TrackerLayer.
|
|
288
|
-
* @param {Object} newOptions Options to override
|
|
289
|
-
* @return {TrackerLayer} A TrackerLayer
|
|
290
|
-
*/
|
|
291
|
-
clone(newOptions) {
|
|
292
|
-
return new TrackerLayer({ ...this.options, ...newOptions });
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
export default TrackerLayer;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import Map from 'ol/Map';
|
|
2
|
-
import View from 'ol/View';
|
|
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
|
-
layer.init(
|
|
24
|
-
new Map({
|
|
25
|
-
view: new View({
|
|
26
|
-
center: [831634, 5933959],
|
|
27
|
-
zoom: 9,
|
|
28
|
-
}),
|
|
29
|
-
}),
|
|
30
|
-
);
|
|
31
|
-
expect(spy).toHaveBeenCalledTimes(1);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('#onClick', () => {
|
|
35
|
-
const f = () => {};
|
|
36
|
-
layer.onClick(f);
|
|
37
|
-
expect(layer.clickCallbacks[1]).toBe(f);
|
|
38
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
39
|
-
layer.onClick(f);
|
|
40
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('#unClick', () => {
|
|
44
|
-
const foo = () => {};
|
|
45
|
-
const bar = () => {};
|
|
46
|
-
layer.onClick(foo);
|
|
47
|
-
layer.onClick(bar);
|
|
48
|
-
expect(layer.clickCallbacks[1]).toBe(foo);
|
|
49
|
-
expect(layer.clickCallbacks[2]).toBe(bar);
|
|
50
|
-
expect(layer.clickCallbacks.length).toBe(3);
|
|
51
|
-
layer.unClick(foo);
|
|
52
|
-
expect(layer.clickCallbacks[1]).toBe(bar);
|
|
53
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('#terminate', () => {
|
|
57
|
-
test('should set container to null', () => {
|
|
58
|
-
layer.container = 'foo';
|
|
59
|
-
layer.terminate();
|
|
60
|
-
expect(layer.container).toBe(null);
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test('should clone', () => {
|
|
65
|
-
const clone = layer.clone({ name: 'clone' });
|
|
66
|
-
expect(clone).not.toBe(layer);
|
|
67
|
-
expect(clone.name).toBe('clone');
|
|
68
|
-
expect(clone).toBeInstanceOf(TrackerLayer);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import Feature from 'ol/Feature';
|
|
2
|
-
import { fromLonLat } from 'ol/proj';
|
|
3
|
-
import { buffer, getWidth } from 'ol/extent';
|
|
4
|
-
import { MultiPoint, LineString } from 'ol/geom';
|
|
5
|
-
import { Style, Fill, Stroke, Circle } from 'ol/style';
|
|
6
|
-
import { unByKey } from 'ol/Observable';
|
|
7
|
-
import TrackerLayer from './TrackerLayer';
|
|
8
|
-
|
|
9
|
-
import mixin from '../../common/mixins/TrajservLayerMixin';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Responsible for loading and display data from a Trajserv service.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* import { TrajservLayer } from 'mobility-toolbox-js/mapbox';
|
|
16
|
-
*
|
|
17
|
-
* const layer = new TrajservLayer({
|
|
18
|
-
* url: 'https://api.geops.io/tracker/v1',
|
|
19
|
-
* apiKey: [yourApiKey],
|
|
20
|
-
* });
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @see <a href="/api/class/src/api/trajserv/TrajservAPI%20js~TrajservAPI%20html">TrajservAPI</a>
|
|
24
|
-
* @see <a href="/example/ol-tracker">OL tracker example</a>
|
|
25
|
-
*
|
|
26
|
-
* @extends {TrackerLayer}
|
|
27
|
-
* @implements {TrajservLayerInterface}
|
|
28
|
-
* @deprecated Use {@link TralisLayer} instead.
|
|
29
|
-
*/
|
|
30
|
-
class TrajservLayer extends mixin(TrackerLayer) {
|
|
31
|
-
/**
|
|
32
|
-
* Start the layer.
|
|
33
|
-
* @override
|
|
34
|
-
*/
|
|
35
|
-
start() {
|
|
36
|
-
if (!this.map) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
super.start();
|
|
40
|
-
/**
|
|
41
|
-
* Array of ol events key, returned by on() or once().
|
|
42
|
-
* @type {Array<ol/events~EventsKey>}
|
|
43
|
-
* @ignore
|
|
44
|
-
*/
|
|
45
|
-
this.olEventsKeys = [
|
|
46
|
-
this.map.on('movestart', () => {
|
|
47
|
-
this.abortFetchTrajectories();
|
|
48
|
-
}),
|
|
49
|
-
this.map.on('moveend', this.onMoveEnd.bind(this)),
|
|
50
|
-
];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
stop() {
|
|
54
|
-
unByKey(this.olEventsKeys);
|
|
55
|
-
super.stop();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Callback on 'moveend' event.
|
|
60
|
-
* @private
|
|
61
|
-
*/
|
|
62
|
-
onMoveEnd() {
|
|
63
|
-
const z = this.map.getView().getZoom();
|
|
64
|
-
|
|
65
|
-
if (z !== this.currentZoom) {
|
|
66
|
-
/**
|
|
67
|
-
* Current value of the zoom.
|
|
68
|
-
* @type {number}
|
|
69
|
-
* @ignore
|
|
70
|
-
*/
|
|
71
|
-
this.currentZoom = z;
|
|
72
|
-
|
|
73
|
-
// This will restart the timeouts.
|
|
74
|
-
// TODO maybe find a calculation a bit less approximative.
|
|
75
|
-
/** @ignore */
|
|
76
|
-
this.requestIntervalSeconds = 200 / z || 1000;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
this.abortFetchTrajectories();
|
|
80
|
-
if (
|
|
81
|
-
!this.map.getView().getAnimating() &&
|
|
82
|
-
!this.map.getView().getInteracting()
|
|
83
|
-
) {
|
|
84
|
-
this.updateTrajectories();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (this.selectedVehicleId && this.journeyId) {
|
|
88
|
-
this.highlightTrajectory();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Draw the trajectory as a line with points for each stop.
|
|
94
|
-
* @param {Array} stationsCoords Array of station coordinates in epsg:4326.
|
|
95
|
-
* @param {Array<ol/coordinate~Coordinate>} lineCoords A list of coordinates.
|
|
96
|
-
* @param {string} color The color of the line.
|
|
97
|
-
* @private
|
|
98
|
-
*/
|
|
99
|
-
drawFullTrajectory(stationsCoords, lineCoords, color) {
|
|
100
|
-
const vectorSource = this.vectorLayer.getSource();
|
|
101
|
-
vectorSource.clear();
|
|
102
|
-
|
|
103
|
-
// Add station points
|
|
104
|
-
if (stationsCoords) {
|
|
105
|
-
const geometry = new MultiPoint(
|
|
106
|
-
stationsCoords.map((coords) => fromLonLat(coords)),
|
|
107
|
-
);
|
|
108
|
-
const aboveStationsFeature = new Feature(geometry);
|
|
109
|
-
aboveStationsFeature.setStyle(
|
|
110
|
-
new Style({
|
|
111
|
-
zIndex: 1,
|
|
112
|
-
image: new Circle({
|
|
113
|
-
radius: 5,
|
|
114
|
-
fill: new Fill({
|
|
115
|
-
color: '#000000',
|
|
116
|
-
}),
|
|
117
|
-
}),
|
|
118
|
-
}),
|
|
119
|
-
);
|
|
120
|
-
const belowStationsFeature = new Feature(geometry);
|
|
121
|
-
belowStationsFeature.setStyle(
|
|
122
|
-
new Style({
|
|
123
|
-
zIndex: 4,
|
|
124
|
-
image: new Circle({
|
|
125
|
-
radius: 4,
|
|
126
|
-
fill: new Fill({
|
|
127
|
-
color,
|
|
128
|
-
}),
|
|
129
|
-
}),
|
|
130
|
-
}),
|
|
131
|
-
);
|
|
132
|
-
vectorSource.addFeatures([aboveStationsFeature, belowStationsFeature]);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Add line.
|
|
136
|
-
if (lineCoords) {
|
|
137
|
-
const lineFeat = new Feature({
|
|
138
|
-
geometry: new LineString(lineCoords),
|
|
139
|
-
});
|
|
140
|
-
lineFeat.setStyle([
|
|
141
|
-
new Style({
|
|
142
|
-
zIndex: 2,
|
|
143
|
-
stroke: new Stroke({
|
|
144
|
-
color: '#000000',
|
|
145
|
-
width: 6,
|
|
146
|
-
}),
|
|
147
|
-
}),
|
|
148
|
-
new Style({
|
|
149
|
-
zIndex: 3,
|
|
150
|
-
stroke: new Stroke({
|
|
151
|
-
color,
|
|
152
|
-
width: 4,
|
|
153
|
-
}),
|
|
154
|
-
}),
|
|
155
|
-
]);
|
|
156
|
-
vectorSource.addFeature(lineFeat);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* @override
|
|
162
|
-
* * Returns the URL parameters.
|
|
163
|
-
* @param {Object} extraParams Extra parameters
|
|
164
|
-
* @return {Object}
|
|
165
|
-
* @private
|
|
166
|
-
*/
|
|
167
|
-
getParams(extraParams = {}) {
|
|
168
|
-
const ext = this.map.getView().calculateExtent();
|
|
169
|
-
const bbox = buffer(ext, getWidth(ext) / 10).join(',');
|
|
170
|
-
const zoom = this.map.getView().getZoom();
|
|
171
|
-
|
|
172
|
-
return super.getParams({
|
|
173
|
-
...extraParams,
|
|
174
|
-
bbox,
|
|
175
|
-
s: zoom < 10 ? 1 : 0,
|
|
176
|
-
z: zoom,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Create a copy of the TrajservLayer.
|
|
182
|
-
* @param {Object} newOptions Options to override
|
|
183
|
-
* @return {TrajservLayer} A TrajservLayer
|
|
184
|
-
*/
|
|
185
|
-
clone(newOptions) {
|
|
186
|
-
return new TrajservLayer({ ...this.options, ...newOptions });
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export default TrajservLayer;
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import fetch from 'jest-fetch-mock';
|
|
2
|
-
import Map from 'ol/Map';
|
|
3
|
-
import View from 'ol/View';
|
|
4
|
-
import TrajservLayer from './TrajservLayer';
|
|
5
|
-
|
|
6
|
-
let layer;
|
|
7
|
-
let onClick;
|
|
8
|
-
let olMap;
|
|
9
|
-
|
|
10
|
-
describe('TrajservLayer', () => {
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
global.fetch = fetch;
|
|
13
|
-
fetch.resetMocks();
|
|
14
|
-
|
|
15
|
-
onClick = jest.fn();
|
|
16
|
-
layer = new TrajservLayer({
|
|
17
|
-
apiKey: 'apiKey',
|
|
18
|
-
onClick,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
olMap = new Map({
|
|
22
|
-
view: new View({
|
|
23
|
-
center: [831634, 5933959],
|
|
24
|
-
zoom: 9,
|
|
25
|
-
}),
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('should be instanced.', () => {
|
|
30
|
-
expect(layer).toBeInstanceOf(TrajservLayer);
|
|
31
|
-
expect(layer.clickCallbacks[0]).toBe(onClick);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('should called terminate on initalization.', () => {
|
|
35
|
-
const spy = jest.spyOn(layer, 'terminate');
|
|
36
|
-
|
|
37
|
-
fetch.mockResponseOnce(JSON.stringify(global.fetchTrajectoriesResponse));
|
|
38
|
-
|
|
39
|
-
layer.init(olMap);
|
|
40
|
-
expect(spy).toHaveBeenCalledTimes(1);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('#onClick', () => {
|
|
44
|
-
const f = () => {};
|
|
45
|
-
layer.onClick(f);
|
|
46
|
-
expect(layer.clickCallbacks[1]).toBe(f);
|
|
47
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
48
|
-
layer.onClick(f);
|
|
49
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('#unClick', () => {
|
|
53
|
-
const foo = () => {};
|
|
54
|
-
const bar = () => {};
|
|
55
|
-
layer.onClick(foo);
|
|
56
|
-
layer.onClick(bar);
|
|
57
|
-
expect(layer.clickCallbacks[1]).toBe(foo);
|
|
58
|
-
expect(layer.clickCallbacks[2]).toBe(bar);
|
|
59
|
-
expect(layer.clickCallbacks.length).toBe(3);
|
|
60
|
-
layer.unClick(foo);
|
|
61
|
-
expect(layer.clickCallbacks[1]).toBe(bar);
|
|
62
|
-
expect(layer.clickCallbacks.length).toBe(2);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test("map events should be called if zoom doesn't change", () => {
|
|
66
|
-
const spy2 = jest.spyOn(layer, 'onMoveEnd');
|
|
67
|
-
|
|
68
|
-
// Mock response for the following calls
|
|
69
|
-
fetch.mockResponse(JSON.stringify(global.fetchTrajectoriesResponse));
|
|
70
|
-
|
|
71
|
-
// init uses mockResponse
|
|
72
|
-
layer.init(olMap);
|
|
73
|
-
|
|
74
|
-
// Start uses mockResponse
|
|
75
|
-
layer.start();
|
|
76
|
-
|
|
77
|
-
// dispatchEvent uses mockResponse
|
|
78
|
-
const evt2 = { type: 'moveend', olMap };
|
|
79
|
-
olMap.dispatchEvent(evt2);
|
|
80
|
-
expect(spy2).toHaveBeenCalledTimes(2);
|
|
81
|
-
olMap.dispatchEvent(evt2);
|
|
82
|
-
expect(spy2).toHaveBeenCalledTimes(4);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('should create a default api with default url.', () => {
|
|
86
|
-
expect(layer).toBeInstanceOf(TrajservLayer);
|
|
87
|
-
expect(layer.api.url).toBe('https://api.geops.io/tracker/v1');
|
|
88
|
-
expect(layer.api.apiKey).toBe('apiKey');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test('should create an api with custom url and apiKey.', () => {
|
|
92
|
-
const layr = new TrajservLayer({
|
|
93
|
-
url: 'https:foo.ch',
|
|
94
|
-
apiKey: 'bar',
|
|
95
|
-
});
|
|
96
|
-
expect(layr).toBeInstanceOf(TrajservLayer);
|
|
97
|
-
expect(layr.api.url).toBe('https:foo.ch');
|
|
98
|
-
expect(layr.api.apiKey).toBe('bar');
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test('should clone', () => {
|
|
102
|
-
const layr = new TrajservLayer({
|
|
103
|
-
name: 'test',
|
|
104
|
-
url: 'https:foo.ch',
|
|
105
|
-
apiKey: 'bar',
|
|
106
|
-
});
|
|
107
|
-
const clone = layr.clone({ name: 'clone' });
|
|
108
|
-
expect(layr.name).toBe('test');
|
|
109
|
-
expect(clone).not.toBe(layr);
|
|
110
|
-
expect(clone.name).toBe('clone');
|
|
111
|
-
expect(clone).toBeInstanceOf(TrajservLayer);
|
|
112
|
-
});
|
|
113
|
-
});
|