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,745 +0,0 @@
|
|
|
1
|
-
/* eslint-disable class-methods-use-this */
|
|
2
|
-
/* eslint-disable max-classes-per-file */
|
|
3
|
-
import { buffer, containsCoordinate } from 'ol/extent';
|
|
4
|
-
import { unByKey } from 'ol/Observable';
|
|
5
|
-
import qs from 'query-string';
|
|
6
|
-
import debounce from 'lodash.debounce';
|
|
7
|
-
import throttle from 'lodash.throttle';
|
|
8
|
-
import Tracker from '../Tracker';
|
|
9
|
-
import { timeSteps } from '../trackerConfig';
|
|
10
|
-
import createFilters from '../utils/createTrackerFilters';
|
|
11
|
-
import { delayTrackerStyle } from '../utils';
|
|
12
|
-
|
|
13
|
-
/* Permalink parameter used to filters vehicles */
|
|
14
|
-
const LINE_FILTER = 'publishedlinename';
|
|
15
|
-
const ROUTE_FILTER = 'tripnumber';
|
|
16
|
-
const OPERATOR_FILTER = 'operator';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* TrackerLayerInterface.
|
|
20
|
-
*
|
|
21
|
-
* @classproperty {string} hoverVehicleId - Id of the hovered vehicle.
|
|
22
|
-
* @classproperty {string} selectedVehicleId - Id of the selected vehicle.
|
|
23
|
-
* @classproperty {number} pixelRatio - Pixel ratio use to render the trajectories. Default to window.devicePixelRatio.
|
|
24
|
-
* @classproperty {boolean} live - If true, the layer will always use Date.now() to render trajectories. Default to true.
|
|
25
|
-
* @classproperty {boolean} useRequestAnimationFrame - If true, encapsulates the renderTrajectories calls in a requestAnimationFrame. Experimental.
|
|
26
|
-
* @classproperty {boolean} useThrottle - If true, encapsulates the renderTrajectories calls in a throttle function. Experimental.
|
|
27
|
-
* @classproperty {boolean} useDebounce - If true, encapsulates the renderTrajectories calls in a debounce function. Experimental.
|
|
28
|
-
* @classproperty {boolean} isTrackerLayer - Property for duck typing since `instanceof` is not working when the instance was created on different bundles.
|
|
29
|
-
* @classproperty {function} sort - Sort the trajectories.
|
|
30
|
-
* @classproperty {function} style - Style of a trajectory.
|
|
31
|
-
* @classproperty {Date} time - Time used to display the trajectories. The setter manages a Date or a number in ms representing a Date. If `live` property is true. The setter does nothing..
|
|
32
|
-
* @classproperty {FilterFunction} filter - Filter the trajectories.
|
|
33
|
-
*/
|
|
34
|
-
export class TrackerLayerInterface {
|
|
35
|
-
/**
|
|
36
|
-
* Initalize the Tracker.
|
|
37
|
-
* @param {ol/Map~Map} map
|
|
38
|
-
* @param {Object} options
|
|
39
|
-
* @param {number} [options.width] Canvas's width.
|
|
40
|
-
* @param {number} [options.height] Canvas's height.
|
|
41
|
-
*/
|
|
42
|
-
// eslint-disable-next-line no-unused-vars
|
|
43
|
-
init(map, options) {}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Destroy the Tracker.
|
|
47
|
-
*/
|
|
48
|
-
terminate() {}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Start the clock.
|
|
52
|
-
*/
|
|
53
|
-
start() {}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Start the timeout for the next update.
|
|
57
|
-
* @private
|
|
58
|
-
*/
|
|
59
|
-
startUpdateTime() {}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Stop the clock.
|
|
63
|
-
*/
|
|
64
|
-
stop() {}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Get vehicle.
|
|
68
|
-
* @param {function} filterFc A function use to filter results.
|
|
69
|
-
*/
|
|
70
|
-
// eslint-disable-next-line no-unused-vars
|
|
71
|
-
getVehicle(filterFc) {}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Returns the list of vehicles which are at the given coordinates.
|
|
75
|
-
* Returns an empty array when no vehicle is located at the given
|
|
76
|
-
* coordinates.
|
|
77
|
-
*
|
|
78
|
-
* @param {number[2]} coordinate A coordinate ([x,y]).
|
|
79
|
-
* @param {number} [resolution=1] The resolution of the map.
|
|
80
|
-
* @param {number} [nb=Infinity] nb The max number of vehicles to return.
|
|
81
|
-
* @return {Array<ol/Feature~Feature>} Array of vehicles.
|
|
82
|
-
*/
|
|
83
|
-
// eslint-disable-next-line no-unused-vars
|
|
84
|
-
getVehiclesAtCoordinate(coordinate, resolution = 1, nb = Infinity) {}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Get the duration before the next update depending on zoom level.
|
|
88
|
-
* @private
|
|
89
|
-
* @param {number} zoom
|
|
90
|
-
*/
|
|
91
|
-
// eslint-disable-next-line no-unused-vars
|
|
92
|
-
getRefreshTimeInMs(zoom) {}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Define a default style of vehicles.
|
|
96
|
-
* Draw a blue circle with the id of the props parameter.
|
|
97
|
-
*
|
|
98
|
-
* @param {Object} trajectory A trajectory
|
|
99
|
-
* @param {ViewState} viewState Map's view state (zoom, resolution, center, ...)
|
|
100
|
-
* @private
|
|
101
|
-
*/
|
|
102
|
-
// eslint-disable-next-line no-unused-vars
|
|
103
|
-
defaultStyle(trajectory, viewState) {}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Mixin for TrackeLayerInterface.
|
|
108
|
-
*
|
|
109
|
-
* @param {Class} Base A class to extend with {TrackerLayerInterface} functionnalities.
|
|
110
|
-
* @return {Class} A class that implements <TrackerLayerInterface> class and extends Base;
|
|
111
|
-
* @private
|
|
112
|
-
*/
|
|
113
|
-
const TrackerLayerMixin = (Base) =>
|
|
114
|
-
class extends Base {
|
|
115
|
-
constructor(options) {
|
|
116
|
-
super({ hitTolerance: 10, ...options });
|
|
117
|
-
this.onFeatureHover = this.onFeatureHover.bind(this);
|
|
118
|
-
this.onFeatureClick = this.onFeatureClick.bind(this);
|
|
119
|
-
this.renderTrajectoriesInternal =
|
|
120
|
-
this.renderTrajectoriesInternal.bind(this);
|
|
121
|
-
|
|
122
|
-
this.throttleRenderTrajectories = throttle(
|
|
123
|
-
this.renderTrajectoriesInternal,
|
|
124
|
-
50,
|
|
125
|
-
{ leading: false, trailing: true },
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
this.debounceRenderTrajectories = debounce(
|
|
129
|
-
this.renderTrajectoriesInternal,
|
|
130
|
-
50,
|
|
131
|
-
{ leading: true, trailing: true, maxWait: 5000 },
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Define layer's properties.
|
|
137
|
-
*
|
|
138
|
-
* @ignore
|
|
139
|
-
*/
|
|
140
|
-
defineProperties(options) {
|
|
141
|
-
// Tracker options use to build the tracker.
|
|
142
|
-
let { regexPublishedLineName, publishedLineName, tripNumber, operator } =
|
|
143
|
-
options;
|
|
144
|
-
const {
|
|
145
|
-
style,
|
|
146
|
-
speed,
|
|
147
|
-
pixelRatio,
|
|
148
|
-
hoverVehicleId,
|
|
149
|
-
selectedVehicleId,
|
|
150
|
-
filter,
|
|
151
|
-
sort,
|
|
152
|
-
time,
|
|
153
|
-
live,
|
|
154
|
-
} = options;
|
|
155
|
-
|
|
156
|
-
const initTrackerOptions = {
|
|
157
|
-
style,
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
Object.keys(initTrackerOptions).forEach(
|
|
161
|
-
(key) =>
|
|
162
|
-
initTrackerOptions[key] === undefined &&
|
|
163
|
-
delete initTrackerOptions[key],
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
let currSpeed = speed || 1;
|
|
167
|
-
let currTime = time || new Date();
|
|
168
|
-
|
|
169
|
-
super.defineProperties(options);
|
|
170
|
-
|
|
171
|
-
Object.defineProperties(this, {
|
|
172
|
-
isTrackerLayer: { value: true },
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Style function used to render a vehicle.
|
|
176
|
-
*/
|
|
177
|
-
style: {
|
|
178
|
-
value: style || this.defaultStyle,
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Speed of the wheel of time.
|
|
183
|
-
* If live property is true. The speed is ignored.
|
|
184
|
-
*/
|
|
185
|
-
speed: {
|
|
186
|
-
get: () => currSpeed,
|
|
187
|
-
set: (newSpeed) => {
|
|
188
|
-
currSpeed = newSpeed;
|
|
189
|
-
this.start();
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Function to filter which vehicles to display.
|
|
195
|
-
*/
|
|
196
|
-
filter: {
|
|
197
|
-
value: filter,
|
|
198
|
-
writable: true,
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Function to sort the vehicles to display.
|
|
203
|
-
*/
|
|
204
|
-
sort: {
|
|
205
|
-
value: sort,
|
|
206
|
-
writable: true,
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* The tracker that renders the trajectories.
|
|
211
|
-
*/
|
|
212
|
-
tracker: { value: null, writable: true },
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Canvas cache object for trajectories drawn.
|
|
216
|
-
*/
|
|
217
|
-
styleCache: { value: {} },
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* If true. The layer will always use Date.now() on the next tick to render the trajectories.
|
|
221
|
-
* When true, setting the time property has no effect.
|
|
222
|
-
*/
|
|
223
|
-
live: {
|
|
224
|
-
value: live === false ? live : true,
|
|
225
|
-
writable: true,
|
|
226
|
-
},
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Time used to display the trajectories. Can be a Date or a number in ms representing a Date.
|
|
230
|
-
* If live property is true. The setter does nothing.
|
|
231
|
-
*/
|
|
232
|
-
time: {
|
|
233
|
-
get: () => currTime,
|
|
234
|
-
set: (newTime) => {
|
|
235
|
-
currTime = newTime && newTime.getTime ? newTime : new Date(newTime);
|
|
236
|
-
this.renderTrajectories();
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Keep track of which trajectories are stored.
|
|
242
|
-
*/
|
|
243
|
-
trajectories: {
|
|
244
|
-
value: {},
|
|
245
|
-
writable: true,
|
|
246
|
-
},
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Keep track of which trajectories are currently drawn.
|
|
250
|
-
*/
|
|
251
|
-
renderedTrajectories: {
|
|
252
|
-
get: () => (this.tracker && this.tracker.renderedTrajectories) || [],
|
|
253
|
-
},
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Id of the hovered vehicle.
|
|
257
|
-
*/
|
|
258
|
-
hoverVehicleId: {
|
|
259
|
-
value: hoverVehicleId,
|
|
260
|
-
writable: true,
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Id of the selected vehicle.
|
|
265
|
-
*/
|
|
266
|
-
selectedVehicleId: {
|
|
267
|
-
value: selectedVehicleId,
|
|
268
|
-
writable: true,
|
|
269
|
-
},
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Id of the selected vehicle.
|
|
273
|
-
*/
|
|
274
|
-
pixelRatio: {
|
|
275
|
-
value: pixelRatio || window.devicePixelRatio || 1,
|
|
276
|
-
writable: true,
|
|
277
|
-
},
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Options used by the constructor of the Tracker class.
|
|
281
|
-
*/
|
|
282
|
-
initTrackerOptions: {
|
|
283
|
-
value: initTrackerOptions,
|
|
284
|
-
writable: false,
|
|
285
|
-
},
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* If true, encapsulates the renderTrajectories calls in a requestAnimationFrame.
|
|
289
|
-
*/
|
|
290
|
-
useRequestAnimationFrame: {
|
|
291
|
-
value: options.useRequestAnimationFrame || false,
|
|
292
|
-
writable: true,
|
|
293
|
-
},
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* If true, encapsulates the renderTrajectories calls in a throttle function. Default to true.
|
|
297
|
-
*/
|
|
298
|
-
useThrottle: {
|
|
299
|
-
value: options.useThrottle || true,
|
|
300
|
-
writable: true,
|
|
301
|
-
},
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* If true, encapsulates the renderTrajectories calls in a debounce function.
|
|
305
|
-
*/
|
|
306
|
-
useDebounce: {
|
|
307
|
-
value: options.useDebounce || false,
|
|
308
|
-
writable: true,
|
|
309
|
-
},
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Filter properties used in combination with permalink parameters.
|
|
313
|
-
*/
|
|
314
|
-
publishedLineName: {
|
|
315
|
-
get: () => publishedLineName,
|
|
316
|
-
set: (newPublishedLineName) => {
|
|
317
|
-
publishedLineName = newPublishedLineName;
|
|
318
|
-
this.updateFilters();
|
|
319
|
-
},
|
|
320
|
-
},
|
|
321
|
-
tripNumber: {
|
|
322
|
-
get: () => tripNumber,
|
|
323
|
-
set: (newTripNumber) => {
|
|
324
|
-
tripNumber = newTripNumber;
|
|
325
|
-
this.updateFilters();
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
operator: {
|
|
329
|
-
get: () => operator,
|
|
330
|
-
set: (newOperator) => {
|
|
331
|
-
operator = newOperator;
|
|
332
|
-
this.updateFilters();
|
|
333
|
-
},
|
|
334
|
-
},
|
|
335
|
-
regexPublishedLineName: {
|
|
336
|
-
get: () => regexPublishedLineName,
|
|
337
|
-
set: (newRegex) => {
|
|
338
|
-
regexPublishedLineName = newRegex;
|
|
339
|
-
this.updateFilters();
|
|
340
|
-
},
|
|
341
|
-
},
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Style properties.
|
|
345
|
-
*/
|
|
346
|
-
delayDisplay: {
|
|
347
|
-
value: options.delayDisplay || 300000,
|
|
348
|
-
writable: true,
|
|
349
|
-
},
|
|
350
|
-
delayOutlineColor: {
|
|
351
|
-
value: options.delayOutlineColor || '#000000',
|
|
352
|
-
writable: true,
|
|
353
|
-
},
|
|
354
|
-
useDelayStyle: {
|
|
355
|
-
value: options.useDelayStyle || false,
|
|
356
|
-
writable: true,
|
|
357
|
-
},
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Debug properties.
|
|
361
|
-
*/
|
|
362
|
-
// Not used anymore, but could be useful for debugging.
|
|
363
|
-
// showVehicleTraj: {
|
|
364
|
-
// value:
|
|
365
|
-
// options.showVehicleTraj !== undefined
|
|
366
|
-
// ? options.showVehicleTraj
|
|
367
|
-
// : true,
|
|
368
|
-
// writable: true,
|
|
369
|
-
// },
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
// When we use the delay style we want to display delayed train on top by default
|
|
373
|
-
if (this.useDelayStyle && !this.sort) {
|
|
374
|
-
this.sort = (traj1, traj2) => {
|
|
375
|
-
const props1 = traj1.properties;
|
|
376
|
-
const props2 = traj2.properties;
|
|
377
|
-
|
|
378
|
-
if (props1.delay === null && props2.delay !== null) {
|
|
379
|
-
return 1;
|
|
380
|
-
}
|
|
381
|
-
if (props2.delay === null && props1.delay !== null) {
|
|
382
|
-
return -1;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// We put cancelled train inbetween green and yellow trains
|
|
386
|
-
// >=180000ms corresponds to yellow train
|
|
387
|
-
if (props1.cancelled && !props2.cancelled) {
|
|
388
|
-
return props2.delay < 180000 ? -1 : 1;
|
|
389
|
-
}
|
|
390
|
-
if (props2.cancelled && !props1.cancelled) {
|
|
391
|
-
return props1.delay < 180000 ? 1 : -1;
|
|
392
|
-
}
|
|
393
|
-
return props2.delay - props1.delay;
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// Update filter function based on convenient properties
|
|
398
|
-
this.updateFilters();
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
* Initalize the Tracker.
|
|
403
|
-
* @param {ol/Map~Map} map
|
|
404
|
-
* @param {Object} options
|
|
405
|
-
* @param {number} [options.width] Canvas's width.
|
|
406
|
-
* @param {number} [options.height] Canvas's height.
|
|
407
|
-
* @param {bool} [options.interpolate] Convert an EPSG:3857 coordinate to a canvas pixel (origin top-left).
|
|
408
|
-
* @param {string} [options.hoverVehicleId] Id of the trajectory which is hovered.
|
|
409
|
-
* @param {string} [options.selectedVehicleId] Id of the trajectory which is selected.
|
|
410
|
-
* @param {function} [options.filter] Function use to filter the features displayed.
|
|
411
|
-
* @param {function} [options.sort] Function use to sort the features displayed.
|
|
412
|
-
* @param {function} [options.style] Function use to style the features displayed.
|
|
413
|
-
*/
|
|
414
|
-
init(map, options = {}) {
|
|
415
|
-
super.init(map);
|
|
416
|
-
|
|
417
|
-
this.tracker = new Tracker({
|
|
418
|
-
style: (...args) => this.style(...args),
|
|
419
|
-
...this.initTrackerOptions,
|
|
420
|
-
...options,
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
if (this.visible) {
|
|
424
|
-
this.start();
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
this.visibilityRef = this.on('change:visible', (evt) => {
|
|
428
|
-
if (evt.target.visible) {
|
|
429
|
-
this.start();
|
|
430
|
-
} else {
|
|
431
|
-
this.stop();
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Destroy the Tracker.
|
|
438
|
-
*/
|
|
439
|
-
terminate() {
|
|
440
|
-
this.stop();
|
|
441
|
-
unByKey(this.visibilityRef);
|
|
442
|
-
if (this.tracker) {
|
|
443
|
-
const { canvas } = this.tracker;
|
|
444
|
-
const context = canvas.getContext('2d');
|
|
445
|
-
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
446
|
-
this.tracker = null;
|
|
447
|
-
}
|
|
448
|
-
super.terminate();
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* Start the trajectories rendering.
|
|
453
|
-
*
|
|
454
|
-
* @param {Array<Number>} size Map's size: [width, height].
|
|
455
|
-
* @param {number} zoom Map's zoom level.
|
|
456
|
-
* @param {number} resolution Map's resolution.
|
|
457
|
-
* @param {number} rotation Map's rotation.
|
|
458
|
-
*/
|
|
459
|
-
start() {
|
|
460
|
-
this.stop();
|
|
461
|
-
this.renderTrajectories();
|
|
462
|
-
this.startUpdateTime();
|
|
463
|
-
|
|
464
|
-
if (this.isClickActive) {
|
|
465
|
-
this.onClick(this.onFeatureClick);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
if (this.isHoverActive) {
|
|
469
|
-
this.onHover(this.onFeatureHover);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Start the clock.
|
|
475
|
-
* @private
|
|
476
|
-
*/
|
|
477
|
-
startUpdateTime() {
|
|
478
|
-
this.stopUpdateTime();
|
|
479
|
-
this.updateTimeDelay = this.getRefreshTimeInMs();
|
|
480
|
-
this.updateTimeInterval = setInterval(() => {
|
|
481
|
-
// When live=true, we update the time with new Date();
|
|
482
|
-
this.time = this.live
|
|
483
|
-
? new Date()
|
|
484
|
-
: this.time.getTime() + this.updateTimeDelay * this.speed;
|
|
485
|
-
}, this.updateTimeDelay);
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Stop the trajectories rendering.
|
|
490
|
-
*/
|
|
491
|
-
stop() {
|
|
492
|
-
this.stopUpdateTime();
|
|
493
|
-
if (this.tracker) {
|
|
494
|
-
const { canvas } = this.tracker;
|
|
495
|
-
const context = canvas.getContext('2d');
|
|
496
|
-
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* Stop the clock.
|
|
502
|
-
* @private
|
|
503
|
-
*/
|
|
504
|
-
stopUpdateTime() {
|
|
505
|
-
if (this.updateTimeInterval) {
|
|
506
|
-
clearInterval(this.updateTimeInterval);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* Launch renderTrajectories. it avoids duplicating code in renderTrajectories method.
|
|
512
|
-
*
|
|
513
|
-
* @param {object} viewState The view state of the map.
|
|
514
|
-
* @param {number[2]} viewState.center Center coordinate of the map in mercator coordinate.
|
|
515
|
-
* @param {number[4]} viewState.extent Extent of the map in mercator coordinates.
|
|
516
|
-
* @param {number[2]} viewState.size Size ([width, height]) of the canvas to render.
|
|
517
|
-
* @param {number} [viewState.rotation = 0] Rotation of the map to render.
|
|
518
|
-
* @param {number} viewState.resolution Resolution of the map to render.
|
|
519
|
-
* @param {boolean} noInterpolate If true trajectories are not interpolated but
|
|
520
|
-
* drawn at the last known coordinate. Use this for performance optimization
|
|
521
|
-
* during map navigation.
|
|
522
|
-
* @private
|
|
523
|
-
*/
|
|
524
|
-
renderTrajectoriesInternal(viewState, noInterpolate) {
|
|
525
|
-
if (!this.tracker) {
|
|
526
|
-
return false;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
const time = this.live ? Date.now() : this.time;
|
|
530
|
-
|
|
531
|
-
const trajectories = Object.values(this.trajectories);
|
|
532
|
-
|
|
533
|
-
// console.time('sort');
|
|
534
|
-
if (this.sort) {
|
|
535
|
-
trajectories.sort(this.sort);
|
|
536
|
-
}
|
|
537
|
-
// console.timeEnd('sort');
|
|
538
|
-
|
|
539
|
-
// console.time('render');
|
|
540
|
-
this.renderState = this.tracker.renderTrajectories(
|
|
541
|
-
trajectories,
|
|
542
|
-
{ ...viewState, pixelRatio: this.pixelRatio, time },
|
|
543
|
-
{
|
|
544
|
-
noInterpolate:
|
|
545
|
-
viewState.zoom < this.minZoomInterpolation ? true : noInterpolate,
|
|
546
|
-
hoverVehicleId: this.hoverVehicleId,
|
|
547
|
-
selectedVehicleId: this.selectedVehicleId,
|
|
548
|
-
iconScale: this.iconScale,
|
|
549
|
-
delayDisplay: this.delayDisplay,
|
|
550
|
-
delayOutlineColor: this.delayOutlineColor,
|
|
551
|
-
useDelayStyle: this.useDelayStyle,
|
|
552
|
-
},
|
|
553
|
-
);
|
|
554
|
-
|
|
555
|
-
// console.timeEnd('render');
|
|
556
|
-
return true;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* Render the trajectories requesting an animation frame and cancelling the previous one.
|
|
561
|
-
* This function must be overrided by children to provide the correct parameters.
|
|
562
|
-
*
|
|
563
|
-
* @param {object} viewState The view state of the map.
|
|
564
|
-
* @param {number[2]} viewState.center Center coordinate of the map in mercator coordinate.
|
|
565
|
-
* @param {number[4]} viewState.extent Extent of the map in mercator coordinates.
|
|
566
|
-
* @param {number[2]} viewState.size Size ([width, height]) of the canvas to render.
|
|
567
|
-
* @param {number} [viewState.rotation = 0] Rotation of the map to render.
|
|
568
|
-
* @param {number} viewState.resolution Resolution of the map to render.
|
|
569
|
-
* @param {boolean} noInterpolate If true trajectories are not interpolated but
|
|
570
|
-
* drawn at the last known coordinate. Use this for performance optimization
|
|
571
|
-
* during map navigation.
|
|
572
|
-
* @private
|
|
573
|
-
*/
|
|
574
|
-
renderTrajectories(viewState, noInterpolate) {
|
|
575
|
-
if (this.requestId) {
|
|
576
|
-
cancelAnimationFrame(this.requestId);
|
|
577
|
-
this.requestId = null;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
if (!noInterpolate && this.useRequestAnimationFrame) {
|
|
581
|
-
this.requestId = requestAnimationFrame(() => {
|
|
582
|
-
this.renderTrajectoriesInternal(viewState, noInterpolate);
|
|
583
|
-
});
|
|
584
|
-
} else if (!noInterpolate && this.useDebounce) {
|
|
585
|
-
this.debounceRenderTrajectories(viewState, noInterpolate);
|
|
586
|
-
} else if (!noInterpolate && this.useThrottle) {
|
|
587
|
-
this.throttleRenderTrajectories(viewState, noInterpolate);
|
|
588
|
-
} else {
|
|
589
|
-
this.renderTrajectoriesInternal(viewState, noInterpolate);
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
/**
|
|
594
|
-
* Get vehicle.
|
|
595
|
-
* @param {function} filterFc A function use to filter results.
|
|
596
|
-
* @return {Array<Object>} Array of vehicle.
|
|
597
|
-
*/
|
|
598
|
-
getVehicle(filterFc) {
|
|
599
|
-
return Object.values(this.trajectories).filter(filterFc);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* Returns an array of vehicles located at the given coordinates and resolution.
|
|
604
|
-
*
|
|
605
|
-
* @param {number[2]} coordinate A coordinate ([x,y]).
|
|
606
|
-
* @param {number} [resolution=1] The resolution of the map.
|
|
607
|
-
* @param {number} [nb=Infinity] The max number of vehicles to return.
|
|
608
|
-
* @return {Array<ol/Feature~Feature>} Array of vehicle.
|
|
609
|
-
*/
|
|
610
|
-
getVehiclesAtCoordinate(coordinate, resolution = 1, nb = Infinity) {
|
|
611
|
-
const ext = buffer(
|
|
612
|
-
[...coordinate, ...coordinate],
|
|
613
|
-
this.hitTolerance * resolution,
|
|
614
|
-
);
|
|
615
|
-
const trajectories = Object.values(this.trajectories);
|
|
616
|
-
const vehicles = [];
|
|
617
|
-
for (let i = 0; i < trajectories.length; i += 1) {
|
|
618
|
-
if (
|
|
619
|
-
trajectories[i].properties.coordinate &&
|
|
620
|
-
containsCoordinate(ext, trajectories[i].properties.coordinate)
|
|
621
|
-
) {
|
|
622
|
-
vehicles.push(trajectories[i]);
|
|
623
|
-
}
|
|
624
|
-
if (vehicles.length === nb) {
|
|
625
|
-
break;
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
return vehicles;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Request feature information for a given coordinate.
|
|
634
|
-
*
|
|
635
|
-
* @param {ol/coordinate~Coordinate} coordinate Coordinate.
|
|
636
|
-
* @param {Object} options Options See child classes to see which options are supported.
|
|
637
|
-
* @param {number} [options.resolution=1] The resolution of the map.
|
|
638
|
-
* @param {number} [options.nb=Infinity] The max number of vehicles to return.
|
|
639
|
-
* @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.
|
|
640
|
-
*/
|
|
641
|
-
getFeatureInfoAtCoordinate(coordinate, options = {}) {
|
|
642
|
-
const { resolution, nb } = options;
|
|
643
|
-
|
|
644
|
-
const vehicles = this.getVehiclesAtCoordinate(coordinate, resolution, nb);
|
|
645
|
-
|
|
646
|
-
return Promise.resolve({
|
|
647
|
-
layer: this,
|
|
648
|
-
features: vehicles.map((vehicle) => this.format.readFeature(vehicle)),
|
|
649
|
-
coordinate,
|
|
650
|
-
});
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
/**
|
|
654
|
-
* On zoomend we adjust the time interval of the update of vehicles positions.
|
|
655
|
-
*
|
|
656
|
-
* @param evt Event that triggered the function.
|
|
657
|
-
* @private
|
|
658
|
-
*/
|
|
659
|
-
// eslint-disable-next-line no-unused-vars
|
|
660
|
-
onZoomEnd(evt) {
|
|
661
|
-
this.startUpdateTime();
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
* Define beahvior when a vehicle is clicked
|
|
666
|
-
* To be defined in child classes.
|
|
667
|
-
*
|
|
668
|
-
* @private
|
|
669
|
-
* @override
|
|
670
|
-
*/
|
|
671
|
-
onFeatureClick() {}
|
|
672
|
-
|
|
673
|
-
/**
|
|
674
|
-
* Define behavior when a vehicle is hovered
|
|
675
|
-
* To be defined in child classes.
|
|
676
|
-
*
|
|
677
|
-
* @private
|
|
678
|
-
* @override
|
|
679
|
-
*/
|
|
680
|
-
onFeatureHover() {}
|
|
681
|
-
|
|
682
|
-
/**
|
|
683
|
-
* Get the duration before the next update depending on zoom level.
|
|
684
|
-
*
|
|
685
|
-
* @private
|
|
686
|
-
* @param {number} zoom
|
|
687
|
-
*/
|
|
688
|
-
getRefreshTimeInMs(zoom) {
|
|
689
|
-
const roundedZoom = Math.round(zoom);
|
|
690
|
-
const timeStep = timeSteps[roundedZoom] || 25;
|
|
691
|
-
const nextTick = Math.max(25, timeStep / this.speed);
|
|
692
|
-
const nextThrottleTick = Math.min(nextTick, 500);
|
|
693
|
-
// TODO: see if this should go elsewhere.
|
|
694
|
-
if (this.useThrottle) {
|
|
695
|
-
this.throttleRenderTrajectories = throttle(
|
|
696
|
-
this.renderTrajectoriesInternal,
|
|
697
|
-
nextThrottleTick,
|
|
698
|
-
{ leading: true, trailing: true },
|
|
699
|
-
);
|
|
700
|
-
} else if (this.useDebounce) {
|
|
701
|
-
this.debounceRenderTrajectories = debounce(
|
|
702
|
-
this.renderTrajectoriesInternal,
|
|
703
|
-
nextThrottleTick,
|
|
704
|
-
{ leading: true, trailing: true, maxWait: 5000 },
|
|
705
|
-
);
|
|
706
|
-
}
|
|
707
|
-
if (this.api?.buffer) {
|
|
708
|
-
const [, size] = this.api.buffer;
|
|
709
|
-
this.api.buffer = [nextThrottleTick, size];
|
|
710
|
-
}
|
|
711
|
-
return nextTick;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
/**
|
|
715
|
-
* Update filter provided by properties or permalink.
|
|
716
|
-
*/
|
|
717
|
-
updateFilters() {
|
|
718
|
-
// Setting filters from the permalink if no values defined by the layer.
|
|
719
|
-
const parameters = qs.parse(window.location.search.toLowerCase());
|
|
720
|
-
const publishedName = this.publishedLineName || parameters[LINE_FILTER];
|
|
721
|
-
const tripNumber = this.tripNumber || parameters[ROUTE_FILTER];
|
|
722
|
-
const operator = this.operator || parameters[OPERATOR_FILTER];
|
|
723
|
-
const { regexPublishedLineName } = this;
|
|
724
|
-
|
|
725
|
-
// Only overrides filter function if one of this property exists.
|
|
726
|
-
if (publishedName || tripNumber || operator || regexPublishedLineName) {
|
|
727
|
-
// filter is the property in TrackerLayerMixin.
|
|
728
|
-
this.filter = createFilters(
|
|
729
|
-
publishedName,
|
|
730
|
-
tripNumber,
|
|
731
|
-
operator,
|
|
732
|
-
regexPublishedLineName,
|
|
733
|
-
);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
/**
|
|
738
|
-
* @private
|
|
739
|
-
*/
|
|
740
|
-
defaultStyle(trajectory, viewState) {
|
|
741
|
-
return delayTrackerStyle(trajectory, viewState, this);
|
|
742
|
-
}
|
|
743
|
-
};
|
|
744
|
-
|
|
745
|
-
export default TrackerLayerMixin;
|