mobility-toolbox-js 2.0.0 → 2.0.1-beta.13
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/api/RoutingAPI.js +15 -0
- package/api/RoutingAPI.test.js +25 -0
- package/api/StopsAPI.js +12 -0
- package/api/StopsAPI.test.js +22 -0
- package/api/TralisAPI.js +359 -0
- package/api/TralisAPI.test.js +67 -0
- package/api/{tralis/TralisAPIUtils.js → TralisAPIUtils.js} +2 -32
- package/api/index.js +3 -3
- package/{ol/README.md → api/typedefs.js} +0 -0
- package/common/Tracker.js +14 -118
- package/common/api/HttpAPI.js +30 -0
- package/common/api/HttpAPI.test.js +50 -0
- package/common/api/WebSocketAPI.js +175 -0
- package/{api/tralis/WebSocketConnector.test.js → common/api/WebSocketAPI.test.js} +100 -145
- package/common/controls/Control.js +26 -91
- package/common/controls/Control.test.js +32 -43
- package/common/index.js +4 -0
- package/common/layers/Layer.js +53 -244
- package/common/layers/Layer.test.js +185 -244
- package/common/mixins/CopyrightMixin.js +20 -44
- package/common/mixins/SearchMixin.js +100 -166
- package/common/mixins/TralisLayerMixin.js +443 -894
- package/common/styles/index.js +4 -4
- package/common/styles/trackerDefaultStyle.js +39 -175
- package/common/styles/trackerDelayStyle.js +2 -11
- package/common/styles/trackerSimpleStyle.js +4 -8
- package/common/trackerConfig.js +61 -99
- package/common/trackerConfig.test.js +15 -17
- package/common/typedefs.js +0 -23
- package/common/utils/createTrackerFilters.js +10 -41
- package/common/utils/createTrackerFilters.test.js +40 -56
- package/common/utils/getMapboxMapCopyrights.js +3 -16
- package/common/utils/getMapboxMapCopyrights.test.js +32 -39
- package/common/utils/getMapboxStyleUrl.js +3 -13
- package/common/utils/getVehiclePosition.js +3 -33
- package/common/utils/index.js +5 -6
- package/common/utils/removeDuplicate.js +3 -17
- package/common/utils/removeDuplicate.test.js +17 -20
- package/common/utils/sortByDelay.js +2 -7
- package/common/utils/timeUtils.js +8 -32
- package/common/utils/timeUtils.test.js +7 -13
- package/index.js +8 -2
- package/mapbox/controls/CopyrightControl.js +9 -38
- package/mapbox/controls/index.js +1 -0
- package/mapbox/index.js +4 -3
- package/mapbox/layers/Layer.js +15 -76
- package/mapbox/layers/Layer.test.js +81 -101
- package/mapbox/layers/TralisLayer.js +46 -193
- package/mapbox/layers/TralisLayer.test.js +12 -14
- package/mapbox/layers/index.js +2 -0
- package/mapbox/utils.js +7 -21
- package/mbt.js +50444 -0
- package/mbt.js.map +7 -0
- package/mbt.min.js +1005 -0
- package/mbt.min.js.map +7 -0
- package/ol/controls/CopyrightControl.js +8 -46
- package/ol/controls/CopyrightControl.test.js +75 -121
- package/ol/controls/RoutingControl.js +167 -532
- package/ol/controls/RoutingControl.test.js +99 -164
- package/ol/controls/StopFinderControl.js +3 -31
- package/ol/controls/StopFinderControl.test.js +18 -29
- package/ol/controls/index.js +3 -0
- package/ol/index.js +5 -13
- package/ol/layers/Layer.js +23 -128
- package/ol/layers/Layer.test.js +79 -102
- package/ol/layers/MapboxLayer.js +62 -237
- package/ol/layers/MapboxLayer.test.js +58 -84
- package/ol/layers/MapboxStyleLayer.js +38 -268
- package/ol/layers/MapboxStyleLayer.test.js +97 -128
- package/ol/layers/MaplibreLayer.js +46 -187
- package/ol/layers/RoutingLayer.js +21 -51
- package/ol/layers/RoutingLayer.test.js +15 -24
- package/ol/layers/TralisLayer.js +102 -276
- package/ol/layers/TralisLayer.test.js +32 -50
- package/ol/layers/VectorLayer.js +3 -24
- package/ol/layers/VectorLayer.test.js +34 -45
- package/ol/layers/WMSLayer.js +15 -57
- package/ol/layers/WMSLayer.test.js +35 -43
- package/ol/layers/index.js +8 -0
- package/ol/styles/fullTrajectoryDelayStyle.js +11 -15
- package/ol/styles/fullTrajectoryStyle.js +17 -25
- package/ol/styles/index.js +2 -2
- package/package.json +35 -62
- package/api/routing/RoutingAPI.js +0 -44
- package/api/routing/RoutingAPI.test.js +0 -41
- package/api/stops/StopsAPI.js +0 -41
- package/api/stops/StopsAPI.test.js +0 -34
- package/api/tralis/TralisAPI.js +0 -731
- package/api/tralis/TralisAPI.test.js +0 -75
- package/api/tralis/WebSocketConnector.js +0 -338
- package/api/tralis/typedefs.js +0 -81
- package/common/api/api.js +0 -64
- package/common/api/api.test.js +0 -68
- package/index.js.map +0 -1
- package/module.js +0 -23
- package/ol/controls/snapshots/RoutingControlRouteGen10.json +0 -58
- package/ol/controls/snapshots/RoutingControlRouteGen100.json +0 -292
- package/ol/controls/snapshots/RoutingControlRouteGen30.json +0 -69
- package/ol/controls/snapshots/RoutingControlRouteGen5.json +0 -58
- package/ol/controls/snapshots/RoutingControlRouteOSM.json +0 -759
- package/ol/controls/snapshots/RoutingControlStation1.json +0 -60
- package/ol/controls/snapshots/RoutingControlStation2.json +0 -49
package/ol/layers/TralisLayer.js
CHANGED
|
@@ -1,290 +1,151 @@
|
|
|
1
|
-
import GeoJSON from
|
|
2
|
-
import { Layer as OLLayer, Group, Vector as VectorLayer } from
|
|
3
|
-
import Source from
|
|
4
|
-
import { composeCssTransform } from
|
|
5
|
-
import { Vector as VectorSource } from
|
|
6
|
-
import Layer from
|
|
7
|
-
import mixin from
|
|
8
|
-
import { fullTrajectoryStyle } from
|
|
9
|
-
|
|
1
|
+
import GeoJSON from "ol/format/GeoJSON";
|
|
2
|
+
import { Layer as OLLayer, Group, Vector as VectorLayer } from "ol/layer";
|
|
3
|
+
import Source from "ol/source/Source";
|
|
4
|
+
import { composeCssTransform } from "ol/transform";
|
|
5
|
+
import { Vector as VectorSource } from "ol/source";
|
|
6
|
+
import Layer from "./Layer";
|
|
7
|
+
import mixin from "../../common/mixins/TralisLayerMixin";
|
|
8
|
+
import { fullTrajectoryStyle } from "../styles";
|
|
10
9
|
const format = new GeoJSON();
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Responsible for loading and display data from a Tralis service.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* import { TralisLayer } from 'mobility-toolbox-js/ol';
|
|
17
|
-
*
|
|
18
|
-
* const layer = new TralisLayer({
|
|
19
|
-
* url: [yourUrl],
|
|
20
|
-
* apiKey: [yourApiKey],
|
|
21
|
-
* });
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* @see <a href="/api/class/src/api/tralis/TralisAPI%20js~TralisAPI%20html">TralisAPI</a>
|
|
25
|
-
*
|
|
26
|
-
* @extends {Layer}
|
|
27
|
-
* @implements {TralisLayerInterface}
|
|
28
|
-
*/
|
|
29
10
|
class TralisLayer extends mixin(Layer) {
|
|
30
|
-
/**
|
|
31
|
-
* Constructor.
|
|
32
|
-
*
|
|
33
|
-
* @param {Object} options
|
|
34
|
-
* @private
|
|
35
|
-
*/
|
|
36
11
|
constructor(options = {}) {
|
|
37
|
-
// We use a group to be able to add custom vector layer in extended class.
|
|
38
|
-
// For example TrajservLayer use a vectorLayer to display the complete trajectory.
|
|
39
12
|
super({
|
|
40
|
-
...options
|
|
13
|
+
...options
|
|
41
14
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// Avoid having really big points when zooming fast.
|
|
86
|
-
const { canvas } = this.tracker;
|
|
87
|
-
const context = canvas.getContext('2d');
|
|
88
|
-
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
89
|
-
} else {
|
|
90
|
-
const pixelCenterRendered =
|
|
91
|
-
this.map.getPixelFromCoordinate(renderedCenter);
|
|
92
|
-
const pixelCenter = this.map.getPixelFromCoordinate(center);
|
|
93
|
-
this.transformContainer.style.transform = composeCssTransform(
|
|
94
|
-
pixelCenterRendered[0] - pixelCenter[0],
|
|
95
|
-
pixelCenterRendered[1] - pixelCenter[1],
|
|
96
|
-
renderedResolution / resolution,
|
|
97
|
-
renderedResolution / resolution,
|
|
98
|
-
rotation - renderedRotation,
|
|
99
|
-
0,
|
|
100
|
-
0,
|
|
101
|
-
);
|
|
102
|
-
}
|
|
15
|
+
this.olLayer = options.olLayer || new Group({
|
|
16
|
+
layers: [
|
|
17
|
+
new VectorLayer({
|
|
18
|
+
source: new VectorSource({ features: [] }),
|
|
19
|
+
style: options.fullTrajectoryStyle || fullTrajectoryStyle
|
|
20
|
+
}),
|
|
21
|
+
new OLLayer({
|
|
22
|
+
source: new Source({}),
|
|
23
|
+
render: (frameState) => {
|
|
24
|
+
if (!this.tracker || !this.tracker.canvas) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
if (!this.container) {
|
|
28
|
+
this.container = document.createElement("div");
|
|
29
|
+
this.container.style.position = "absolute";
|
|
30
|
+
this.container.style.width = "100%";
|
|
31
|
+
this.container.style.height = "100%";
|
|
32
|
+
this.transformContainer = document.createElement("div");
|
|
33
|
+
this.transformContainer.style.position = "absolute";
|
|
34
|
+
this.transformContainer.style.width = "100%";
|
|
35
|
+
this.transformContainer.style.height = "100%";
|
|
36
|
+
this.container.appendChild(this.transformContainer);
|
|
37
|
+
this.tracker.canvas.style.position = "absolute";
|
|
38
|
+
this.tracker.canvas.style.top = "0";
|
|
39
|
+
this.tracker.canvas.style.left = "0";
|
|
40
|
+
this.tracker.canvas.style.transformOrigin = "top left";
|
|
41
|
+
this.transformContainer.appendChild(this.tracker.canvas);
|
|
42
|
+
}
|
|
43
|
+
if (this.renderedViewState) {
|
|
44
|
+
const { center, resolution, rotation } = frameState.viewState;
|
|
45
|
+
const {
|
|
46
|
+
center: renderedCenter,
|
|
47
|
+
resolution: renderedResolution,
|
|
48
|
+
rotation: renderedRotation
|
|
49
|
+
} = this.renderedViewState;
|
|
50
|
+
if (renderedResolution / resolution >= 3) {
|
|
51
|
+
const { canvas } = this.tracker;
|
|
52
|
+
const context = canvas.getContext("2d");
|
|
53
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
54
|
+
} else {
|
|
55
|
+
const pixelCenterRendered = this.map.getPixelFromCoordinate(renderedCenter);
|
|
56
|
+
const pixelCenter = this.map.getPixelFromCoordinate(center);
|
|
57
|
+
this.transformContainer.style.transform = composeCssTransform(pixelCenterRendered[0] - pixelCenter[0], pixelCenterRendered[1] - pixelCenter[1], renderedResolution / resolution, renderedResolution / resolution, rotation - renderedRotation, 0, 0);
|
|
103
58
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
// We store the layer used to highlight the full Trajectory
|
|
59
|
+
}
|
|
60
|
+
return this.container;
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
]
|
|
64
|
+
});
|
|
111
65
|
this.vectorLayer = this.olLayer.getLayers().item(0);
|
|
112
|
-
|
|
113
|
-
// Options the last render run did happen. If something changes
|
|
114
|
-
// we have to render again
|
|
115
|
-
/** @ignore */
|
|
116
66
|
this.renderState = {
|
|
117
67
|
center: [0, 0],
|
|
118
68
|
zoom: null,
|
|
119
|
-
rotation: 0
|
|
69
|
+
rotation: 0
|
|
120
70
|
};
|
|
121
71
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
super.init(map);
|
|
72
|
+
attachToMap(map) {
|
|
73
|
+
super.attachToMap(map);
|
|
125
74
|
if (this.map) {
|
|
126
|
-
this.olListenersKeys.push(
|
|
127
|
-
this.map.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this.currentZoom = zoom;
|
|
139
|
-
|
|
140
|
-
this.onMoveEnd(evt);
|
|
141
|
-
}),
|
|
142
|
-
);
|
|
75
|
+
this.olListenersKeys.push(this.map.on(["moveend", "change:target"], (evt) => {
|
|
76
|
+
const view = this.map.getView();
|
|
77
|
+
if (view.getAnimating() || view.getInteracting()) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const zoom = view.getZoom();
|
|
81
|
+
if (this.currentZoom !== zoom) {
|
|
82
|
+
this.onZoomEnd(evt);
|
|
83
|
+
}
|
|
84
|
+
this.currentZoom = zoom;
|
|
85
|
+
this.onMoveEnd(evt);
|
|
86
|
+
}));
|
|
143
87
|
}
|
|
144
88
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* Destroy the container of the tracker.
|
|
148
|
-
*/
|
|
149
|
-
terminate() {
|
|
150
|
-
super.terminate();
|
|
89
|
+
detachFromMap() {
|
|
90
|
+
super.detachFromMap();
|
|
151
91
|
this.container = null;
|
|
152
92
|
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Detect in the canvas if there is data to query at a specific coordinate.
|
|
156
|
-
* @param {ol/coordinate~Coordinate} coordinate The coordinate to test
|
|
157
|
-
* @returns
|
|
158
|
-
*/
|
|
159
93
|
hasFeatureInfoAtCoordinate(coordinate) {
|
|
160
94
|
if (this.map && this.tracker && this.tracker.canvas) {
|
|
161
|
-
const context = this.tracker.canvas.getContext(
|
|
95
|
+
const context = this.tracker.canvas.getContext("2d");
|
|
162
96
|
const pixel = this.map.getPixelFromCoordinate(coordinate);
|
|
163
|
-
return !!context.getImageData(
|
|
164
|
-
pixel[0] * this.pixelRatio,
|
|
165
|
-
pixel[1] * this.pixelRatio,
|
|
166
|
-
1,
|
|
167
|
-
1,
|
|
168
|
-
).data[3];
|
|
97
|
+
return !!context.getImageData(pixel[0] * this.pixelRatio, pixel[1] * this.pixelRatio, 1, 1).data[3];
|
|
169
98
|
}
|
|
170
99
|
return false;
|
|
171
100
|
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Render the trajectories using current map's size, resolution and rotation.
|
|
175
|
-
* @param {boolean} noInterpolate if true, renders the vehicles without interpolating theirs positions.
|
|
176
|
-
* @overrides
|
|
177
|
-
*/
|
|
178
101
|
renderTrajectories(noInterpolate) {
|
|
179
102
|
const view = this.map.getView();
|
|
180
|
-
super.renderTrajectories(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
},
|
|
190
|
-
noInterpolate,
|
|
191
|
-
);
|
|
103
|
+
super.renderTrajectories({
|
|
104
|
+
size: this.map.getSize(),
|
|
105
|
+
center: this.map.getView().getCenter(),
|
|
106
|
+
extent: view.calculateExtent(),
|
|
107
|
+
resolution: view.getResolution(),
|
|
108
|
+
rotation: view.getRotation(),
|
|
109
|
+
zoom: view.getZoom(),
|
|
110
|
+
pixelRatio: this.pixelRatio
|
|
111
|
+
}, noInterpolate);
|
|
192
112
|
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Launch renderTrajectories. it avoids duplicating code in renderTrajectories methhod.
|
|
196
|
-
* @private
|
|
197
|
-
* @override
|
|
198
|
-
*/
|
|
199
113
|
renderTrajectoriesInternal(viewState, noInterpolate) {
|
|
200
114
|
let isRendered = false;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this.map.getView().getAnimating() || this.map.getView().getInteracting();
|
|
204
|
-
|
|
205
|
-
// Don't render the map when the map is animating or interacting.
|
|
206
|
-
isRendered = blockRendering
|
|
207
|
-
? false
|
|
208
|
-
: super.renderTrajectoriesInternal(viewState, noInterpolate);
|
|
209
|
-
|
|
210
|
-
// We update the current render state.
|
|
115
|
+
const blockRendering = this.map.getView().getAnimating() || this.map.getView().getInteracting();
|
|
116
|
+
isRendered = blockRendering ? false : super.renderTrajectoriesInternal(viewState, noInterpolate);
|
|
211
117
|
if (isRendered) {
|
|
212
118
|
this.renderedViewState = { ...viewState };
|
|
213
|
-
|
|
214
119
|
if (this.transformContainer) {
|
|
215
|
-
this.transformContainer.style.transform =
|
|
120
|
+
this.transformContainer.style.transform = "";
|
|
216
121
|
}
|
|
217
122
|
}
|
|
218
123
|
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Return the delay in ms before the next rendering.
|
|
222
|
-
*/
|
|
223
124
|
getRefreshTimeInMs() {
|
|
224
125
|
return super.getRefreshTimeInMs(this.map.getView().getZoom());
|
|
225
126
|
}
|
|
226
|
-
|
|
227
127
|
getFeatureInfoAtCoordinate(coordinate, options = {}) {
|
|
228
128
|
const resolution = this.map.getView().getResolution();
|
|
229
129
|
return super.getFeatureInfoAtCoordinate(coordinate, {
|
|
230
130
|
resolution,
|
|
231
|
-
...options
|
|
131
|
+
...options
|
|
232
132
|
});
|
|
233
133
|
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* On move end we update the websocket with the new bbox.
|
|
237
|
-
*
|
|
238
|
-
* @param {ol/MapEvent~MapEvent} evt Moveend event
|
|
239
|
-
* @private
|
|
240
|
-
* @override
|
|
241
|
-
*/
|
|
242
134
|
onMoveEnd() {
|
|
243
135
|
if (this.visible && this.isUpdateBboxOnMoveEnd) {
|
|
244
136
|
this.setBbox();
|
|
245
137
|
}
|
|
246
|
-
|
|
247
|
-
if (
|
|
248
|
-
this.visible &&
|
|
249
|
-
this.isUpdateBboxOnMoveEnd &&
|
|
250
|
-
this.isClickActive &&
|
|
251
|
-
this.selectedVehicleId
|
|
252
|
-
) {
|
|
138
|
+
if (this.visible && this.isUpdateBboxOnMoveEnd && this.isClickActive && this.selectedVehicleId) {
|
|
253
139
|
this.highlightTrajectory(this.selectedVehicleId);
|
|
254
140
|
}
|
|
255
141
|
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Function called on moveend event only when the zoom has changed.
|
|
259
|
-
*
|
|
260
|
-
* @param {ol/MapEvent~MapEvent} evt Moveend event.
|
|
261
|
-
* @private
|
|
262
|
-
* @override
|
|
263
|
-
*/
|
|
264
|
-
// eslint-disable-next-line no-unused-vars
|
|
265
142
|
onZoomEnd(evt) {
|
|
266
143
|
super.onZoomEnd(evt);
|
|
267
144
|
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Update the cursor style when hovering a vehicle.
|
|
271
|
-
*
|
|
272
|
-
* @private
|
|
273
|
-
* @override
|
|
274
|
-
*/
|
|
275
145
|
onFeatureHover(features, layer, coordinate) {
|
|
276
146
|
super.onFeatureHover(features, layer, coordinate);
|
|
277
|
-
this.map.getTargetElement().style.cursor = features.length
|
|
278
|
-
? 'pointer'
|
|
279
|
-
: 'auto';
|
|
147
|
+
this.map.getTargetElement().style.cursor = features.length ? "pointer" : "auto";
|
|
280
148
|
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Display the complete trajectory of the vehicle.
|
|
284
|
-
*
|
|
285
|
-
* @private
|
|
286
|
-
* @override
|
|
287
|
-
*/
|
|
288
149
|
onFeatureClick(features, layer, coordinate) {
|
|
289
150
|
super.onFeatureClick(features, layer, coordinate);
|
|
290
151
|
if (!features.length && this.vectorLayer) {
|
|
@@ -294,25 +155,9 @@ class TralisLayer extends mixin(Layer) {
|
|
|
294
155
|
this.highlightTrajectory(this.selectedVehicleId);
|
|
295
156
|
}
|
|
296
157
|
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Remove the trajectory form the list if necessary.
|
|
300
|
-
*
|
|
301
|
-
* @private
|
|
302
|
-
*/
|
|
303
158
|
purgeTrajectory(trajectory, extent, zoom) {
|
|
304
|
-
return super.purgeTrajectory(
|
|
305
|
-
trajectory,
|
|
306
|
-
extent || this.map.getView().calculateExtent(),
|
|
307
|
-
zoom || this.map.getView().getZoom(),
|
|
308
|
-
);
|
|
159
|
+
return super.purgeTrajectory(trajectory, extent || this.map.getView().calculateExtent(), zoom || this.map.getView().getZoom());
|
|
309
160
|
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Send the current bbox to the websocket
|
|
313
|
-
*
|
|
314
|
-
* @private
|
|
315
|
-
*/
|
|
316
161
|
setBbox(extent, zoom) {
|
|
317
162
|
let newExtent = extent;
|
|
318
163
|
let newZoom = zoom;
|
|
@@ -322,38 +167,19 @@ class TralisLayer extends mixin(Layer) {
|
|
|
322
167
|
}
|
|
323
168
|
super.setBbox(newExtent, newZoom);
|
|
324
169
|
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Highlight the trajectory of journey.
|
|
328
|
-
* @private
|
|
329
|
-
*/
|
|
330
170
|
highlightTrajectory(id) {
|
|
331
|
-
this.api
|
|
332
|
-
|
|
333
|
-
.
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
!fullTrajectory.features.length
|
|
341
|
-
) {
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
const features = format.readFeatures(fullTrajectory);
|
|
345
|
-
this.vectorLayer.getSource().addFeatures(features);
|
|
346
|
-
});
|
|
171
|
+
this.api.getFullTrajectory(id, this.mode, this.generalizationLevel).then((fullTrajectory) => {
|
|
172
|
+
const vectorSource = this.vectorLayer.getSource();
|
|
173
|
+
vectorSource.clear();
|
|
174
|
+
if (!fullTrajectory || !fullTrajectory.features || !fullTrajectory.features.length) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const features = format.readFeatures(fullTrajectory);
|
|
178
|
+
this.vectorLayer.getSource().addFeatures(features);
|
|
179
|
+
});
|
|
347
180
|
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Create a copy of the TralisLayer.
|
|
351
|
-
* @param {Object} newOptions Options to override
|
|
352
|
-
* @return {TralisLayer} A TralisLayer
|
|
353
|
-
*/
|
|
354
181
|
clone(newOptions) {
|
|
355
182
|
return new TralisLayer({ ...this.options, ...newOptions });
|
|
356
183
|
}
|
|
357
184
|
}
|
|
358
|
-
|
|
359
185
|
export default TralisLayer;
|
|
@@ -1,95 +1,77 @@
|
|
|
1
|
-
import fetch from
|
|
2
|
-
import Map from
|
|
3
|
-
import View from
|
|
4
|
-
import WS from
|
|
5
|
-
import TralisLayer from
|
|
6
|
-
|
|
7
|
-
// create a WS instance, listening on port 1234 on localhost
|
|
1
|
+
import fetch from "jest-fetch-mock";
|
|
2
|
+
import Map from "ol/Map";
|
|
3
|
+
import View from "ol/View";
|
|
4
|
+
import WS from "jest-websocket-mock";
|
|
5
|
+
import TralisLayer from "./TralisLayer";
|
|
8
6
|
let layer;
|
|
9
7
|
let onClick;
|
|
10
8
|
let olMap;
|
|
11
9
|
let server;
|
|
12
|
-
|
|
13
|
-
describe('TralisLayer', () => {
|
|
10
|
+
describe("TralisLayer", () => {
|
|
14
11
|
beforeEach(() => {
|
|
15
|
-
server = new WS(
|
|
12
|
+
server = new WS("ws://localhost:1234");
|
|
16
13
|
global.fetch = fetch;
|
|
17
14
|
fetch.resetMocks();
|
|
18
|
-
|
|
19
15
|
onClick = jest.fn();
|
|
20
16
|
layer = new TralisLayer({
|
|
21
|
-
url:
|
|
22
|
-
apiKey:
|
|
23
|
-
onClick
|
|
17
|
+
url: "ws://localhost:1234",
|
|
18
|
+
apiKey: "apiKey",
|
|
19
|
+
onClick
|
|
24
20
|
});
|
|
25
|
-
|
|
26
21
|
olMap = new Map({
|
|
27
22
|
view: new View({
|
|
28
23
|
center: [831634, 5933959],
|
|
29
|
-
zoom: 9
|
|
30
|
-
})
|
|
24
|
+
zoom: 9
|
|
25
|
+
})
|
|
31
26
|
});
|
|
32
27
|
});
|
|
33
|
-
|
|
34
28
|
afterEach(() => {
|
|
35
|
-
// ...or gracefully close the connection
|
|
36
29
|
server.close();
|
|
37
|
-
|
|
38
|
-
// The WS class also has a static "clean" method to gracefully close all open connections,
|
|
39
|
-
// particularly useful to reset the environment between test runs.
|
|
40
30
|
WS.clean();
|
|
41
31
|
});
|
|
42
|
-
|
|
43
|
-
test('should be instanced.', () => {
|
|
32
|
+
test("should be instanced.", () => {
|
|
44
33
|
expect(layer).toBeInstanceOf(TralisLayer);
|
|
45
34
|
expect(layer.clickCallbacks[0]).toBe(onClick);
|
|
46
35
|
});
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const spy = jest.spyOn(layer, 'terminate');
|
|
50
|
-
|
|
36
|
+
test("should called terminate on initalization.", () => {
|
|
37
|
+
const spy = jest.spyOn(layer, "detachFromMap");
|
|
51
38
|
fetch.mockResponseOnce(JSON.stringify(global.fetchTrajectoriesResponse));
|
|
52
|
-
|
|
53
|
-
layer.init(olMap);
|
|
39
|
+
layer.attachToMap(olMap);
|
|
54
40
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
55
41
|
});
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const clone = layer.clone({ name: 'clone' });
|
|
42
|
+
test("should clone", () => {
|
|
43
|
+
const clone = layer.clone({ name: "clone" });
|
|
59
44
|
expect(clone).not.toBe(layer);
|
|
60
|
-
expect(clone.name).toBe(
|
|
45
|
+
expect(clone.name).toBe("clone");
|
|
61
46
|
expect(clone).toBeInstanceOf(TralisLayer);
|
|
62
47
|
});
|
|
63
|
-
|
|
64
|
-
test('should use the sort function.', () => {
|
|
48
|
+
test("should use the sort function.", () => {
|
|
65
49
|
const fn = () => true;
|
|
66
50
|
const laye = new TralisLayer({
|
|
67
|
-
url:
|
|
68
|
-
apiKey:
|
|
69
|
-
sort: fn
|
|
51
|
+
url: "ws://localhost:1234",
|
|
52
|
+
apiKey: "apiKey",
|
|
53
|
+
sort: fn
|
|
70
54
|
});
|
|
71
55
|
expect(laye).toBeInstanceOf(TralisLayer);
|
|
72
56
|
expect(laye.sort).toBe(fn);
|
|
73
57
|
});
|
|
74
|
-
|
|
75
|
-
test('should use filter function.', () => {
|
|
58
|
+
test("should use filter function.", () => {
|
|
76
59
|
const fn = () => true;
|
|
77
60
|
const laye = new TralisLayer({
|
|
78
|
-
url:
|
|
79
|
-
apiKey:
|
|
80
|
-
filter: fn
|
|
61
|
+
url: "ws://localhost:1234",
|
|
62
|
+
apiKey: "apiKey",
|
|
63
|
+
filter: fn
|
|
81
64
|
});
|
|
82
65
|
expect(laye).toBeInstanceOf(TralisLayer);
|
|
83
66
|
expect(laye.filter).toBe(fn);
|
|
84
67
|
});
|
|
85
|
-
|
|
86
|
-
test('should override filter function if operator, tripNumber, regexPublishedLineName is set.', () => {
|
|
68
|
+
test("should override filter function if operator, tripNumber, regexPublishedLineName is set.", () => {
|
|
87
69
|
const fn = () => true;
|
|
88
70
|
const laye = new TralisLayer({
|
|
89
|
-
url:
|
|
90
|
-
apiKey:
|
|
91
|
-
filter: fn,
|
|
92
|
-
publishedLineName:
|
|
71
|
+
url: "ws://localhost:1234",
|
|
72
|
+
apiKey: "apiKey",
|
|
73
|
+
filter: fn,
|
|
74
|
+
publishedLineName: ".*"
|
|
93
75
|
});
|
|
94
76
|
expect(laye).toBeInstanceOf(TralisLayer);
|
|
95
77
|
expect(laye.filter).not.toBe(fn);
|
package/ol/layers/VectorLayer.js
CHANGED
|
@@ -1,43 +1,22 @@
|
|
|
1
|
-
import Layer from
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A class use to display vector data.
|
|
5
|
-
*
|
|
6
|
-
* @classproperty {ol/Map~Map} map - The map where the layer is displayed.
|
|
7
|
-
* @extends {Layer}
|
|
8
|
-
*/
|
|
1
|
+
import Layer from "./Layer";
|
|
9
2
|
class VectorLayer extends Layer {
|
|
10
|
-
/**
|
|
11
|
-
* Request feature information for a given coordinate.
|
|
12
|
-
* @param {ol/coordinate~Coordinate} coordinate the coordinate to request the information at.
|
|
13
|
-
* @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.
|
|
14
|
-
*/
|
|
15
3
|
getFeatureInfoAtCoordinate(coordinate) {
|
|
16
4
|
let features = [];
|
|
17
|
-
|
|
18
5
|
if (this.map) {
|
|
19
6
|
const pixel = this.map.getPixelFromCoordinate(coordinate);
|
|
20
7
|
features = this.map.getFeaturesAtPixel(pixel, {
|
|
21
8
|
layerFilter: (l) => l === this.olLayer,
|
|
22
|
-
hitTolerance: this.hitTolerance
|
|
9
|
+
hitTolerance: this.hitTolerance
|
|
23
10
|
});
|
|
24
11
|
}
|
|
25
|
-
|
|
26
12
|
return Promise.resolve({
|
|
27
13
|
features,
|
|
28
14
|
layer: this,
|
|
29
|
-
coordinate
|
|
15
|
+
coordinate
|
|
30
16
|
});
|
|
31
17
|
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Create a copy of the VectorLayer.
|
|
35
|
-
* @param {Object} newOptions Options to override
|
|
36
|
-
* @return {VectorLayer} A VectorLayer
|
|
37
|
-
*/
|
|
38
18
|
clone(newOptions) {
|
|
39
19
|
return new VectorLayer({ ...this.options, ...newOptions });
|
|
40
20
|
}
|
|
41
21
|
}
|
|
42
|
-
|
|
43
22
|
export default VectorLayer;
|