@masterportal/masterportalapi 2.20.0 → 2.21.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,7 +3,17 @@
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
6
+ ## 2.21.0 - 2023-07-20
7
+ ### Added
8
+ - VectorStyle: Add Styling rules for Geoemtries of type `Circle`.
9
+ - Add Styling and zIndex to draw interactions and improve the draw behavior.
10
+
11
+ ### Changed
12
+ - Changed peerDependency from cesium 1.106.0 to @cesium/engine 2.4.1.
13
+
14
+ ---
15
+
16
+ ## 2.20.0 - 2023-06-30
7
17
  ### Added
8
18
  - Add draw interaction for interactive and static geometry types.
9
19
  - WFS: Added function to load wfs features manually.
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.20.0",
4
+ "version": "2.21.0",
5
5
  "license": "MIT",
6
6
  "description": "Basic functions of the Masterportal as api",
7
7
  "repository": {
@@ -47,7 +47,7 @@
47
47
  "use-resize-observer": "^9.1.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "cesium": "^1.106.0"
50
+ "@cesium/engine": "^2.4.1"
51
51
  },
52
52
  "engines": {
53
53
  "node": "^16.13.2 || ^18.12.0",
package/src/layer/wfs.js CHANGED
@@ -202,9 +202,16 @@ export function createLayerSource (rawLayer, options = {}) {
202
202
  return createClusterVectorSource(source, rawLayer.clusterDistance, options.clusterGeometryFunction);
203
203
  }
204
204
  if (rawLayer.renderer === "webgl") {
205
- source.once("featuresloadend", event => {
206
- webgl.afterLoading(event?.features, rawLayer.styleId, rawLayer.excludeTypesFromParsing);
207
- });
205
+ if (options.loadingStrategy === bbox) {
206
+ source.on("featuresloadend", event => {
207
+ webgl.afterLoading(event?.features, rawLayer.styleId, rawLayer.excludeTypesFromParsing);
208
+ });
209
+ }
210
+ else {
211
+ source.once("featuresloadend", event => {
212
+ webgl.afterLoading(event?.features, rawLayer.styleId, rawLayer.excludeTypesFromParsing);
213
+ });
214
+ }
208
215
  }
209
216
  return source;
210
217
  }
@@ -1,6 +1,8 @@
1
1
  import {createBox} from "ol/interaction/Draw.js";
2
2
  import {Draw} from "ol/interaction.js";
3
3
 
4
+ import createStyle from "../../vectorStyle/createStyle";
5
+
4
6
  const earthRadius = 6378137,
5
7
  roh = 180 / Math.PI,
6
8
  mappingDrawTypes = {
@@ -32,6 +34,9 @@ const earthRadius = 6378137,
32
34
  type: "Polygon"
33
35
  }
34
36
  };
37
+ let styleObject = null,
38
+ styleObjectOuterCircle = null,
39
+ zIndex = 0;
35
40
 
36
41
  /**
37
42
  * Transform the radius to map projection unit.
@@ -55,21 +60,44 @@ function transformMapUnitRadius (radius, mapProjection) {
55
60
 
56
61
  /**
57
62
  * Create a feature for the outer circle of draw type: double circle.
58
- * @param {ol/interaction/Draw} drawInteraction The draw interaction.
63
+ * @param {ol/feature} feature The ol feature.
59
64
  * @param {Object} mapProjection The map projection.
60
65
  * @param {ol/source} source The vector layer source for draw features.
61
66
  * @param {Object} [options={}] The options for drawing features.
62
- * @param {Number} [options.circleOuterRadius] The radius for the outer circle.
67
+ * @param {Number} [options.innerRadius] The radius for the inner circle.
68
+ * @param {Number} [options.outerRadius] The radius for the outer circle.
63
69
  * @returns {void}
64
70
  */
65
- function drawOuterCircle (drawInteraction, mapProjection, source, options = {}) {
66
- drawInteraction.on("drawend", event => {
67
- const outerCircleFeature = event.feature.clone(),
68
- mapUnitOuterRadius = transformMapUnitRadius(options.circleOuterRadius, mapProjection);
71
+ function drawOuterCircle (feature, mapProjection, source, options = {}) {
72
+ const innerCircleFeature = feature.clone(),
73
+ mapUnitInnerRadius = transformMapUnitRadius(options.innerRadius, mapProjection),
74
+ mapUnitOuterRadius = transformMapUnitRadius(options.outerRadius, mapProjection),
75
+ innerStyle = createStyle.createStyle(styleObject, innerCircleFeature, false),
76
+ outerStyle = createStyle.createStyle(styleObjectOuterCircle, feature, false);
69
77
 
70
- outerCircleFeature.getGeometry().setRadius(mapUnitOuterRadius);
71
- source.addFeature(outerCircleFeature);
72
- });
78
+ outerStyle.setZIndex(zIndex++);
79
+ feature.setStyle(outerStyle);
80
+ feature.getGeometry().setRadius(mapUnitOuterRadius);
81
+
82
+ innerStyle.setZIndex(zIndex++);
83
+ innerCircleFeature.setStyle(innerStyle);
84
+ innerCircleFeature.getGeometry().setRadius(mapUnitInnerRadius);
85
+
86
+ source.addFeature(innerCircleFeature);
87
+ }
88
+
89
+ /**
90
+ * Create a feature for the (inner) circle of draw type: circle or double circle.
91
+ * @param {ol/feature} feature The ol feature.vb
92
+ * @param {Object} mapProjection The map projection.
93
+ * @param {Object} [options={}] The options for drawing features.
94
+ * @param {Number} [options.innerRadius] The radius for the (inner) circle.
95
+ * @returns {void}
96
+ */
97
+ function drawInnerCircle (feature, mapProjection, options = {}) {
98
+ const mapUnitInnerRadius = transformMapUnitRadius(options.innerRadius, mapProjection);
99
+
100
+ feature.getGeometry().setRadius(mapUnitInnerRadius);
73
101
  }
74
102
 
75
103
  /**
@@ -79,26 +107,74 @@ function drawOuterCircle (drawInteraction, mapProjection, source, options = {})
79
107
  * @param {Object} mapProjection The map projection.
80
108
  * @param {ol/source} source The vector layer source for draw features.
81
109
  * @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.
110
+ * @param {Number} [options.innerRadius] The radius for the inner circle.
111
+ * @param {Boolean} [options.interactive] Circle is drawn interactively or not.
112
+ * @param {Number} [options.outerRadius] The radius for the outer circle.
85
113
  * @returns {void}
86
114
  */
87
115
  function drawCircle (drawInteraction, drawType, mapProjection, source, options = {}) {
88
- if (options.interactiveCircle === false && options.circleInnerRadius > 0) {
116
+ if ((drawType === "doubleCircle" || options.interactive === false) && options.innerRadius > 0) {
89
117
  drawInteraction.on("drawstart", event => {
90
- const mapUnitInnerRadius = transformMapUnitRadius(options.circleInnerRadius, mapProjection);
91
-
92
- event.feature.getGeometry().setRadius(mapUnitInnerRadius);
118
+ if (drawType === "circle") {
119
+ drawInnerCircle(event.feature, mapProjection, options);
120
+ }
121
+ else if (drawType === "doubleCircle" && options.outerRadius > 0) {
122
+ drawOuterCircle(event.feature, mapProjection, source, options);
123
+ }
93
124
  drawInteraction.finishDrawing();
94
125
  });
126
+ }
127
+ }
95
128
 
96
- if (drawType === "doubleCircle" && options.circleOuterRadius > 0) {
97
- drawOuterCircle(drawInteraction, mapProjection, source, options);
98
- }
129
+ /**
130
+ * Creates a styleObject from vectorStyling from layout.
131
+ * @param {Object} currentLayout The current layout.
132
+ * @param {Boolean} [outerCircle=false] Indicates if the styling is for the outer circle.
133
+ * @returns {void}
134
+ */
135
+ function setStyleObject (currentLayout, outerCircle = false) {
136
+ const fillOpacity = 1 - (currentLayout.fillTransparency / 100),
137
+ fillColorRgba = [...currentLayout.fillColor, fillOpacity],
138
+ style = {
139
+ rules: [
140
+ {
141
+ style: {
142
+ circleFillColor: fillColorRgba,
143
+ circleStrokeColor: currentLayout.strokeColor,
144
+ circleStrokeWidth: currentLayout.strokeWidth,
145
+ lineStrokeColor: currentLayout.strokeColor,
146
+ lineStrokeWidth: currentLayout.strokeWidth,
147
+ polygonFillColor: fillColorRgba,
148
+ polygonStrokeColor: currentLayout.strokeColor,
149
+ polygonStrokeWidth: currentLayout.strokeWidth
150
+ }
151
+ }
152
+ ]
153
+ };
154
+
155
+ if (outerCircle === true) {
156
+ styleObjectOuterCircle = style;
157
+ }
158
+ else {
159
+ styleObject = style;
99
160
  }
100
161
  }
101
162
 
163
+ /**
164
+ * Sets the style to overlay and feature.
165
+ * @param {ol/interaction/Draw} drawInteraction The draw interaction.
166
+ * @returns {void}
167
+ */
168
+ function setStyleToDrawInteraction (drawInteraction) {
169
+ drawInteraction.on("drawstart", event => {
170
+ const style = createStyle.createStyle(styleObject, event.feature, false);
171
+
172
+ style.setZIndex(zIndex++);
173
+ drawInteraction.getOverlay().setStyle(style);
174
+ event.feature.setStyle(style);
175
+ });
176
+ }
177
+
102
178
  /**
103
179
  * Create the draw interaction.
104
180
  * @param {String} drawType The current draw type.
@@ -112,19 +188,27 @@ function createDrawInteraction (drawType, source) {
112
188
  const options = mappingDrawTypes[drawType].options || {};
113
189
 
114
190
  drawInteraction = new Draw({
115
- source: source,
116
- type: mappingDrawTypes[drawType].type,
117
191
  freehand: options.freehand,
118
- geometryFunction: options.geometryFunction
192
+ geometryFunction: options.geometryFunction,
193
+ source: source,
194
+ type: mappingDrawTypes[drawType].type
119
195
  });
196
+
197
+ if (styleObject !== null && drawType !== "doubleCircle") {
198
+ setStyleToDrawInteraction(drawInteraction);
199
+ }
120
200
  }
121
201
 
122
202
  return drawInteraction;
123
203
  }
124
204
 
205
+ export {styleObject};
206
+
125
207
  export default {
126
208
  createDrawInteraction,
127
209
  drawCircle,
210
+ drawInnerCircle,
128
211
  drawOuterCircle,
212
+ setStyleObject,
129
213
  transformMapUnitRadius
130
214
  };
@@ -21,15 +21,13 @@ const defaultStyle = {
21
21
  }
22
22
  },
23
23
 
24
- /** @type {import('../src/ol/style/literal.js').LiteralStyle} */
24
+ /** @type {import('ol/style/literal.js').LiteralStyle} */
25
25
  style = {
26
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,
27
+ "stroke-width": ["get", "STROKEWIDTH", "number"],
30
28
  "fill-color": ["get", "FILLCOLOR"],
31
- "opacity": ["get", "OPACITY"],
32
- "size": ["get", "CIRCLESIZE"]
29
+ "opacity": ["get", "OPACITY", "number"],
30
+ "size": ["get", "CIRCLESIZE", "number"]
33
31
  };
34
32
 
35
33
  /**
@@ -82,18 +80,17 @@ export function formatFeatureStyles (feature, styleObject) {
82
80
  feature.styleRule = rule;
83
81
 
84
82
  if (rule && rule.style) {
85
- // TODO set style on properties will be visible in GFI
86
83
  const polygonFillColor = returnColor(rule.style.polygonFillColor, "hex"),
87
84
  circleFillColor = returnColor(rule.style.circleFillColor, "hex"),
88
85
  fillColor = polygonFillColor ? polygonFillColor : circleFillColor,
89
- polygonStrokeColor = returnColor(rule.style.polygonStrokeColor, "hex"),
90
- polygonStrokeWidth = rule.style.polygonStrokeWidth,
86
+ strokeColor = returnColor(rule.style.polygonStrokeColor || rule.style.lineStrokeColor, "hex"),
87
+ strokeWidth = rule.style.polygonStrokeWidth || rule.style.lineStrokeWidth,
91
88
  size = rule.style.circleRadius;
92
89
 
93
90
  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);
91
+ feature.set("STROKECOLOR", strokeColor ? strokeColor : "#006688");
92
+ feature.set("STROKEWIDTH", strokeWidth ? strokeWidth : 1);
93
+ feature.set("OPACITY", fillColor ? (rule.style.polygonFillColor || rule.style.circleFillColor)[3] : 1);
97
94
  feature.set("CIRCLESIZE", size ? size : 20);
98
95
  }
99
96
  }
@@ -3,6 +3,7 @@ import PointStyle from "./styles/point/stylePoint";
3
3
  import TextStyle from "./styles/styleText";
4
4
  import PolygonStyle from "./styles/polygon/stylePolygon";
5
5
  import LineStringStyle from "./styles/styleLine";
6
+ import CircleStyle from "./styles/styleCircle";
6
7
  import CesiumStyle from "./styles/styleCesium";
7
8
  import {getRuleForIndex, getRulesForFeature} from "./lib/getRuleForIndex";
8
9
 
@@ -60,7 +61,13 @@ function getSimpleGeometryStyle (geometryType, feature, rule, isClustered, wfsIm
60
61
  styleObject.legendValue = legendValue;
61
62
  return styleObject;
62
63
  }
63
- else if (geometryType === "LinearRing" || geometryType === "Circle") {
64
+ else if (geometryType === "Circle") {
65
+ styleObject = new CircleStyle(feature, style, isClustered);
66
+ if (isClustered) {
67
+ styleObjectForLegend = new CircleStyle(feature, style, false);
68
+ }
69
+ }
70
+ else if (geometryType === "LinearRing") {
64
71
  console.warn("Geometry type not implemented: " + geometryType + " default style ist used for feature " + feature);
65
72
  return new Style();
66
73
  }
@@ -0,0 +1,61 @@
1
+ import StyleClass from "./style";
2
+ import {Circle, Fill, Stroke, Style} from "ol/style.js";
3
+ import defaultStyle from "./defaultStyles";
4
+
5
+ class CircleStyle extends StyleClass {
6
+ /**
7
+ * @description Class to create ol.style.Style
8
+ * @constructor
9
+ * @class CircleStyle
10
+ * @extends StyleClass
11
+ * @memberof VectorStyle.Style
12
+ */
13
+ constructor () {
14
+ super();
15
+ this.attributes = {...defaultStyle.circle};
16
+ }
17
+
18
+ /**
19
+ * This function initializes the Linestring Object by setting or overwriting some attributes.
20
+ * @param {ol/feature} feature Feature to be styled.
21
+ * @param {object} styles styling properties to overwrite defaults
22
+ * @param {Boolean} isClustered Flag to show if feature is clustered.
23
+ * @returns {void}
24
+ */
25
+ initialize (feature, styles, isClustered) {
26
+ this.setFeature(feature);
27
+ this.setIsClustered(isClustered);
28
+ this.overwriteStyling(styles);
29
+ this.setStyle(this.createStyle());
30
+ }
31
+
32
+ /**
33
+ * This function returns a style for each feature.
34
+ * @returns {ol/style/Style} - The created style.
35
+ */
36
+ createStyle () {
37
+ if (this.nullStyle) {
38
+ return null;
39
+ }
40
+
41
+ const fill = new Fill({
42
+ color: this.attributes.circleFillColor
43
+ }),
44
+ stroke = new Stroke({
45
+ color: this.attributes.circleStrokeColor,
46
+ width: this.attributes.circleStrokeWidth
47
+ });
48
+
49
+ return new Style({
50
+ image: new Circle({
51
+ fill: fill,
52
+ stroke: stroke,
53
+ radius: 0
54
+ }),
55
+ fill: fill,
56
+ stroke: stroke
57
+ });
58
+ }
59
+ }
60
+
61
+ export default CircleStyle;
@@ -1,9 +1,103 @@
1
1
  import {Draw} from "ol/interaction.js";
2
+ import Feature from "ol/Feature";
3
+ import Circle from "ol/geom/Circle";
2
4
  import VectorSource from "ol/source/Vector";
3
5
 
4
- import drawInteractions from "../../../src/maps/interactions/drawInteractions";
6
+ import drawInteractions, {styleObject} from "../../../src/maps/interactions/drawInteractions";
5
7
 
6
8
  describe("src/maps/interactions/drawInteractions.js", () => {
9
+ describe("transformMapUnitRadius", () => {
10
+ it("should return the input meter radius in meter ", () => {
11
+ const radius = 100,
12
+ mapProjection = {
13
+ getUnits: () => "m"
14
+ },
15
+ mapUnitRadius = drawInteractions.transformMapUnitRadius(radius, mapProjection);
16
+
17
+ expect(mapUnitRadius).toEqual(100);
18
+ });
19
+
20
+ it("should return the input degree radius in meter ", () => {
21
+ const radius = 100,
22
+ mapProjection = {
23
+ getUnits: () => "degrees"
24
+ },
25
+ mapUnitRadius = drawInteractions.transformMapUnitRadius(radius, mapProjection);
26
+
27
+ expect(mapUnitRadius).toEqual(0.0008983152841195215);
28
+ });
29
+ });
30
+
31
+ describe("drawInnerCircle", () => {
32
+ it("should set radius for circle feature", () => {
33
+ const feature = new Feature({geometry: new Circle([565826.38, 5934174.40], 10)}),
34
+ mapProjection = {
35
+ getUnits: () => "m"
36
+ },
37
+ options = {
38
+ innerRadius: 100,
39
+ interactive: false,
40
+ outerRadius: 500
41
+ };
42
+
43
+ drawInteractions.drawInnerCircle(feature, mapProjection, options);
44
+
45
+ expect(feature.getGeometry().getRadius()).toEqual(100);
46
+ });
47
+ });
48
+
49
+ describe("setStyleObject", () => {
50
+ it("should set style object", () => {
51
+ const currentLayout = {
52
+ fillColor: [55, 126, 184],
53
+ fillTransparency: 0,
54
+ strokeColor: [0, 0, 0],
55
+ strokeWidth: 1
56
+ };
57
+
58
+ drawInteractions.setStyleObject(currentLayout);
59
+
60
+ expect(styleObject).toEqual({
61
+ rules: [
62
+ {
63
+ style: {
64
+ circleFillColor: [
65
+ 55,
66
+ 126,
67
+ 184,
68
+ 1
69
+ ],
70
+ circleStrokeColor: [
71
+ 0,
72
+ 0,
73
+ 0
74
+ ],
75
+ circleStrokeWidth: 1,
76
+ lineStrokeColor: [
77
+ 0,
78
+ 0,
79
+ 0
80
+ ],
81
+ lineStrokeWidth: 1,
82
+ polygonFillColor: [
83
+ 55,
84
+ 126,
85
+ 184,
86
+ 1
87
+ ],
88
+ polygonStrokeColor: [
89
+ 0,
90
+ 0,
91
+ 0
92
+ ],
93
+ polygonStrokeWidth: 1
94
+ }
95
+ }
96
+ ]
97
+ });
98
+ });
99
+ });
100
+
7
101
  describe("createDrawInteraction", () => {
8
102
  it("should create a draw interaction", () => {
9
103
  const source = new VectorSource(),
@@ -26,25 +120,4 @@ describe("src/maps/interactions/drawInteractions.js", () => {
26
120
  });
27
121
  });
28
122
 
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
123
  });
@@ -0,0 +1,31 @@
1
+ import CircleStyle from "../../../src/vectorStyle/styles/styleCircle";
2
+ import {Style} from "ol/style.js";
3
+
4
+ describe("styleCircle", () => {
5
+ const feature = {
6
+ geometryName: "geom",
7
+ id: "DE.HH.UP_GESUNDHEIT_KRANKENHAEUSER_2"
8
+ },
9
+ style = {
10
+ type: "icon",
11
+ legendValue: "Krankenhaus",
12
+ imageName: "krankenhaus.png"
13
+ },
14
+ isClustered = false,
15
+ styleCircleClass = new CircleStyle(feature, style, isClustered);
16
+
17
+ describe("initialize", function () {
18
+ it("returns an instance of openlayers style", () => {
19
+ expect(typeof styleCircleClass.initialize).toBe("function");
20
+ });
21
+ });
22
+
23
+ describe("createStyle", function () {
24
+ it("returns an instance of openlayers style", () => {
25
+ const createdStyle = styleCircleClass.createStyle();
26
+
27
+ styleCircleClass.setStyle(createdStyle);
28
+ expect(styleCircleClass.getStyle()).toBeInstanceOf(Style);
29
+ });
30
+ });
31
+ });