@masterportal/masterportalapi 2.19.2 → 2.20.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/CHANGELOG.md CHANGED
@@ -3,11 +3,29 @@
3
3
 
4
4
  The [Semantic Versioning](https://semver.org/spec/v2.0.0.html) is used.
5
5
 
6
+ ## ## 2.20.0 - 2023-06-30
7
+ ### Added
8
+ - Add draw interaction for interactive and static geometry types.
9
+ - WFS: Added function to load wfs features manually.
10
+
11
+ ### Changed
12
+ - The following packages have been updated:
13
+ - dependencies:
14
+ - ol: 7.3.0 to 7.4.0
15
+ - cesium: 1.95.0 to 1.106.0
16
+ - The examples in example/index.js are updated.
17
+
18
+ ### Fixed
19
+ - VectorStyle: fixed several bugs of multiple geometries with styling rules.
20
+
21
+ ---
22
+
6
23
  ## 2.19.2 - 2023-06-12
7
24
  ### Fixed
8
25
  - VectorStyle of multiple geometries with styling rules does not fail on not existing style.
9
26
 
10
27
  ---
28
+
11
29
  ## 2.19.1 - 2023-06-02
12
30
  ### Changed
13
31
  - Exports in src/layer/wmts.js changed to export default {} to provide ES-Syntax.
@@ -135,32 +135,53 @@
135
135
  },
136
136
  {
137
137
  "id": "6001",
138
- "name": "ADV (EPSG:25832)",
139
- "url": "https://dev.adv-smart.de/tiles/smarttiles_de_UTM32_dev/{z}/{x}/{y}.pbf",
140
- "epsg": "EPSG:25832",
138
+ "name": "ArcGIS VectorTile",
139
+ "shortname": "VectorTile",
141
140
  "typ": "VectorTile",
141
+ "visibility": false,
142
+ "preview": {
143
+ "src": "./resources/vectorTile.png"
144
+ },
145
+ "gfiAttributes": "showAll",
146
+ "url": "https://test.geoportal-hamburg.de/vt/esri/tile/{z}/{y}/{x}.pbf",
147
+ "epsg": "EPSG:25832",
142
148
  "extent": [
143
- -46133.17,
144
- 5048875.26857567,
145
- 1206211.10142433,
146
- 6301219.54000000
149
+ 441336.2209999999,
150
+ 5915995,
151
+ 594002,
152
+ 5986767.56699999981
153
+ ],
154
+ "origin": [
155
+ -9497963.94293634221,
156
+ 9997963.94293634221
147
157
  ],
148
158
  "resolutions": [
149
- 4891.96981025128,
150
- 2445.98490512564,
151
- 1222.99245256282,
152
- 611.496226281410,
153
- 305.748113140705,
154
- 152.874056570353,
155
- 76.4370282851763,
156
- 38.2185141425881,
157
- 19.1092570712941,
158
- 9.55462853564703,
159
- 4.77731426782352,
160
- 2.38865713391176
159
+ 39054.5466520950868,
160
+ 19527.2733260475434,
161
+ 9763.63666302377169,
162
+ 4881.81833151188584,
163
+ 2440.90916575594292,
164
+ 1220.45458287797146,
165
+ 610.227291438985731,
166
+ 305.113645719492865,
167
+ 152.556822859746433,
168
+ 76.2784114298732163,
169
+ 38.1392057149366082,
170
+ 19.0696028574683041,
171
+ 9.534801428734152,
172
+ 4.767400714367076,
173
+ 2.383700357183538,
174
+ 1.191850178591769
161
175
  ],
162
- "tileSize": 256,
163
- "zDirection": -1
176
+ "tileSize": 512,
177
+ "vtStyles": [
178
+ {
179
+ "id": "VectorTile_STYLE",
180
+ "name": "Test",
181
+ "url": "https://test.geoportal-hamburg.de/vt/esri/resources/styles/root.json",
182
+ "defaultStyle": true
183
+ }
184
+ ]
164
185
  },
165
186
  {
166
187
  "id": "7001",
package/example/index.js CHANGED
@@ -18,6 +18,7 @@ function errorCallback (errorEvent) {
18
18
  console.error("This is an error event:", errorEvent);
19
19
  }
20
20
 
21
+ // Definitions:
21
22
  //* Add elements to window to play with API in console
22
23
  window.mpapi = {
23
24
  ...mpapi,
@@ -45,12 +46,12 @@ const hamburgServicesUrl = "https://geodienste.hamburg.de/services-internet.json
45
46
  // eslint-disable-next-line func-style
46
47
  getWfsStyleFunction = function () {
47
48
  const styleId = "8712",
48
- olLayer = window.mpapi.map.getLayers().getArray().find((element) => element.get("id") === "8712"),
49
- source = olLayer.getSource(),
49
+ olLayer = window.mpapi.map?.getLayers().getArray().find((element) => element.get("id") === "8712"),
50
+ source = olLayer?.getSource(),
50
51
  styleObject = styleList.returnStyleObject(styleId);
51
52
  let isClusterFeature = false;
52
53
 
53
- if (styleObject !== undefined) {
54
+ if (styleObject !== undefined && source !== undefined) {
54
55
  source.on("featuresloadend", event => {
55
56
  event.features.forEach(element => {
56
57
  isClusterFeature = false;
@@ -61,6 +62,9 @@ const hamburgServicesUrl = "https://geodienste.hamburg.de/services-internet.json
61
62
  };
62
63
  let map2D = null;
63
64
 
65
+
66
+ // Examples:
67
+
64
68
  /* VectorStyle example */
65
69
  // Example for using the vectorStyle that is now implemented in the masterportalAPI.
66
70
  // Hardcoded to show the school layer "8712" as a wfs and "1534" as wfs with webgl renderer.
@@ -74,70 +78,8 @@ styleList.initializeStyleList({}, config, config.layers, undefined, (currentStyl
74
78
  return currentStyleList;
75
79
  });
76
80
 
77
- // */
78
81
  //* Cleans up map before it is re-rendered (happens on every save during dev mode)
79
82
  document.getElementById(portalConfig.target).innerHTML = "";
80
- // add a click-listener to button, that creates a 3D-map on click
81
- document.getElementById("enable").addEventListener("click", function () {
82
- if (window.mpapi.map2D === null) {
83
- window.mpapi.map2D = window.mpapi.map;
84
- }
85
-
86
- if (window.mpapi.map.mapMode === "3D") {
87
- window.mpapi.map.setEnabled(false);
88
- window.mpapi.map = window.mpapi.map2D;
89
- window.mpapi.map.getView().setRotation(0);
90
- document.getElementById("layer-visibility").style.display = "none";
91
- }
92
- else {
93
- const lib = portalConfig.cesiumLib ? portalConfig.cesiumLib : "https://geoportal-hamburg.de/mastercode/cesium/1_99/index.js";
94
-
95
- document.getElementById("layer-visibility").style.display = "block";
96
-
97
- load3DScriptModule.load3DScript(lib, function Loaded3DCallback () {
98
- let tilesetLayer = null;
99
-
100
- const settings3D = {
101
- map2D: window.mpapi.map2D,
102
- // set some options to Cesium scene
103
- cesiumParameter: {
104
- fxaa: true,
105
- globe: {
106
- enableLighting: true,
107
- maximumScreenSpaceError: 2,
108
- tileCacheSize: 20
109
- }
110
- }
111
- },
112
- map3D = mapsAPI.map.createMap(settings3D, "3D"),
113
- rawLayerTerrain = rawLayerList.getLayerWhere({id: "4001"}),
114
- rawLayerTileset = rawLayerList.getLayerWhere({id: "4002"}),
115
- rawLayerEntities = rawLayerList.getLayerWhere({id: "4003"});
116
-
117
- window.mpapi.map = map3D;
118
- tilesetLayer = new mpapi.Tileset(rawLayerTileset, window.mpapi.map);
119
- tilesetLayer.setVisible(true, window.mpapi.map);
120
-
121
- // entities are 2 simple buildings in the park 'planten und blomen' near Tiergartenstraße
122
- mpapi.entities.createLayer(rawLayerEntities, window.mpapi.map);
123
- // mpapi.entities.setVisible(true, rawLayerEntities, window.mpapi.map);
124
-
125
- mpapi.terrain.createLayer(rawLayerTerrain, window.mpapi.map);
126
- mpapi.terrain.setVisible(true, rawLayerTerrain, window.mpapi.map);
127
-
128
- window.mpapi.map.setEnabled(true);
129
- });
130
- }
131
- });
132
-
133
- // add a click-listener to button, that hides background layer in 3d
134
- document.getElementById("layer-visibility").addEventListener("click", function () {
135
- map2D.getLayers().forEach(layer => {
136
- map2D.removeLayer(layer);
137
- });
138
- });
139
-
140
- map2D = mapsAPI.map.createMap(config, "2D", {errorCallback});
141
83
 
142
84
  //* geojson styling function call to override default styling and special wfs styling
143
85
  mpapi.geojson.setCustomStyles({
@@ -167,7 +109,6 @@ const styleWfs = function (feature, resolution) {
167
109
  };
168
110
 
169
111
  services.find(({id}) => id === "3001").style = styleWfs;
170
- // */
171
112
 
172
113
 
173
114
  // eslint-disable-next-line
@@ -187,6 +128,8 @@ const styleOaf = function (feature, resolution) {
187
128
  services.find(({id}) => id === "5001").style = styleOaf;
188
129
 
189
130
  //* SYNCHRONOUS EXAMPLE: layerConf is known
131
+ // /*
132
+ map2D = mapsAPI.map.createMap(config, "2D", {errorCallback});
190
133
  window.mpapi.map = map2D;
191
134
 
192
135
  ["2001", "2002", "1002", "3001", "5001"].forEach(id => window.mpapi.map.addLayer(id, {errorCallback}));
@@ -204,7 +147,8 @@ services
204
147
 
205
148
  // */
206
149
 
207
- /* ASYNCHRONOUS EXAMPLE 1: work with layerConf callback
150
+ //* ASYNCHRONOUS EXAMPLE 1: work with layerConf callback (for testing comment out SYNCHRONOUS EXAMPLE)
151
+ /*
208
152
  document.getElementById("enable").style.display = "none";
209
153
  mpapi.rawLayerList.initializeLayerList(hamburgServicesUrl,
210
154
  conf => {
@@ -213,49 +157,34 @@ mpapi.rawLayerList.initializeLayerList(hamburgServicesUrl,
213
157
  layerConf: conf,
214
158
  layers: null
215
159
  }, "2D");
216
- ["6357", "6074"].forEach(id => window.mpapi.map.addLayer(id));
160
+ ["23420", "6074"].forEach(id => window.mpapi.map.addLayer(id));
217
161
  });
218
- //*/
162
+ */
219
163
 
220
- /* ASYNCHRONOUS EXAMPLE 2: work with createMap callback
164
+ //* ASYNCHRONOUS EXAMPLE 2: work with createMap callback (for testing comment out SYNCHRONOUS EXAMPLE)
165
+ /*
221
166
  document.getElementById("enable").style.display = "none";
222
167
  window.mpapi.map = mapsAPI.map.createMap({
223
168
  ...portalConfig, layerConf: hamburgServicesUrl, layers: [
224
- {id: "6357"},
169
+ {id: "23420"},
225
170
  {id: "453", transparency: 50}
226
171
  ]}, "2D",
227
172
  {
228
173
  callback: () => ["6074"].forEach(id => window.mpapi.map.addLayer(id))
229
174
  });
230
- //*/
231
-
232
- /* SEARCH FUNCTION EXAMPLE
233
- // You may e.g. copy this code to the browser's console to run a search.
234
-
235
- window.mpapi.search("Eiffe", {
236
- map: window.mpapi.map,
237
- zoom: true,
238
- zoomToParams: {duration: 1000, maxZoom: 8},
239
- searchStreets: true
240
- }).then(x => console.log(x)).catch(e => console.error(e));
241
-
242
- window.mpapi.search("Mümmelmannsberg 72", {
243
- map: window.mpapi.map,
244
- zoom: true,
245
- zoomToParams: {duration: 1000, maxZoom: 8},
246
- searchAddress: true
247
- }).then(x => console.log(x)).catch(e => console.error(e));
175
+ */
248
176
 
249
- //*/
250
177
 
251
178
  /* VECTOR TILE EXAMPLE */
252
179
  /*
253
180
  document.getElementById("enable").style.display = "none";
254
- map2D.getLayers().forEach(layer => {
255
- map2D.removeLayer(layer);
181
+ window.mpapi.map = mapsAPI.map.createMap(config, "2D", {errorCallback});
182
+
183
+ window.mpapi.map.getLayers().forEach(layer => {
184
+ window.mpapi.map.removeLayer(layer);
256
185
  });
257
186
 
258
- const vtStyleUrl = "https://dev.adv-smart.de/styles/playground/masterportal_test1.json";
187
+ const vtStyleUrl = "https://test.geoportal-hamburg.de/vt/esri/resources/styles/root.json";
259
188
 
260
189
  fetch(vtStyleUrl)
261
190
  .then(response => response.json())
@@ -264,20 +193,105 @@ fetch(vtStyleUrl)
264
193
 
265
194
  mpapi.vectorTile.setStyle(vtLayer, style, vtStyleUrl);
266
195
  });
267
- //*/
196
+ */
268
197
 
269
198
  /* WMTS example */
270
199
  /*
271
- map2D.getLayers().forEach(layer => {
272
- map2D.removeLayer(layer);
200
+ window.mpapi.map = mapsAPI.map.createMap(config, "2D", {errorCallback});
201
+
202
+ window.mpapi.map.getLayers().forEach(layer => {
203
+ window.mpapi.map.removeLayer(layer);
273
204
  });
274
205
  window.mpapi.map.addLayer("7001");
275
206
  window.mpapi.map.addLayer("7002");
276
207
  window.mpapi.map.addLayer("7003");
277
- */
208
+ //*/
278
209
 
279
210
  /* VectorStyle example */
280
211
  // Example for using the vectorStyle that is now implemented in the masterportalAPI.
281
212
  // Apply style to layer "8172"
282
213
  // mirrors behavior of Masterportal styling
283
214
  getWfsStyleFunction();
215
+
216
+
217
+ /* SEARCH FUNCTION EXAMPLE
218
+ // You may e.g. copy this code to the browser's console to run a search.
219
+
220
+ window.mpapi.search("Eiffe", {
221
+ map: window.mpapi.map,
222
+ zoom: true,
223
+ zoomToParams: {duration: 1000, maxZoom: 8},
224
+ searchStreets: true
225
+ }).then(x => console.log(x)).catch(e => console.error(e));
226
+
227
+ window.mpapi.search("Mümmelmannsberg 72", {
228
+ map: window.mpapi.map,
229
+ zoom: true,
230
+ zoomToParams: {duration: 1000, maxZoom: 8},
231
+ searchAddress: true
232
+ }).then(x => console.log(x)).catch(e => console.error(e));
233
+
234
+ //*/
235
+
236
+
237
+ // Add 3D functionality to the example:
238
+
239
+ // add a click-listener to button, that creates a 3D-map on click
240
+ document.getElementById("enable").addEventListener("click", function () {
241
+ if (window.mpapi.map2D === null) {
242
+ window.mpapi.map2D = window.mpapi.map;
243
+ }
244
+
245
+ if (window.mpapi.map.mapMode === "3D") {
246
+ window.mpapi.map.setEnabled(false);
247
+ window.mpapi.map = window.mpapi.map2D;
248
+ window.mpapi.map.getView().setRotation(0);
249
+ document.getElementById("layer-visibility").style.display = "none";
250
+ }
251
+ else {
252
+ const lib = portalConfig.cesiumLib ? portalConfig.cesiumLib : "https://geoportal-hamburg.de/mastercode/cesium/1_99/index.js";
253
+
254
+ document.getElementById("layer-visibility").style.display = "block";
255
+
256
+ load3DScriptModule.load3DScript(lib, function Loaded3DCallback () {
257
+ let tilesetLayer = null;
258
+
259
+ const settings3D = {
260
+ map2D: window.mpapi.map2D,
261
+ // set some options to Cesium scene
262
+ cesiumParameter: {
263
+ fxaa: true,
264
+ globe: {
265
+ enableLighting: true,
266
+ maximumScreenSpaceError: 2,
267
+ tileCacheSize: 20
268
+ }
269
+ }
270
+ },
271
+ map3D = mapsAPI.map.createMap(settings3D, "3D"),
272
+ rawLayerTerrain = rawLayerList.getLayerWhere({id: "4001"}),
273
+ rawLayerTileset = rawLayerList.getLayerWhere({id: "4002"}),
274
+ rawLayerEntities = rawLayerList.getLayerWhere({id: "4003"});
275
+
276
+ window.mpapi.map = map3D;
277
+ tilesetLayer = new mpapi.Tileset(rawLayerTileset, window.mpapi.map);
278
+ tilesetLayer.setVisible(true, window.mpapi.map);
279
+
280
+ // entities are 2 simple buildings in the park 'planten und blomen' near Tiergartenstraße
281
+ mpapi.entities.createLayer(rawLayerEntities, window.mpapi.map);
282
+ // mpapi.entities.setVisible(true, rawLayerEntities, window.mpapi.map);
283
+
284
+ mpapi.terrain.createLayer(rawLayerTerrain, window.mpapi.map);
285
+ mpapi.terrain.setVisible(true, rawLayerTerrain, window.mpapi.map);
286
+
287
+ window.mpapi.map.setEnabled(true);
288
+ });
289
+ }
290
+ });
291
+
292
+ // add a click-listener to button, that hides background layer in 3d
293
+ document.getElementById("layer-visibility").addEventListener("click", function () {
294
+ map2D.getLayers().forEach(layer => {
295
+ map2D.removeLayer(layer);
296
+ });
297
+ });
package/jest.setup.js CHANGED
@@ -1,5 +1,20 @@
1
1
  import "regenerator-runtime/runtime";
2
2
 
3
+ class Worker {
4
+ constructor (stringUrl) {
5
+ this.url = stringUrl;
6
+ this.onmessage = () => {
7
+ // empty
8
+ };
9
+ }
10
+
11
+ postMessage (msg) {
12
+ this.onmessage(msg);
13
+ }
14
+ }
15
+ // a mock for web worker
16
+ window.Worker = Worker;
17
+
3
18
  window.URL.createObjectURL = function () {
4
19
  // empty
5
20
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@masterportal/masterportalapi",
3
3
  "author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
4
- "version": "2.19.2",
4
+ "version": "2.20.0",
5
5
  "license": "MIT",
6
6
  "description": "Basic functions of the Masterportal as api",
7
7
  "repository": {
@@ -21,7 +21,7 @@
21
21
  "dependencies": {
22
22
  "core-js": "^3.30.2",
23
23
  "dayjs": "^1.11.7",
24
- "ol": "7.3.0",
24
+ "ol": "7.4.0",
25
25
  "olcs": "^2.14.0",
26
26
  "proj4": "^2.9.0",
27
27
  "xml2js": "^0.5.0"
@@ -47,7 +47,7 @@
47
47
  "use-resize-observer": "^9.1.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "cesium": "^1.95.0"
50
+ "cesium": "^1.106.0"
51
51
  },
52
52
  "engines": {
53
53
  "node": "^16.13.2 || ^18.12.0",
package/src/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import {createMapView} from "./maps/mapView";
2
2
  import crs from "./crs";
3
+ import drawInteractions from "./maps/interactions/drawInteractions";
3
4
  import rawLayerList from "./rawLayerList";
4
5
  import * as wms from "./layer/wms";
5
6
  import wmts from "./layer/wmts";
@@ -36,5 +37,6 @@ export {
36
37
  ping,
37
38
  search,
38
39
  crs,
40
+ drawInteractions,
39
41
  webgl
40
42
  };
package/src/layer/wfs.js CHANGED
@@ -252,3 +252,22 @@ export function createLayer (rawLayer = {}, {layerParams = {}, options = {}} = {
252
252
  }
253
253
  return layer;
254
254
  }
255
+
256
+ /**
257
+ * Load the features manually.
258
+ * @param {Object} layerAttributes raw layer attributes.
259
+ * @param {module:ol/vector/Source} layerSource - the source of the layer
260
+ * @returns {void}
261
+ */
262
+ export function loadFeaturesManually (layerAttributes, layerSource) {
263
+ const getUrl = createUrl(layerAttributes, layerAttributes.version, {getCode: () => layerAttributes.crs}, "");
264
+
265
+ fetch(getUrl, layerSource)
266
+ .then(response => response.text())
267
+ .then(responseString => {
268
+ layerSource.addFeatures(layerSource.getFormat().readFeatures(responseString));
269
+ })
270
+ .catch(error => {
271
+ console.error(error);
272
+ });
273
+ }
@@ -0,0 +1,130 @@
1
+ import {createBox} from "ol/interaction/Draw.js";
2
+ import {Draw} from "ol/interaction.js";
3
+
4
+ const earthRadius = 6378137,
5
+ roh = 180 / Math.PI,
6
+ mappingDrawTypes = {
7
+ box: {
8
+ type: "Circle",
9
+ options: {
10
+ geometryFunction: createBox()
11
+ }
12
+ },
13
+ circle: {
14
+ type: "Circle"
15
+ },
16
+ doubleCircle: {
17
+ type: "Circle"
18
+ },
19
+ line: {
20
+ type: "LineString"
21
+ },
22
+ pen: {
23
+ type: "LineString",
24
+ options: {
25
+ freehand: true
26
+ }
27
+ },
28
+ point: {
29
+ type: "Point"
30
+ },
31
+ polygon: {
32
+ type: "Polygon"
33
+ }
34
+ };
35
+
36
+ /**
37
+ * Transform the radius to map projection unit.
38
+ * @param {Number} radius The radius.
39
+ * @param {Object} mapProjection The map projection.
40
+ * @returns {Number} The transformed radius.
41
+ */
42
+ function transformMapUnitRadius (radius, mapProjection) {
43
+ const unit = mapProjection.getUnits();
44
+ let mapUnitRadius;
45
+
46
+ if (unit === "m") {
47
+ mapUnitRadius = radius;
48
+ }
49
+ else if (unit === "degrees") {
50
+ mapUnitRadius = radius * roh / earthRadius;
51
+ }
52
+
53
+ return mapUnitRadius;
54
+ }
55
+
56
+ /**
57
+ * Create a feature for the outer circle of draw type: double circle.
58
+ * @param {ol/interaction/Draw} drawInteraction The draw interaction.
59
+ * @param {Object} mapProjection The map projection.
60
+ * @param {ol/source} source The vector layer source for draw features.
61
+ * @param {Object} [options={}] The options for drawing features.
62
+ * @param {Number} [options.circleOuterRadius] The radius for the outer circle.
63
+ * @returns {void}
64
+ */
65
+ function drawOuterCircle (drawInteraction, mapProjection, source, options = {}) {
66
+ drawInteraction.on("drawend", event => {
67
+ const outerCircleFeature = event.feature.clone(),
68
+ mapUnitOuterRadius = transformMapUnitRadius(options.circleOuterRadius, mapProjection);
69
+
70
+ outerCircleFeature.getGeometry().setRadius(mapUnitOuterRadius);
71
+ source.addFeature(outerCircleFeature);
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Create features for non-interactive circle or double circle.
77
+ * @param {ol/interaction/Draw} drawInteraction The draw interaction.
78
+ * @param {String} drawType The current draw type.
79
+ * @param {Object} mapProjection The map projection.
80
+ * @param {ol/source} source The vector layer source for draw features.
81
+ * @param {Object} [options={}] The options for drawing features.
82
+ * @param {Number} [options.circleInnerRadius] The radius for the inner circle.
83
+ * @param {Number} [options.circleOuterRadius] The radius for the outer circle.
84
+ * @param {Boolean} [options.interactiveCircle] Circle is drawn interactively or not.
85
+ * @returns {void}
86
+ */
87
+ function drawCircle (drawInteraction, drawType, mapProjection, source, options = {}) {
88
+ if (options.interactiveCircle === false && options.circleInnerRadius > 0) {
89
+ drawInteraction.on("drawstart", event => {
90
+ const mapUnitInnerRadius = transformMapUnitRadius(options.circleInnerRadius, mapProjection);
91
+
92
+ event.feature.getGeometry().setRadius(mapUnitInnerRadius);
93
+ drawInteraction.finishDrawing();
94
+ });
95
+
96
+ if (drawType === "doubleCircle" && options.circleOuterRadius > 0) {
97
+ drawOuterCircle(drawInteraction, mapProjection, source, options);
98
+ }
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Create the draw interaction.
104
+ * @param {String} drawType The current draw type.
105
+ * @param {ol/source} source The vector layer source for draw features.
106
+ * @returns {ol/interaction/Draw|null} The draw interaction.
107
+ */
108
+ function createDrawInteraction (drawType, source) {
109
+ let drawInteraction = null;
110
+
111
+ if (typeof mappingDrawTypes[drawType] === "object") {
112
+ const options = mappingDrawTypes[drawType].options || {};
113
+
114
+ drawInteraction = new Draw({
115
+ source: source,
116
+ type: mappingDrawTypes[drawType].type,
117
+ freehand: options.freehand,
118
+ geometryFunction: options.geometryFunction
119
+ });
120
+ }
121
+
122
+ return drawInteraction;
123
+ }
124
+
125
+ export default {
126
+ createDrawInteraction,
127
+ drawCircle,
128
+ drawOuterCircle,
129
+ transformMapUnitRadius
130
+ };
@@ -4,7 +4,7 @@ import setBackgroundImage from "../../lib/setBackgroundImage";
4
4
  import getInitialLayers from "../../lib/getInitialLayers";
5
5
  import defaults from "../../defaults";
6
6
  import * as wms from "../../layer/wms";
7
- import * as wmts from "../../layer/wmts";
7
+ import wmts from "../../layer/wmts";
8
8
  import * as geojson from "../../layer/geojson";
9
9
  import * as wfs from "../../layer/wfs";
10
10
  import * as vectorBase from "../../layer/vectorBase";
@@ -23,7 +23,7 @@ let mapIdCounter = 0;
23
23
  */
24
24
  const layerBuilderMap = {
25
25
  wms,
26
- wmts,
26
+ "wmts": wmts,
27
27
  wfs,
28
28
  geojson,
29
29
  vectorBase,
@@ -1,9 +1,9 @@
1
1
  import WebGLPointsLayer from "ol/layer/WebGLPoints";
2
2
  import WebGLVectorLayerRenderer from "ol/renderer/webgl/VectorLayer";
3
3
  import VectorLayer from "ol/layer/Layer";
4
- import {packColor} from "ol/renderer/webgl/shaders";
5
4
  import styleList from "../vectorStyle/styleList";
6
5
  import {getRulesForFeature} from "../vectorStyle/lib/getRuleForIndex";
6
+ import {returnColor} from "../vectorStyle/lib/colorConvertions";
7
7
 
8
8
  /**
9
9
  * The default style for OpenLayers WebGLPoints class
@@ -11,82 +11,26 @@ import {getRulesForFeature} from "../vectorStyle/lib/getRuleForIndex";
11
11
  * @private
12
12
  */
13
13
  const defaultStyle = {
14
- symbol: {
15
- symbolType: "circle",
16
- size: 20,
17
- color: "#006688",
18
- rotateWithView: false,
19
- offset: [0, 0],
20
- opacity: 0.6
21
- }
22
- };
23
-
24
- /**
25
- * parses the styling rules for the renderer
26
- * @static
27
- * @private
28
- * @returns {Object} the style options object with conditional functions
29
- */
30
- export function getRenderFunctions () {
31
- return {
32
- /**
33
- * Used for polygon fills
34
- * Reads the relevant properties from the Masterportal style object
35
- * @see https://bitbucket.org/geowerkstatt-hamburg/masterportal/src/dev/doc/style.json.md
36
- */
37
- fill: {
38
- attributes: {
39
- color: (feature) => {
40
- return packColor(feature.styleRule?.style.polygonFillColor || "#006688");
41
- },
42
- opacity: (feature) => {
43
- return typeof feature.styleRule?.style.polygonFillColor?.[3] === "number" ?
44
- feature.styleRule.style.polygonFillColor[3] : 1;
45
- }
46
- }
47
- },
48
- stroke: {
49
- /**
50
- * Used for polygon edges and lineStrings
51
- * Reads the relevant properties from the Masterportal style object
52
- * @see https://bitbucket.org/geowerkstatt-hamburg/masterportal/src/dev/doc/style.json.md
53
- */
54
- attributes: {
55
- color: (feature) => {
56
- return packColor(feature.styleRule?.style.polygonStrokeColor || "#006688");
57
- },
58
- width: (feature) => {
59
- return feature.styleRule?.style.polygonStrokeWidth || 1;
60
- },
61
- opacity: (feature) => {
62
- return typeof feature.styleRule?.style.polygonStrokeColor?.[3] === "number" ?
63
- feature.styleRule.style.polygonStrokeColor[3] : 1;
64
- }
65
- }
66
- },
67
- point: {
68
- /**
69
- * As of now, the generic VectorLayerRenderer only supports points rendered as quads
70
- * available attributes: color, size, opacity
71
- * Due to that, we use WebGLPoints Layer Class for point geom types
72
- * Reads the relevant properties from the Masterportal style object
73
- * @see https://bitbucket.org/geowerkstatt-hamburg/masterportal/src/dev/doc/style.json.md
74
- */
75
- attributes: {
76
- color: (feature) => {
77
- return packColor(feature.styleRule?.style.circleFillColor || "#006688");
78
- },
79
- size: (feature) => {
80
- return feature.styleRule?.style.circleRadius || 20;
81
- },
82
- opacity: (feature) => {
83
- return typeof feature.styleRule?.style.circleFillColor?.[3] === "number" ?
84
- feature.styleRule.style.circleFillColor[3] : 1;
85
- }
86
- }
14
+ symbol: {
15
+ symbolType: "circle",
16
+ size: 20,
17
+ color: "#006688",
18
+ rotateWithView: false,
19
+ offset: [0, 0],
20
+ opacity: 0.6
87
21
  }
22
+ },
23
+
24
+ /** @type {import('../src/ol/style/literal.js').LiteralStyle} */
25
+ style = {
26
+ "stroke-color": ["get", "STROKECOLOR"],
27
+ // NOTICE: does not work with ol 7.4.0, throws errors -> use 1 pixel width
28
+ // "stroke-width": ["get", "STROKEWIDTH"],
29
+ "stroke-width": 1,
30
+ "fill-color": ["get", "FILLCOLOR"],
31
+ "opacity": ["get", "OPACITY"],
32
+ "size": ["get", "CIRCLESIZE"]
88
33
  };
89
- }
90
34
 
91
35
  /**
92
36
  * Creates a layer object to extend from.
@@ -109,7 +53,9 @@ export function createVectorLayerRenderer () {
109
53
  * @experimental
110
54
  */
111
55
  createRenderer () {
112
- return new WebGLVectorLayerRenderer(this, getRenderFunctions());
56
+ return new WebGLVectorLayerRenderer(this, {
57
+ style
58
+ });
113
59
  }
114
60
  }
115
61
 
@@ -132,9 +78,24 @@ export function formatFeatureStyles (feature, styleObject) {
132
78
  // extract first matching rule only
133
79
  const rule = getRulesForFeature(styleObject, feature)[0];
134
80
 
135
- // don't set on properties to avoid GFI issues
136
81
  // undefined if no match
137
82
  feature.styleRule = rule;
83
+
84
+ if (rule && rule.style) {
85
+ // TODO set style on properties will be visible in GFI
86
+ const polygonFillColor = returnColor(rule.style.polygonFillColor, "hex"),
87
+ circleFillColor = returnColor(rule.style.circleFillColor, "hex"),
88
+ fillColor = polygonFillColor ? polygonFillColor : circleFillColor,
89
+ polygonStrokeColor = returnColor(rule.style.polygonStrokeColor, "hex"),
90
+ polygonStrokeWidth = rule.style.polygonStrokeWidth,
91
+ size = rule.style.circleRadius;
92
+
93
+ feature.set("FILLCOLOR", fillColor ? fillColor : "#006688");
94
+ feature.set("STROKECOLOR", polygonStrokeColor ? polygonStrokeColor : "#006688");
95
+ feature.set("STROKEWIDTH", polygonStrokeWidth ? polygonStrokeWidth : 1);
96
+ feature.set("OPACITY", polygonFillColor ? polygonFillColor[3] : 1);
97
+ feature.set("CIRCLESIZE", size ? size : 20);
98
+ }
138
99
  }
139
100
 
140
101
  /**
@@ -6,8 +6,7 @@ import LineStringStyle from "./styles/styleLine";
6
6
  import CesiumStyle from "./styles/styleCesium";
7
7
  import {getRuleForIndex, getRulesForFeature} from "./lib/getRuleForIndex";
8
8
 
9
- const legendsOfAllStyles = [],
10
- uniqueStyles = [];
9
+ const legendsOfAllStyles = [];
11
10
  let legendInformationLength = 0;
12
11
 
13
12
  /**
@@ -30,17 +29,13 @@ function isMultiGeometry (geometryType) {
30
29
  */
31
30
  function getSimpleGeometryStyle (geometryType, feature, rule, isClustered, wfsImgPathFromConfig) {
32
31
  const style = rule?.style,
33
- legendValue = style ? style.legendValue : null,
34
- alreadyExisitingStyle = uniqueStyles.find(element => element.featureStyle === style && element.geometryType === geometryType);
32
+ legendValue = style ? style.legendValue : null;
35
33
  let styleObject,
36
34
  styleObjectForLegend = null;
37
35
 
38
36
  feature.legendValue = legendValue ? legendValue : null;
39
37
 
40
- if (alreadyExisitingStyle) {
41
- styleObject = alreadyExisitingStyle.featureStyleObject;
42
- }
43
- else if (geometryType === "Point") {
38
+ if (geometryType === "Point") {
44
39
  styleObject = new PointStyle(feature, style, isClustered);
45
40
  if (isClustered) {
46
41
  styleObjectForLegend = new PointStyle(feature, style, false);
@@ -78,7 +73,6 @@ function getSimpleGeometryStyle (geometryType, feature, rule, isClustered, wfsIm
78
73
  styleObjectForLegend.initialize(feature, style, false, wfsImgPathFromConfig);
79
74
  styleObjectForLegend.legendValue = legendValue;
80
75
  }
81
- uniqueStyles.push({featureStyle: style, featureStyleObject: styleObject, geometryType});
82
76
  styleObject.initialize(feature, style, isClustered, wfsImgPathFromConfig);
83
77
  styleObject.addLegendInfo(geometryType, styleObjectForLegend === null ? styleObject : styleObjectForLegend, rule);
84
78
  styleObject.legendValue = legendValue;
@@ -122,6 +116,7 @@ function getMultiGeometryStyle (geometryType, feature, rules, isClustered, wfsIm
122
116
  console.warn("Multi encapsulated multiGeometries are not supported.");
123
117
  }
124
118
  else if (!simpleStyle.styleMultiGeomOnlyWithRule || rule) {
119
+ simpleStyle.getStyle()?.setGeometry(geometry);
125
120
  olStyle.push(simpleStyle);
126
121
  }
127
122
  });
@@ -136,7 +131,7 @@ function getMultiGeometryStyle (geometryType, feature, rules, isClustered, wfsIm
136
131
  else {
137
132
  const simpleStyle = getSimpleGeometryStyle(geometryType, feature, rules, isClustered, wfsImgPathFromConfig);
138
133
 
139
- simpleStyle.getStyle().setGeometry(geometryType);
134
+ simpleStyle.getStyle()?.setGeometry(geometryType);
140
135
  olStyle.push(simpleStyle);
141
136
  }
142
137
  return olStyle;
@@ -251,7 +246,7 @@ function createStyle (styleObject, feature, isClustered, wfsImgPathFromConfig) {
251
246
  captureLegendFromFeature(styleObject.styleId, legendInformation);
252
247
  }
253
248
  // label style is optional and depends on some fields
254
- if (isClustered || hasLabelField) {
249
+ if (styleObjectGeometry !== null && (isClustered || hasLabelField)) {
255
250
  if (Array.isArray(styleObjectGeometry)) {
256
251
  styleObjectGeometry[0].setText(getLabelStyle(feature, style, isClustered));
257
252
  }
@@ -38,14 +38,14 @@ class PointStyle extends StyleClass {
38
38
  this.setFeature(feature);
39
39
  this.setIsClustered(isClustered);
40
40
  this.overwriteStyling(styles);
41
- this.setStyle(this.getStyle());
41
+ this.setStyle(this.createStyle());
42
42
  }
43
43
 
44
44
  /**
45
45
  * This function returns a style for each feature.
46
46
  * @returns {ol/style} - The created style.
47
47
  */
48
- getStyle () {
48
+ createStyle () {
49
49
  if (this.nullStyle) {
50
50
  return null;
51
51
  }
@@ -28,14 +28,14 @@ class PolygonStyle extends StyleClass {
28
28
  this.setFeature(feature);
29
29
  this.setIsClustered(isClustered);
30
30
  this.overwriteStyling(styles);
31
- this.setStyle(this.getStyle());
31
+ this.setStyle(this.createStyle());
32
32
  }
33
33
 
34
34
  /**
35
35
  * This function returns a style for each feature.
36
36
  * @returns {ol/style} - The created style.
37
37
  */
38
- getStyle () {
38
+ createStyle () {
39
39
  if (this.nullStyle) {
40
40
  return null;
41
41
  }
@@ -35,6 +35,14 @@ class StyleClass {
35
35
  this.style = value;
36
36
  }
37
37
 
38
+ /**
39
+ * Getter for style.
40
+ * @returns {ol/style} - The style.
41
+ */
42
+ getStyle () {
43
+ return this.style;
44
+ }
45
+
38
46
  /*
39
47
  * setter for styles
40
48
  * @param {object} styles styles
@@ -22,14 +22,14 @@ class CesiumStyle extends StyleClass {
22
22
  initialize (rule) {
23
23
  this.overwriteStyling(rule.style);
24
24
  this.setConditions(rule.conditions);
25
- this.setStyle(this.getStyle());
25
+ this.setStyle(this.createStyle());
26
26
  }
27
27
 
28
28
  /**
29
29
  * This function returns a style for each feature.
30
30
  * @returns {ol/style} - The created style.
31
31
  */
32
- getStyle () {
32
+ createStyle () {
33
33
  return this.createCondition(this.get("conditions"), this.get("style"));
34
34
  }
35
35
 
@@ -26,14 +26,14 @@ class LineStringStyle extends StyleClass {
26
26
  this.setFeature(feature);
27
27
  this.setIsClustered(isClustered);
28
28
  this.overwriteStyling(styles);
29
- this.setStyle(this.getStyle());
29
+ this.setStyle(this.createStyle());
30
30
  }
31
31
 
32
32
  /**
33
33
  * This function returns a style for each feature.
34
34
  * @returns {ol/style/Style} - The created style.
35
35
  */
36
- getStyle () {
36
+ createStyle () {
37
37
  if (this.nullStyle) {
38
38
  return null;
39
39
  }
@@ -28,14 +28,14 @@ class TextStyle extends StyleClass {
28
28
  this.setFeature(feature);
29
29
  this.setIsClustered(isClustered);
30
30
  this.overwriteStyling(styles);
31
- this.setStyle(this.getStyle());
31
+ this.setStyle(this.createStyle());
32
32
  }
33
33
 
34
34
  /**
35
35
  * This function returns a style for each feature.
36
36
  * @returns {ol/style} - The created style.
37
37
  */
38
- getStyle () {
38
+ createStyle () {
39
39
  if (this.nullStyle) {
40
40
  return null;
41
41
  }
@@ -414,5 +414,57 @@ describe("wfs.js", function () {
414
414
  expect(webgl.afterLoading).toHaveBeenCalled();
415
415
  });
416
416
  });
417
+ describe("loadFeaturesManually", function () {
418
+ const consoleError = console.error;
419
+ let tick;
420
+
421
+ beforeEach(() => {
422
+ tick = () => {
423
+ return new Promise(resolve => {
424
+ setTimeout(resolve, 0);
425
+ });
426
+ };
427
+
428
+ if (global.fetch) {
429
+ global.fetch.mockClear();
430
+ }
431
+ });
432
+ // to reset show error on load in console
433
+ afterEach(() => {
434
+ console.error = consoleError;
435
+ });
436
+
437
+ it("load features manually", async function () {
438
+ global.fetch = jest.fn().mockImplementationOnce(() => {
439
+ return new Promise((resolve) => {
440
+ resolve({
441
+ ok: true,
442
+ status: 200,
443
+ text: () => {
444
+ return featureCollection;
445
+ }
446
+ });
447
+ });
448
+ });
449
+
450
+ const format = new WFS(),
451
+ source = new VectorSource({
452
+ format: format,
453
+ url: "https://url.de",
454
+ version: "1.1.0",
455
+ featureType: "krankenhaeuser_hh",
456
+ featureNS: "http://www.deegree.org/app"
457
+ }),
458
+ layerAttributes = {
459
+ crs: "EPSG:25832",
460
+ version: "1.1.0",
461
+ url: "https://url.de"
462
+ };
463
+
464
+ wfs.loadFeaturesManually(layerAttributes, source);
465
+ await tick();
466
+ expect(source.getFeatures()).toHaveLength(1);
467
+ });
468
+ });
417
469
  });
418
470
 
@@ -0,0 +1,50 @@
1
+ import {Draw} from "ol/interaction.js";
2
+ import VectorSource from "ol/source/Vector";
3
+
4
+ import drawInteractions from "../../../src/maps/interactions/drawInteractions";
5
+
6
+ describe("src/maps/interactions/drawInteractions.js", () => {
7
+ describe("createDrawInteraction", () => {
8
+ it("should create a draw interaction", () => {
9
+ const source = new VectorSource(),
10
+ drawType = "pen",
11
+ drawInteraction = drawInteractions.createDrawInteraction(drawType, source);
12
+
13
+ expect(drawInteraction).not.toBeUndefined();
14
+ expect(drawInteraction).not.toBeNull();
15
+ expect(drawInteraction).toBeInstanceOf(Draw);
16
+ });
17
+
18
+ it("should return null, if drawType is not supported", () => {
19
+ const source = new VectorSource(),
20
+ drawType = "abc",
21
+ drawInteraction = drawInteractions.createDrawInteraction(drawType, source);
22
+
23
+ expect(drawInteraction).not.toBeUndefined();
24
+ expect(drawInteraction).toBeNull();
25
+ expect(drawInteraction).not.toBeInstanceOf(Draw);
26
+ });
27
+ });
28
+
29
+ describe("transformMapUnitRadius", () => {
30
+ it("should return the input meter radius in meter ", () => {
31
+ const radius = 100,
32
+ mapProjection = {
33
+ getUnits: () => "m"
34
+ },
35
+ mapUnitRadius = drawInteractions.transformMapUnitRadius(radius, mapProjection);
36
+
37
+ expect(mapUnitRadius).toEqual(100);
38
+ });
39
+
40
+ it("should return the input degree radius in meter ", () => {
41
+ const radius = 100,
42
+ mapProjection = {
43
+ getUnits: () => "degrees"
44
+ },
45
+ mapUnitRadius = drawInteractions.transformMapUnitRadius(radius, mapProjection);
46
+
47
+ expect(mapUnitRadius).toEqual(0.0008983152841195215);
48
+ });
49
+ });
50
+ });
@@ -4,7 +4,6 @@ import Polygon from "ol/geom/Polygon";
4
4
  import * as webgl from "../../src/renderer/webgl";
5
5
  import WebGLPointsLayer from "ol/layer/WebGLPoints";
6
6
  import Layer from "ol/layer/Layer";
7
- import {packColor} from "ol/renderer/webgl/shaders";
8
7
  import styleList from "../../src/vectorStyle/styleList";
9
8
 
10
9
  describe("webgl.js", () => {
@@ -108,54 +107,5 @@ describe("webgl.js", () => {
108
107
  expect($feature.styleRule).toEqual(styleRule);
109
108
  });
110
109
  });
111
- describe("getRenderFunctions", () => {
112
- it("should read the style from styleRule and pack them to single float", () => {
113
- const renderFunctions = webgl.getRenderFunctions();
114
-
115
- $feature = feature.clone();
116
- webgl.formatFeatureStyles($feature, styleObject);
117
- expect(renderFunctions.fill.attributes.color($feature)).toEqual(packColor(styleRule.style.polygonFillColor));
118
- expect(renderFunctions.fill.attributes.opacity($feature)).toEqual(styleRule.style.polygonFillColor[3]);
119
- expect(renderFunctions.stroke.attributes.color($feature)).toEqual(packColor(styleRule.style.polygonStrokeColor));
120
- expect(renderFunctions.stroke.attributes.width($feature)).toEqual(styleRule.style.polygonStrokeWidth);
121
- expect(renderFunctions.stroke.attributes.opacity($feature)).toEqual(styleRule.style.polygonStrokeColor[3]);
122
- expect(renderFunctions.point.attributes.color($feature)).toEqual(packColor(styleRule.style.circleFillColor));
123
- expect(renderFunctions.point.attributes.size($feature)).toEqual(styleRule.style.circleRadius);
124
- expect(renderFunctions.point.attributes.opacity($feature)).toEqual(styleRule.style.circleFillColor[3]);
125
- });
126
- it("should return default values if style is empty, i.e. \"default\" style", () => {
127
- const renderFunctions = webgl.getRenderFunctions();
128
-
129
- styleObject = {
130
- rules: [{
131
- style: {}
132
- }]
133
- };
134
- $feature = feature.clone();
135
- webgl.formatFeatureStyles($feature, styleObject);
136
- expect(typeof renderFunctions.fill.attributes.color($feature)).toEqual("number");
137
- expect(typeof renderFunctions.fill.attributes.opacity($feature)).toEqual("number");
138
- expect(typeof renderFunctions.stroke.attributes.color($feature)).toEqual("number");
139
- expect(typeof renderFunctions.stroke.attributes.width($feature)).toEqual("number");
140
- expect(typeof renderFunctions.stroke.attributes.opacity($feature)).toEqual("number");
141
- expect(typeof renderFunctions.point.attributes.color($feature)).toEqual("number");
142
- expect(typeof renderFunctions.point.attributes.size($feature)).toEqual("number");
143
- expect(typeof renderFunctions.point.attributes.opacity($feature)).toEqual("number");
144
- });
145
- it("should return default values if no style rule is found", () => {
146
- const renderFunctions = webgl.getRenderFunctions();
147
-
148
- $feature = feature.clone();
149
- expect(feature.styleRule).toBeUndefined();
150
- expect(typeof renderFunctions.fill.attributes.color($feature)).toEqual("number");
151
- expect(typeof renderFunctions.fill.attributes.opacity($feature)).toEqual("number");
152
- expect(typeof renderFunctions.stroke.attributes.color($feature)).toEqual("number");
153
- expect(typeof renderFunctions.stroke.attributes.width($feature)).toEqual("number");
154
- expect(typeof renderFunctions.stroke.attributes.opacity($feature)).toEqual("number");
155
- expect(typeof renderFunctions.point.attributes.color($feature)).toEqual("number");
156
- expect(typeof renderFunctions.point.attributes.size($feature)).toEqual("number");
157
- expect(typeof renderFunctions.point.attributes.opacity($feature)).toEqual("number");
158
- });
159
- });
160
110
  });
161
111
  });
@@ -27,8 +27,11 @@ describe("stylePoint", () => {
27
27
  expect(typeof stylePointClass.setSize).toBe("function");
28
28
  });
29
29
  });
30
- describe("getStyle", function () {
30
+ describe("createStyle", function () {
31
31
  it("returns an instance of openlayers style", () => {
32
+ const createdStyle = stylePointClass.createStyle();
33
+
34
+ stylePointClass.setStyle(createdStyle);
32
35
  expect(stylePointClass.getStyle()).toBeInstanceOf(Style);
33
36
  });
34
37
  it("returns an instance of openlayers circleStyle", () => {
@@ -39,6 +42,9 @@ describe("stylePoint", () => {
39
42
  legendValue: "Krankenhaus",
40
43
  imageName: "krankenhaus.png"
41
44
  };
45
+ const createdStyle = stylePointClass.createStyle();
46
+
47
+ stylePointClass.setStyle(createdStyle);
42
48
 
43
49
  expect(stylePointClass.getStyle()).toBeInstanceOf(Style);
44
50
  expect(stylePointClass.getStyle().getImage()).toBeInstanceOf(CircleStyle);
@@ -15,8 +15,11 @@ describe("stylePolygon", () => {
15
15
  isClustered = false,
16
16
  stylePolygonClass = new PolygonStyle(feature, style, isClustered);
17
17
 
18
- describe("getStyle", function () {
18
+ describe("createStyle", function () {
19
19
  it("returns an instance of openlayers style", () => {
20
+ const createdStyle = stylePolygonClass.createStyle();
21
+
22
+ stylePolygonClass.setStyle(createdStyle);
20
23
  expect(stylePolygonClass.getStyle()).toBeInstanceOf(Style);
21
24
  });
22
25
  });
@@ -21,8 +21,11 @@ describe("styleLine", () => {
21
21
  });
22
22
  });
23
23
 
24
- describe("getStyle", function () {
24
+ describe("createStyle", function () {
25
25
  it("returns an instance of openlayers style", () => {
26
+ const createdStyle = styleLineClass.createStyle();
27
+
28
+ styleLineClass.setStyle(createdStyle);
26
29
  expect(styleLineClass.getStyle()).toBeInstanceOf(Style);
27
30
  });
28
31
  });