mobility-toolbox-js 2.0.0-beta.33 → 2.0.0-beta.36

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.
Files changed (116) hide show
  1. package/api/RealtimeAPI.d.ts +6 -6
  2. package/api/RealtimeAPI.d.ts.map +1 -1
  3. package/api/RealtimeAPI.js +613 -0
  4. package/api/RoutingAPI.d.ts.map +1 -1
  5. package/api/RoutingAPI.js +35 -0
  6. package/api/StopsAPI.d.ts +1 -1
  7. package/api/StopsAPI.d.ts.map +1 -1
  8. package/api/StopsAPI.js +38 -0
  9. package/api/index.d.ts +3 -4
  10. package/api/index.d.ts.map +1 -1
  11. package/api/index.js +3 -0
  12. package/api/typedefs.js +73 -0
  13. package/common/api/HttpAPI.d.ts.map +1 -1
  14. package/common/api/HttpAPI.js +57 -0
  15. package/common/api/WebSocketAPI.d.ts +2 -2
  16. package/common/api/WebSocketAPI.d.ts.map +1 -1
  17. package/common/api/WebSocketAPI.js +290 -0
  18. package/common/controls/Control.d.ts +5 -5
  19. package/common/controls/Control.d.ts.map +1 -1
  20. package/common/controls/Control.js +137 -0
  21. package/common/index.js +2 -0
  22. package/common/layers/Layer.d.ts +11 -11
  23. package/common/layers/Layer.d.ts.map +1 -1
  24. package/common/layers/Layer.js +223 -0
  25. package/common/mixins/CopyrightMixin.js +43 -0
  26. package/common/mixins/MapboxLayerMixin.js +198 -0
  27. package/common/mixins/RealtimeLayerMixin.js +650 -0
  28. package/common/mixins/StopFinderMixin.d.ts +3 -3
  29. package/common/mixins/StopFinderMixin.d.ts.map +1 -1
  30. package/common/mixins/StopFinderMixin.js +156 -0
  31. package/common/mixins/UserInteractionsLayerMixin.js +192 -0
  32. package/common/styles/index.js +4 -0
  33. package/common/styles/realtimeDefaultStyle.js +239 -0
  34. package/common/styles/realtimeDelayStyle.js +13 -0
  35. package/common/styles/realtimeSimpleStyle.js +22 -0
  36. package/common/typedefs.js +22 -0
  37. package/common/utils/cleanStopTime.js +28 -0
  38. package/common/utils/compareDepartures.d.ts +1 -1
  39. package/common/utils/compareDepartures.d.ts.map +1 -1
  40. package/common/utils/compareDepartures.js +34 -0
  41. package/common/utils/createCanvas.js +27 -0
  42. package/common/utils/createTrackerFilters.d.ts +1 -1
  43. package/common/utils/createTrackerFilters.d.ts.map +1 -1
  44. package/common/utils/createTrackerFilters.js +67 -0
  45. package/common/utils/getLayersAsFlatArray.js +14 -0
  46. package/common/utils/getMapboxMapCopyrights.js +24 -0
  47. package/common/utils/getMapboxRender.js +74 -0
  48. package/common/utils/getMaplibreRender.js +35 -0
  49. package/common/utils/getRealtimeModeSuffix.js +7 -0
  50. package/common/utils/getUrlWithParams.js +18 -0
  51. package/common/utils/getVehiclePosition.js +63 -0
  52. package/common/utils/index.js +12 -0
  53. package/common/utils/removeDuplicate.d.ts +1 -1
  54. package/common/utils/removeDuplicate.d.ts.map +1 -1
  55. package/common/utils/removeDuplicate.js +15 -0
  56. package/common/utils/renderTrajectories.js +107 -0
  57. package/common/utils/sortByDelay.js +20 -0
  58. package/common/utils/timeUtils.js +39 -0
  59. package/common/utils/trackerConfig.js +170 -0
  60. package/iife.js +5 -0
  61. package/index.d.ts +4 -0
  62. package/index.js +10 -0
  63. package/mapbox/controls/CopyrightControl.d.ts +0 -1
  64. package/mapbox/controls/CopyrightControl.d.ts.map +1 -1
  65. package/mapbox/controls/CopyrightControl.js +53 -0
  66. package/mapbox/controls/index.js +2 -0
  67. package/mapbox/index.js +4 -0
  68. package/mapbox/layers/Layer.d.ts +1 -1
  69. package/mapbox/layers/Layer.d.ts.map +1 -1
  70. package/mapbox/layers/Layer.js +97 -0
  71. package/mapbox/layers/RealtimeLayer.d.ts +4 -4
  72. package/mapbox/layers/RealtimeLayer.d.ts.map +1 -1
  73. package/mapbox/layers/RealtimeLayer.js +270 -0
  74. package/mapbox/layers/index.js +2 -0
  75. package/mapbox/utils.js +43 -0
  76. package/mbt.js +6 -5
  77. package/mbt.js.map +2 -2
  78. package/mbt.min.js +2 -2
  79. package/mbt.min.js.map +2 -2
  80. package/ol/controls/CopyrightControl.js +69 -0
  81. package/ol/controls/RoutingControl.d.ts +6 -5
  82. package/ol/controls/RoutingControl.d.ts.map +1 -1
  83. package/ol/controls/RoutingControl.js +622 -0
  84. package/ol/controls/StopFinderControl.js +36 -0
  85. package/ol/controls/index.js +3 -0
  86. package/ol/index.js +5 -0
  87. package/ol/layers/Layer.d.ts +1 -1
  88. package/ol/layers/Layer.d.ts.map +1 -1
  89. package/ol/layers/Layer.js +148 -0
  90. package/ol/layers/MapboxLayer.d.ts +7 -7
  91. package/ol/layers/MapboxLayer.d.ts.map +1 -1
  92. package/ol/layers/MapboxLayer.js +101 -0
  93. package/ol/layers/MapboxStyleLayer.d.ts +3 -3
  94. package/ol/layers/MapboxStyleLayer.d.ts.map +1 -1
  95. package/ol/layers/MapboxStyleLayer.js +340 -0
  96. package/ol/layers/MaplibreLayer.d.ts +1 -1
  97. package/ol/layers/MaplibreLayer.d.ts.map +1 -1
  98. package/ol/layers/MaplibreLayer.js +35 -0
  99. package/ol/layers/RealtimeLayer.d.ts +2 -2
  100. package/ol/layers/RealtimeLayer.d.ts.map +1 -1
  101. package/ol/layers/RealtimeLayer.js +294 -0
  102. package/ol/layers/RoutingLayer.d.ts +2 -2
  103. package/ol/layers/RoutingLayer.d.ts.map +1 -1
  104. package/ol/layers/RoutingLayer.js +84 -0
  105. package/ol/layers/VectorLayer.d.ts +1 -1
  106. package/ol/layers/VectorLayer.d.ts.map +1 -1
  107. package/ol/layers/VectorLayer.js +38 -0
  108. package/ol/layers/WMSLayer.d.ts +1 -1
  109. package/ol/layers/WMSLayer.d.ts.map +1 -1
  110. package/ol/layers/WMSLayer.js +72 -0
  111. package/ol/layers/index.js +8 -0
  112. package/ol/styles/fullTrajectoryDelayStyle.js +33 -0
  113. package/ol/styles/fullTrajectoryStyle.js +44 -0
  114. package/ol/styles/index.js +2 -0
  115. package/package.json +2 -2
  116. package/setupTests.js +13 -0
@@ -0,0 +1,148 @@
1
+ import { unByKey } from 'ol/Observable';
2
+ import LayerCommon from '../../common/layers/Layer';
3
+ import userInteractionsMixin from '../../common/mixins/UserInteractionsLayerMixin';
4
+ /**
5
+ * A class representing a layer to display on an OpenLayers map.
6
+ *
7
+ * @example
8
+ * import { Layer } from 'mobility-toolbox-js/ol';
9
+ *
10
+ * const layer = new Layer({
11
+ * olLayer: ...,
12
+ * });
13
+ *
14
+ * @see <a href="/example/ol-map">Map example</a>
15
+ *
16
+ * @classproperty {ol/Map~Map} map - The map where the layer is displayed.
17
+ * @extends {Layer}
18
+ */
19
+ class Layer extends userInteractionsMixin(LayerCommon) {
20
+ /**
21
+ * Constructor.
22
+ *
23
+ * @param {Object} options
24
+ * @param {ol/layer/Layer~Layer} options.olLayer The layer (required).
25
+ * @param {string} [options.name=uuid()] Layer name. Default use a generated uuid.
26
+ * @param {string} [options.key=uuid().toLowerCase()] Layer key, will use options.name.toLowerCase() if not specified.
27
+ * @param {string} [options.copyright=undefined] Copyright-Statement.
28
+ * @param {Array<Layer>} [options.children=[]] Sublayers.
29
+ * @param {Object} [options.properties={}] Application-specific layer properties.
30
+ * @param {boolean} [options.visible=true] If true this layer is the currently visible layer on the map.
31
+ */
32
+ constructor(options) {
33
+ super(options);
34
+ if (this.olLayer) {
35
+ this.olLayer.setVisible(this.visible);
36
+ }
37
+ }
38
+ /**
39
+ * Define layer's properties.
40
+ *
41
+ * @ignore
42
+ */
43
+ defineProperties(options) {
44
+ super.defineProperties(options);
45
+ Object.defineProperties(this, {
46
+ olLayer: { value: options.olLayer, writable: true },
47
+ olListenersKeys: {
48
+ value: [],
49
+ },
50
+ });
51
+ }
52
+ /**
53
+ * Initialize the layer and listen to feature clicks.
54
+ * @param {ol/Map~Map} map
55
+ */
56
+ attachToMap(map) {
57
+ var _a, _b, _c, _d;
58
+ super.attachToMap(map);
59
+ if (!this.map) {
60
+ return;
61
+ }
62
+ if (this.olLayer &&
63
+ !((_c = (_b = (_a = this.map) === null || _a === void 0 ? void 0 : _a.getLayers()) === null || _b === void 0 ? void 0 : _b.getArray()) === null || _c === void 0 ? void 0 : _c.includes(this.olLayer))) {
64
+ this.map.addLayer(this.olLayer);
65
+ }
66
+ this.olListenersKeys.push(this.on('change:visible', () => {
67
+ if (this.olLayer) {
68
+ this.olLayer.setVisible(this.visible);
69
+ }
70
+ }));
71
+ this.olListenersKeys.push(this.map.getLayers().on('remove', (evt) => {
72
+ if (evt.element === this.olLayer) {
73
+ this.detachFromMap();
74
+ }
75
+ }));
76
+ this.toggleVisibleListeners();
77
+ this.olListenersKeys.push(this.on('change:visible', this.toggleVisibleListeners));
78
+ // We set the copyright to the source used by the layer.
79
+ if (this.copyrights && this.olLayer) {
80
+ const attributions = this.copyrights || [];
81
+ if (this.olLayer.getLayers) {
82
+ this.olLayer
83
+ .getLayers()
84
+ .getArray()
85
+ .forEach((layer) => {
86
+ var _a;
87
+ (_a = layer.getSource()) === null || _a === void 0 ? void 0 : _a.setAttributions(attributions);
88
+ });
89
+ }
90
+ else if (this.olLayer.getSource) {
91
+ (_d = this.olLayer.getSource()) === null || _d === void 0 ? void 0 : _d.setAttributions(attributions);
92
+ }
93
+ }
94
+ }
95
+ /**
96
+ * Terminate what was initialized in init function. Remove layer, events...
97
+ */
98
+ detachFromMap() {
99
+ var _a, _b, _c;
100
+ this.deactivateUserInteractions();
101
+ unByKey(this.olListenersKeys);
102
+ if (this.olLayer &&
103
+ ((_c = (_b = (_a = this.map) === null || _a === void 0 ? void 0 : _a.getLayers()) === null || _b === void 0 ? void 0 : _b.getArray()) === null || _c === void 0 ? void 0 : _c.includes(this.olLayer))) {
104
+ this.map.removeLayer(this.olLayer);
105
+ }
106
+ super.detachFromMap();
107
+ }
108
+ activateUserInteractions() {
109
+ this.deactivateUserInteractions();
110
+ if (this.map &&
111
+ this.userInteractions &&
112
+ this.userClickInteractions &&
113
+ this.userClickCallbacks.length) {
114
+ this.singleClickListenerKey = this.map.on('singleclick', this.onUserClickCallback);
115
+ this.olListenersKeys.push(this.singleClickListenerKey);
116
+ }
117
+ if (this.map &&
118
+ this.userInteractions &&
119
+ this.userHoverInteractions &&
120
+ this.userHoverCallbacks.length) {
121
+ this.pointerMoveListenerKey = this.map.on('pointermove', this.onUserMoveCallback);
122
+ }
123
+ }
124
+ deactivateUserInteractions() {
125
+ unByKey([this.pointerMoveListenerKey, this.singleClickListenerKey]);
126
+ }
127
+ /**
128
+ * Toggle listeners needed when a layer is avisible or not.
129
+ * @private
130
+ */
131
+ toggleVisibleListeners() {
132
+ if (this.visible) {
133
+ this.activateUserInteractions();
134
+ }
135
+ else {
136
+ this.deactivateUserInteractions();
137
+ }
138
+ }
139
+ /**
140
+ * Create a copy of the Layer.
141
+ * @param {Object} newOptions Options to override
142
+ * @return {Layer} A Layer
143
+ */
144
+ clone(newOptions) {
145
+ return new Layer(Object.assign(Object.assign({}, this.options), newOptions));
146
+ }
147
+ }
148
+ export default Layer;
@@ -21,14 +21,14 @@ export default class MapboxLayer extends Layer {
21
21
  /** @ignore */
22
22
  renderState: {
23
23
  center: any[];
24
- zoom: any;
25
- rotation: any;
26
- visible: any;
27
- opacity: any;
24
+ zoom: null;
25
+ rotation: null;
26
+ visible: null;
27
+ opacity: null;
28
28
  size: number[];
29
- };
29
+ } | undefined;
30
30
  /** @ignore */
31
- copyrights: any[];
31
+ copyrights: any[] | undefined;
32
32
  getOlLayerRender(): (frameState: any) => any;
33
33
  getMapboxMapClass(): any;
34
34
  /**
@@ -36,7 +36,7 @@ export default class MapboxLayer extends Layer {
36
36
  * @param {Object} newOptions Options to override
37
37
  * @return {MapboxLayer} A MapboxLayer
38
38
  */
39
- clone(newOptions: any): MapboxLayer;
39
+ clone(newOptions: Object): MapboxLayer;
40
40
  }
41
41
  import Layer from "./Layer";
42
42
  //# sourceMappingURL=MapboxLayer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MapboxLayer.d.ts","sourceRoot":"","sources":["../../../src/ol/layers/MapboxLayer.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;GAaG;AACH;IA2BE;;;OAGG;IACH,kBA0CC;IA/BC,cAAc;IACd;;;;;;;MAOC;IAOC,cAAc;IACd,kBAA0D;IAiB9D,6CAEC;IAGD,yBAEC;IAED;;;;OAIG;IACH,wBAFY,WAAW,CAItB;CACF"}
1
+ {"version":3,"file":"MapboxLayer.d.ts","sourceRoot":"","sources":["../../../src/ol/layers/MapboxLayer.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;GAaG;AACH;IA2BE;;;OAGG;IACH,kBA0CC;IA/BC,cAAc;IACd;;;;;;;kBAOC;IAOC,cAAc;IACd,8BAA0D;IAiB9D,6CAEC;IAGD,yBAEC;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACL,WAAW,CAItB;CACF"}
@@ -0,0 +1,101 @@
1
+ /* eslint-disable no-underscore-dangle */
2
+ import { Map } from 'mapbox-gl';
3
+ import Layer from './Layer';
4
+ import mixin from '../../common/mixins/MapboxLayerMixin';
5
+ import { getMapboxMapCopyrights, getMapboxRender } from '../../common/utils';
6
+ /**
7
+ * A class representing Mapboxlayer to display on BasicMap
8
+ *
9
+ * @example
10
+ * import { MapboxLayer } from 'mobility-toolbox-js/ol';
11
+ *
12
+ * const layer = new MapboxLayer({
13
+ * url: 'https://maps.geops.io/styles/travic_v2/style.json',
14
+ * apikey: 'yourApiKey',
15
+ * });
16
+ *
17
+ * @classproperty {ol/Map~Map} map - The map where the layer is displayed.
18
+ * @extends {Layer}
19
+ */
20
+ export default class MapboxLayer extends mixin(Layer) {
21
+ /**
22
+ * Initialize the layer and listen to feature clicks.
23
+ * @param {ol/Map~Map} map
24
+ */
25
+ attachToMap(map) {
26
+ super.attachToMap(map);
27
+ if (!this.map || this.mbMap) {
28
+ return;
29
+ }
30
+ this.olListenersKeys.push(this.map.on('change:size', () => {
31
+ try {
32
+ if (this.mbMap) {
33
+ this.mbMap.resize();
34
+ }
35
+ }
36
+ catch (err) {
37
+ // ignore render errors
38
+ // eslint-disable-next-line no-console
39
+ console.warn(err);
40
+ }
41
+ }));
42
+ }
43
+ /**
44
+ * Create the mapbox map.
45
+ * @private
46
+ */
47
+ loadMbMap() {
48
+ // If the map hasn't been resized, the center could be [NaN,NaN].
49
+ // We set default good value for the mapbox map, to avoid the app crashes.
50
+ let [x, y] = this.map.getView().getCenter();
51
+ if (!x || !y) {
52
+ x = 0;
53
+ y = 0;
54
+ }
55
+ // Options the last render run did happen. If something changes
56
+ // we have to render again
57
+ /** @ignore */
58
+ this.renderState = {
59
+ center: [x, y],
60
+ zoom: null,
61
+ rotation: null,
62
+ visible: null,
63
+ opacity: null,
64
+ size: [0, 0],
65
+ };
66
+ super.loadMbMap();
67
+ this.mbMap.once('load', () => {
68
+ var _a;
69
+ this.mbMap.resize();
70
+ /** @ignore */
71
+ this.copyrights = getMapboxMapCopyrights(this.mbMap) || [];
72
+ (_a = this.olLayer.getSource()) === null || _a === void 0 ? void 0 : _a.setAttributions(this.copyrights);
73
+ });
74
+ const mapboxCanvas = this.mbMap.getCanvas();
75
+ if (mapboxCanvas) {
76
+ if (this.options.tabIndex) {
77
+ mapboxCanvas.setAttribute('tabindex', this.options.tabIndex);
78
+ }
79
+ else {
80
+ // With a tabIndex='-1' the mouse events works but the map is not focused when we click on it
81
+ // so we remove completely the tabIndex attribute.
82
+ mapboxCanvas.removeAttribute('tabindex');
83
+ }
84
+ }
85
+ }
86
+ getOlLayerRender() {
87
+ return getMapboxRender(this);
88
+ }
89
+ // eslint-disable-next-line class-methods-use-this
90
+ getMapboxMapClass() {
91
+ return Map;
92
+ }
93
+ /**
94
+ * Create a copy of the MapboxLayer.
95
+ * @param {Object} newOptions Options to override
96
+ * @return {MapboxLayer} A MapboxLayer
97
+ */
98
+ clone(newOptions) {
99
+ return new MapboxLayer(Object.assign(Object.assign({}, this.options), newOptions));
100
+ }
101
+ }
@@ -26,8 +26,8 @@ declare class MapboxStyleLayer extends Layer {
26
26
  * @param {Function} [options.styleLayersFilter] Filter function to decide which style layer to display.
27
27
  */
28
28
  constructor(options?: {
29
- mapboxLayer?: MapboxLayer;
30
- styleLayersFilter?: Function;
29
+ mapboxLayer?: any;
30
+ styleLayersFilter?: Function | undefined;
31
31
  });
32
32
  /**
33
33
  * MapboxLayer provided for the style Layer.
@@ -140,7 +140,7 @@ declare class MapboxStyleLayer extends Layer {
140
140
  * @param {Object} newOptions Options to override.
141
141
  * @return {MapboxStyleLayer} A MapboxStyleLayer.
142
142
  */
143
- clone(newOptions: any): MapboxStyleLayer;
143
+ clone(newOptions: Object): MapboxStyleLayer;
144
144
  }
145
145
  import Layer from "./Layer";
146
146
  //# sourceMappingURL=MapboxStyleLayer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MapboxStyleLayer.d.ts","sourceRoot":"","sources":["../../../src/ol/layers/MapboxStyleLayer.js"],"names":[],"mappings":";AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH;IACE;;;;;;OAMG;IACH;QAHiC,WAAW;QACd,iBAAiB;OA4F9C;IAvFC;;;;OAIG;IACH,oBAAsC;IAEtC;;OAEG;IACH,kBAAqB;IAErB;;;;OAIG;IACH,0BAAkD;IAElD;;;;;OAKG;IACH,iBAAgC;IAEhC;;;;OAIG;IACH,0BAAoE;IAEpE;;;;OAIG;IACH,kCAAkE;IAElE;;;;OAIG;IACH,4BAA6B;IAE7B;;;;OAIG;IACH,yBAA0B;IAE1B;;;;OAIG;IACH,oBACyE;IAiG3E,cAAc;IACd,uBAcC;IAiBD;;;OAGG;IACH,eAaC;IAtIG,eAAe;IACf,0BAMC;IAgEL;;;;OAIG;IACH,gDAOC;IAmBD,cAAc;IACd,0BAYC;IAqBD;;;;OAIG;IACH,6CAFY,QAAQ,WAAW,CAAC,CAiC/B;IAED;;;OAGG;IACH,yCAYC;IAED;;;;;OAKG;IACH,sBA8BC;IAED;;;;OAIG;IACH,eAIC;IAED;;;;OAIG;IACH,kBAeC;IAED;;;;OAIG;IAEH,8BA8BC;IAED;;;;OAIG;IACH,wBAFY,gBAAgB,CAI3B;CACF"}
1
+ {"version":3,"file":"MapboxStyleLayer.d.ts","sourceRoot":"","sources":["../../../src/ol/layers/MapboxStyleLayer.js"],"names":[],"mappings":";AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH;IACE;;;;;;OAMG;IACH;QAHiC,WAAW;QACd,iBAAiB;OA4F9C;IAvFC;;;;OAIG;IACH,oBAAsC;IAEtC;;OAEG;IACH,kBAAqB;IAErB;;;;OAIG;IACH,0BAAkD;IAElD;;;;;OAKG;IACH,iBAAgC;IAEhC;;;;OAIG;IACH,0BAAoE;IAEpE;;;;OAIG;IACH,kCAAkE;IAElE;;;;OAIG;IACH,4BAA6B;IAE7B;;;;OAIG;IACH,yBAA0B;IAE1B;;;;OAIG;IACH,oBACyE;IAiG3E,cAAc;IACd,uBAcC;IAiBD;;;OAGG;IACH,eAaC;IAtIG,eAAe;IACf,0BAMC;IAgEL;;;;OAIG;IACH,gDAOC;IAmBD,cAAc;IACd,0BAYC;IAqBD;;;;OAIG;IACH,6CAFY,QAAQ,WAAW,CAAC,CAiC/B;IAED;;;OAGG;IACH,yCAYC;IAED;;;;;OAKG;IACH,sBA8BC;IAED;;;;OAIG;IACH,eAIC;IAED;;;;OAIG;IACH,kBAeC;IAED;;;;OAIG;IAEH,8BA8BC;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACL,gBAAgB,CAI3B;CACF"}
@@ -0,0 +1,340 @@
1
+ /* eslint-disable no-param-reassign */
2
+ import Layer from './Layer';
3
+ /**
4
+ * Layer for visualizing a specific set of layer from a MapboxLayer.
5
+ *
6
+ * @example
7
+ * import { MapboxLayer, MapboxStyleLayer } from 'mobility-toolbox-js/ol';
8
+ *
9
+ * const mapboxLayer = new MapboxLayer({
10
+ * url: 'https://maps.geops.io/styles/travic_v2/style.json?key=[yourApiKey]',
11
+ * });
12
+ *
13
+ * const layer = new MapboxStyleLayer({
14
+ * mapboxLayer: mapboxLayer,
15
+ * styleLayersFilter: () => {},
16
+ * });
17
+ *
18
+ * @classproperty {ol/Map~Map} map - The map where the layer is displayed.
19
+ * @extends {Layer}
20
+ */
21
+ class MapboxStyleLayer extends Layer {
22
+ /**
23
+ * Constructor.
24
+ *
25
+ * @param {Object} options
26
+ * @param {MapboxLayer} [options.mapboxLayer] The MapboxLayer to use.
27
+ * @param {Function} [options.styleLayersFilter] Filter function to decide which style layer to display.
28
+ */
29
+ constructor(options = {}) {
30
+ super(options);
31
+ /**
32
+ * MapboxLayer provided for the style Layer.
33
+ * @type {MapboxLayer}
34
+ * @private
35
+ */
36
+ this.mapboxLayer = options.mapboxLayer;
37
+ /**
38
+ * Define if the layer has data to display in the current mapbox layer.
39
+ */
40
+ this.disabled = false;
41
+ /**
42
+ * Function to filter features to be displayed.
43
+ * @type {function}
44
+ * @private
45
+ */
46
+ this.styleLayersFilter = options.styleLayersFilter;
47
+ /**
48
+ * Mapbox style layer id where to add the style layers.
49
+ * See [mapbox.map.addLayer](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#addlayer) documentation.
50
+ * @type {String}
51
+ * @private
52
+ */
53
+ this.beforeId = options.beforeId;
54
+ /**
55
+ * Function to filter features for getFeatureInfoAtCoordinate method.
56
+ * @type {function}
57
+ * @private
58
+ */
59
+ this.featureInfoFilter = options.featureInfoFilter || ((obj) => obj);
60
+ /**
61
+ * Function to query the rendered features.
62
+ * @type {function}
63
+ * @private
64
+ */
65
+ this.queryRenderedLayersFilter = options.queryRenderedLayersFilter;
66
+ /**
67
+ * Array of features to highlight.
68
+ * @type {Array<ol/Feature~Feature>}
69
+ * @private
70
+ */
71
+ this.highlightedFeatures = [];
72
+ /**
73
+ * Array of selected features.
74
+ * @type {Array<ol/Feature~Feature>}
75
+ * @private
76
+ */
77
+ this.selectedFeatures = [];
78
+ /**
79
+ * Array of mapbox style layers to add.
80
+ * @type {Array<mapboxgl.styleLayer>}
81
+ * @private
82
+ */
83
+ this.styleLayers =
84
+ (options.styleLayer ? [options.styleLayer] : options.styleLayers) || [];
85
+ /**
86
+ * @private
87
+ */
88
+ this.addStyleLayers = this.addStyleLayers.bind(this);
89
+ /**
90
+ * @private
91
+ */
92
+ this.onLoad = this.onLoad.bind(this);
93
+ if (options.filters) {
94
+ /** @private */
95
+ this.addDynamicFilters = () => {
96
+ this.setFilter(typeof options.filters === 'function'
97
+ ? options.filters(this)
98
+ : options.filters);
99
+ };
100
+ }
101
+ if (!this.styleLayersFilter && this.styleLayers) {
102
+ const ids = this.styleLayers.map((s) => s.id);
103
+ this.styleLayersFilter = (styleLayer) => ids.includes(styleLayer.id);
104
+ }
105
+ }
106
+ /**
107
+ * Initialize the layer.
108
+ * @param {mapboxgl.Map} map the mapbox map.
109
+ * @override
110
+ */
111
+ attachToMap(map) {
112
+ if (!this.mapboxLayer.map) {
113
+ this.mapboxLayer.attachToMap(map);
114
+ }
115
+ super.attachToMap(map);
116
+ if (!this.map) {
117
+ return;
118
+ }
119
+ // Apply the initial visibiltity.
120
+ const { mbMap } = this.mapboxLayer;
121
+ if (!mbMap) {
122
+ // If the mbMap is not yet created because the map has no target yet, we
123
+ // relaunch the initialisation when it's the case.
124
+ this.olListenersKeys.push(this.map.on('change:target', () => {
125
+ this.attachToMap(map);
126
+ }));
127
+ return;
128
+ }
129
+ // mbMap.loaded() and mbMap.isStyleLoaded() are reliable only on the first call of init.
130
+ // On the next call (when a topic change for example), these functions returns false because
131
+ // the style is being modified.
132
+ // That's why we rely on a property instead for the next calls.
133
+ if (this.mapboxLayer.loaded || mbMap.isStyleLoaded() || mbMap.loaded()) {
134
+ this.onLoad();
135
+ }
136
+ else {
137
+ mbMap.once('load', this.onLoad);
138
+ }
139
+ // Apply the visibiltity when layer's visibility change.
140
+ this.olListenersKeys.push(this.on('change:visible', (evt) => {
141
+ // Once the map is loaded we can apply vsiiblity without waiting
142
+ // the style. Mapbox take care of the application of style changes.
143
+ this.applyLayoutVisibility(evt);
144
+ }));
145
+ this.olListenersKeys.push(this.mapboxLayer.on('load', () => {
146
+ this.onLoad();
147
+ }));
148
+ }
149
+ /**
150
+ * Terminate the layer.
151
+ * @param {mapboxgl.Map} map the mapbox map.
152
+ * @override
153
+ */
154
+ detachFromMap(map) {
155
+ const { mbMap } = this.mapboxLayer;
156
+ if (mbMap) {
157
+ mbMap.off('load', this.onLoad);
158
+ this.removeStyleLayers();
159
+ }
160
+ super.detachFromMap(map);
161
+ }
162
+ /** @ignore */
163
+ addStyleLayers() {
164
+ const { mbMap } = this.mapboxLayer;
165
+ if (!mbMap) {
166
+ return;
167
+ }
168
+ this.styleLayers.forEach((styleLayer) => {
169
+ const { id, source } = styleLayer;
170
+ if (mbMap.getSource(source) && !mbMap.getLayer(id)) {
171
+ mbMap.addLayer(styleLayer, this.beforeId);
172
+ }
173
+ });
174
+ this.applyLayoutVisibility();
175
+ }
176
+ /** @ignore */
177
+ removeStyleLayers() {
178
+ const { mbMap } = this.mapboxLayer;
179
+ if (!mbMap) {
180
+ return;
181
+ }
182
+ this.styleLayers.forEach((styleLayer) => {
183
+ if (mbMap.getLayer(styleLayer.id)) {
184
+ mbMap.removeLayer(styleLayer.id);
185
+ }
186
+ });
187
+ }
188
+ /**
189
+ * On Mapbox map load callback function. Add style layers and dynaimc filters.
190
+ * @ignore
191
+ */
192
+ onLoad() {
193
+ this.addStyleLayers();
194
+ if (this.addDynamicFilters) {
195
+ this.addDynamicFilters();
196
+ }
197
+ const { mbMap } = this.mapboxLayer;
198
+ const style = mbMap.getStyle();
199
+ if (style && this.styleLayersFilter) {
200
+ const styles = style.layers.filter(this.styleLayersFilter);
201
+ this.disabled = !styles.length;
202
+ }
203
+ }
204
+ /**
205
+ * Request feature information for a given coordinate.
206
+ * @param {ol/coordinate~Coordinate} coordinate Coordinate to request the information at.
207
+ * @return {Promise<FeatureInfo>} Promise with features, layer and coordinate.
208
+ */
209
+ getFeatureInfoAtCoordinate(coordinate) {
210
+ const { mbMap } = this.mapboxLayer;
211
+ // Ignore the getFeatureInfo until the mapbox map is loaded
212
+ if (!mbMap || !mbMap.isStyleLoaded()) {
213
+ return Promise.resolve({ coordinate, features: [], layer: this });
214
+ }
215
+ // We query features only on style layers used by this layer.
216
+ let layers = this.styleLayers || [];
217
+ if (this.styleLayersFilter) {
218
+ layers = mbMap.getStyle().layers.filter(this.styleLayersFilter);
219
+ }
220
+ if (this.queryRenderedLayersFilter) {
221
+ layers = mbMap.getStyle().layers.filter(this.queryRenderedLayersFilter);
222
+ }
223
+ return this.mapboxLayer
224
+ .getFeatureInfoAtCoordinate(coordinate, {
225
+ layers: layers.map((layer) => layer && layer.id),
226
+ validate: false,
227
+ })
228
+ .then((featureInfo) => {
229
+ const features = featureInfo.features.filter((feature) => this.featureInfoFilter(feature, this.map.getView().getResolution()));
230
+ this.highlight(features);
231
+ return Object.assign(Object.assign({}, featureInfo), { features, layer: this });
232
+ });
233
+ }
234
+ /**
235
+ * Set filter that determines which features should be rendered in a style layer.
236
+ * @param {mapboxgl.filter} filter Determines which features should be rendered in a style layer.
237
+ */
238
+ setFilter(filter) {
239
+ const { mbMap } = this.mapboxLayer;
240
+ if (!mbMap) {
241
+ return;
242
+ }
243
+ this.styleLayers.forEach(({ id }) => {
244
+ if (mbMap.getLayer(id)) {
245
+ mbMap.setFilter(id, filter);
246
+ }
247
+ });
248
+ }
249
+ /**
250
+ * Set if features are hovered or not.
251
+ * @param {Array<ol/Feature~Feature>} features
252
+ * @param {boolean} state Is the feature hovered
253
+ * @private
254
+ */
255
+ setHoverState(features, state) {
256
+ const { mbMap } = this.mapboxLayer;
257
+ if (!features || !mbMap) {
258
+ return;
259
+ }
260
+ features.forEach((feature) => {
261
+ const { source, sourceLayer } = feature.get('mapboxFeature') || {};
262
+ if ((!source && !sourceLayer) || !feature.getId()) {
263
+ if (!feature.getId()) {
264
+ // eslint-disable-next-line no-console
265
+ console.warn("No feature's id found. To use the feature state functionnality, tiles must be generated with --generate-ids. See https://github.com/mapbox/tippecanoe#adding-calculated-attributes.", feature.getId(), feature.getProperties());
266
+ }
267
+ return;
268
+ }
269
+ mbMap.setFeatureState({
270
+ id: feature.getId(),
271
+ source,
272
+ sourceLayer,
273
+ }, { hover: state });
274
+ });
275
+ }
276
+ /**
277
+ * Select a list of features.
278
+ * @param {Array<ol/Feature~Feature>} [features=[]] Features to select.
279
+ * @private
280
+ */
281
+ select(features = []) {
282
+ this.setHoverState(this.selectedFeatures, false);
283
+ this.selectedFeatures = features;
284
+ this.setHoverState(this.selectedFeatures, true);
285
+ }
286
+ /**
287
+ * Highlight a list of features.
288
+ * @param {Array<ol/Feature~Feature>} [features=[]] Features to highlight.
289
+ * @private
290
+ */
291
+ highlight(features = []) {
292
+ // Filter out selected features
293
+ const filtered = this.highlightedFeatures.filter((feature) => !this.selectedFeatures
294
+ .map((feat) => feat.getId())
295
+ .includes(feature.getId()));
296
+ // Remove previous highlight
297
+ this.setHoverState(filtered, false);
298
+ this.highlightedFeatures = features;
299
+ // Add highlight
300
+ this.setHoverState(this.highlightedFeatures, true);
301
+ }
302
+ /**
303
+ * Apply visibility to style layers that fits the styleLayersFilter function.
304
+ * @param {Event} evt Layer's event that has called the function.
305
+ * @private
306
+ */
307
+ // eslint-disable-next-line no-unused-vars
308
+ applyLayoutVisibility(evt) {
309
+ const { visible } = this;
310
+ const { mbMap } = this.mapboxLayer;
311
+ const filterFunc = this.styleLayersFilter;
312
+ if (!mbMap) {
313
+ return;
314
+ }
315
+ const style = mbMap.getStyle();
316
+ if (!style) {
317
+ return;
318
+ }
319
+ if (filterFunc) {
320
+ const visibilityValue = visible ? 'visible' : 'none';
321
+ for (let i = 0; i < style.layers.length; i += 1) {
322
+ const styleLayer = style.layers[i];
323
+ if (filterFunc(styleLayer)) {
324
+ if (mbMap.getLayer(styleLayer.id)) {
325
+ mbMap.setLayoutProperty(styleLayer.id, 'visibility', visibilityValue);
326
+ }
327
+ }
328
+ }
329
+ }
330
+ }
331
+ /**
332
+ * Create a copy of the MapboxStyleLayer.
333
+ * @param {Object} newOptions Options to override.
334
+ * @return {MapboxStyleLayer} A MapboxStyleLayer.
335
+ */
336
+ clone(newOptions) {
337
+ return new MapboxStyleLayer(Object.assign(Object.assign({}, this.options), newOptions));
338
+ }
339
+ }
340
+ export default MapboxStyleLayer;
@@ -20,7 +20,7 @@ export default class MaplibreLayer extends Layer {
20
20
  * @param {Object} newOptions Options to override
21
21
  * @return {MapboxLayer} A MapboxLayer
22
22
  */
23
- clone(newOptions: any): MapboxLayer;
23
+ clone(newOptions: Object): MapboxLayer;
24
24
  }
25
25
  import Layer from "./Layer";
26
26
  import { Map } from "maplibre-gl";
@@ -1 +1 @@
1
- {"version":3,"file":"MaplibreLayer.d.ts","sourceRoot":"","sources":["../../../src/ol/layers/MaplibreLayer.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;GAaG;AACH;IACE,6CAEC;IAGD,gCAEC;IAED;;;;OAIG;IACH,oCAEC;CACF"}
1
+ {"version":3,"file":"MaplibreLayer.d.ts","sourceRoot":"","sources":["../../../src/ol/layers/MaplibreLayer.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;GAaG;AACH;IACE,6CAEC;IAGD,gCAEC;IAED;;;;OAIG;IACH,kBAHW,MAAM,eAKhB;CACF"}