@masterportal/masterportalapi 2.20.0 → 2.22.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 +33 -1
- package/package.json +3 -2
- package/src/index.js +1 -1
- package/src/layer/wfs.js +236 -8
- package/src/maps/interactions/drawInteractions.js +106 -22
- package/src/maps/ol/olMap.js +1 -1
- package/src/renderer/webgl.js +9 -12
- package/src/vectorStyle/createStyle.js +8 -1
- package/src/vectorStyle/styles/styleCircle.js +61 -0
- package/test/layer/wfs.test.js +633 -14
- package/test/maps/interactions/drawInteractions.test.js +95 -22
- package/test/vectorStyle/styles/styleCircle.test.js +31 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,39 @@
|
|
|
3
3
|
|
|
4
4
|
The [Semantic Versioning](https://semver.org/spec/v2.0.0.html) is used.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Unreleased - in development
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
### Deprecated
|
|
12
|
+
|
|
13
|
+
### Removed
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
## 2.22.0 - 2023-07-25
|
|
20
|
+
### Added
|
|
21
|
+
- VectorStyle: Add Styling rules for Geoemtries of type `Circle`.
|
|
22
|
+
- Add Styling and zIndex to draw interactions and improve the draw behavior.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- Changed peerDependency from cesium 1.106.0 to @cesium/engine 2.4.1.
|
|
26
|
+
- WFS:
|
|
27
|
+
- Migrated writeTransaction and sendTransaction from masterportal the masterportalAPI.
|
|
28
|
+
- Exports in src/layer/wfs.js changed to export default {} to provide ES-Syntax.
|
|
29
|
+
### Deprecated
|
|
30
|
+
|
|
31
|
+
### Removed
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- WFS: fixed a bug that prevented parsing GeoServer responses.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2.20.0 - 2023-06-30
|
|
7
39
|
### Added
|
|
8
40
|
- Add draw interaction for interactive and static geometry types.
|
|
9
41
|
- 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.
|
|
4
|
+
"version": "2.22.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Basic functions of the Masterportal as api",
|
|
7
7
|
"repository": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"jest": "^29.5.0",
|
|
39
39
|
"jest-canvas-mock": "^2.5.0",
|
|
40
40
|
"jest-environment-jsdom": "^29.5.0",
|
|
41
|
+
"jest-fetch-mock": "^3.0.3",
|
|
41
42
|
"jsdoc": "^4.0.2",
|
|
42
43
|
"parcel": "^2.8.3",
|
|
43
44
|
"process": "^0.11.10",
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
"use-resize-observer": "^9.1.0"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
|
-
"cesium": "^
|
|
51
|
+
"@cesium/engine": "^2.4.1"
|
|
51
52
|
},
|
|
52
53
|
"engines": {
|
|
53
54
|
"node": "^16.13.2 || ^18.12.0",
|
package/src/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import drawInteractions from "./maps/interactions/drawInteractions";
|
|
|
4
4
|
import rawLayerList from "./rawLayerList";
|
|
5
5
|
import * as wms from "./layer/wms";
|
|
6
6
|
import wmts from "./layer/wmts";
|
|
7
|
-
import
|
|
7
|
+
import wfs from "./layer/wfs";
|
|
8
8
|
import * as geojson from "./layer/geojson";
|
|
9
9
|
import * as vectorBase from "./layer/vectorBase";
|
|
10
10
|
import * as vectorTile from "./layer/vectorTile";
|
package/src/layer/wfs.js
CHANGED
|
@@ -154,7 +154,7 @@ function createUrl (rawLayer, version, projection, bboxParam) {
|
|
|
154
154
|
* {@link https://openlayers.org/en/latest/apidoc/module-ol_source_Vector-VectorSource.html failure/success see}
|
|
155
155
|
* @returns {(ol.source.VectorSource|ol.source.Cluster)} VectorSource or Cluster, depending on whether clusterDistance is set.
|
|
156
156
|
*/
|
|
157
|
-
|
|
157
|
+
function createLayerSource (rawLayer, options = {}) {
|
|
158
158
|
if (!options.loadingStrategy) {
|
|
159
159
|
options.loadingStrategy = bbox;
|
|
160
160
|
}
|
|
@@ -175,10 +175,15 @@ export function createLayerSource (rawLayer, options = {}) {
|
|
|
175
175
|
}
|
|
176
176
|
else {
|
|
177
177
|
const bboxParam = options.loadingStrategy === bbox ? `&bbox=${extent.join(",")},${projection.getCode()}` : "";
|
|
178
|
-
let url = createUrl(rawLayer, version, projection, bboxParam)
|
|
178
|
+
let url = createUrl(rawLayer, version, projection, bboxParam),
|
|
179
|
+
params = {};
|
|
179
180
|
|
|
180
181
|
if (options.loadingParams) {
|
|
181
182
|
for (const key in options.loadingParams) {
|
|
183
|
+
if (key === "xhrParameters") {
|
|
184
|
+
params = options.loadingParams.xhrParameters;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
182
187
|
const option = Array.isArray(options.loadingParams[key]) ? options.loadingParams[key].join(",") : options.loadingParams[key];
|
|
183
188
|
|
|
184
189
|
if (option !== undefined && key === "bbox") {
|
|
@@ -189,7 +194,7 @@ export function createLayerSource (rawLayer, options = {}) {
|
|
|
189
194
|
}
|
|
190
195
|
}
|
|
191
196
|
}
|
|
192
|
-
loadWFS(url,
|
|
197
|
+
loadWFS(url, params, source, {onErrorFn: onError, success, failure}, options);
|
|
193
198
|
}
|
|
194
199
|
}
|
|
195
200
|
format.featureType = rawLayer.featureType;
|
|
@@ -202,9 +207,16 @@ export function createLayerSource (rawLayer, options = {}) {
|
|
|
202
207
|
return createClusterVectorSource(source, rawLayer.clusterDistance, options.clusterGeometryFunction);
|
|
203
208
|
}
|
|
204
209
|
if (rawLayer.renderer === "webgl") {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
210
|
+
if (options.loadingStrategy === bbox) {
|
|
211
|
+
source.on("featuresloadend", event => {
|
|
212
|
+
webgl.afterLoading(event?.features, rawLayer.styleId, rawLayer.excludeTypesFromParsing);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
source.once("featuresloadend", event => {
|
|
217
|
+
webgl.afterLoading(event?.features, rawLayer.styleId, rawLayer.excludeTypesFromParsing);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
208
220
|
}
|
|
209
221
|
return source;
|
|
210
222
|
}
|
|
@@ -217,7 +229,7 @@ export function createLayerSource (rawLayer, options = {}) {
|
|
|
217
229
|
* @param {options} [optionalParams.options] - additional options
|
|
218
230
|
* @returns {ol.Layer} Layer that can be added to map.
|
|
219
231
|
*/
|
|
220
|
-
|
|
232
|
+
function createLayer (rawLayer = {}, {layerParams = {}, options = {}} = {}) {
|
|
221
233
|
let layer, source;
|
|
222
234
|
|
|
223
235
|
// use WebGL render pipeline, if specified
|
|
@@ -253,13 +265,227 @@ export function createLayer (rawLayer = {}, {layerParams = {}, options = {}} = {
|
|
|
253
265
|
return layer;
|
|
254
266
|
}
|
|
255
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Writes a wfs transaction including the given feature for given layer
|
|
270
|
+
* inserting, updated or deleting the feature depending on the given selectedInteraction.
|
|
271
|
+
*
|
|
272
|
+
* @param {ol/Feature} feature Feature to be inserted, updated or deleted.
|
|
273
|
+
* @param {Object} transactionOptions Information about the layer to be manipulated.
|
|
274
|
+
* @param {string} transactionMethod Which transaction to perform. Possible values are: "insert"|"delete"|"selectedUpdate"
|
|
275
|
+
* @param {string} srsName EPSG code currently used by the map.
|
|
276
|
+
* @returns {string} WFS Transaction as an XML Node as String.
|
|
277
|
+
*/
|
|
278
|
+
|
|
279
|
+
function writeTransactionBody (feature, transactionOptions, transactionMethod, version = "1.1.0") {
|
|
280
|
+
const transactionPosition = {
|
|
281
|
+
insert: 0,
|
|
282
|
+
selectedUpdate: 1,
|
|
283
|
+
delete: 2
|
|
284
|
+
},
|
|
285
|
+
transaction = [[], [], []];
|
|
286
|
+
|
|
287
|
+
if (transactionMethod !== "insert" && transactionMethod !== "delete" && transactionMethod !== "selectedUpdate") {
|
|
288
|
+
throw new Error("transactionMethod has to be \"insert\", \"selectedUpdate\" or \"delete\".");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
transaction[transactionPosition[transactionMethod]].push(feature);
|
|
292
|
+
return new XMLSerializer()
|
|
293
|
+
.serializeToString(new WFS({version})
|
|
294
|
+
.writeTransaction(...transaction, transactionOptions));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Checks if it is an unknown or special error and returns the code and the error message
|
|
299
|
+
*
|
|
300
|
+
* @param {Object} xmlDocument with the error
|
|
301
|
+
* @returns {Object} the code and the specific or unknown error looking like this {code, message}
|
|
302
|
+
*/
|
|
303
|
+
function getExceptionFromTransactionResponse (xmlDocument) {
|
|
304
|
+
const response = {code: null, message: "genericFailedTransaction"},
|
|
305
|
+
exception = xmlDocument.getElementsByTagName(`${xmlDocument.getElementsByTagName("Exception").length === 0 ? "ows:" : ""}Exception`)[0],
|
|
306
|
+
exceptionText = exception.getElementsByTagName(`${xmlDocument.getElementsByTagName("ExceptionText").length === 0 ? "ows:" : ""}ExceptionText`)[0];
|
|
307
|
+
|
|
308
|
+
if (exceptionText !== undefined) {
|
|
309
|
+
response.message = exceptionText.textContent;
|
|
310
|
+
console.error("WfsTransaction: An error occurred when sending the transaction to the service.", exceptionText.textContent);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
response.message = "WfsTransaction: An unkown error occurred when sending the transaction to the service.";
|
|
314
|
+
console.error(response.message);
|
|
315
|
+
}
|
|
316
|
+
if (exception?.attributes.getNamedItem("code") || exception?.attributes.getNamedItem("exceptionCode")) {
|
|
317
|
+
response.code = exception.attributes.getNamedItem(`${exception?.attributes.getNamedItem("code") ? "c" : "exceptionC"}ode`).textContent;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return response;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Sends a transaction to the service and returns the feature.
|
|
326
|
+
*
|
|
327
|
+
* @param {string} srsName of the coordinate reference system
|
|
328
|
+
* @param {ol/Feature} feature Feature to by inserted / updated / deleted.
|
|
329
|
+
* @param {string} url of the wfs-t service
|
|
330
|
+
* @param {Object} layer the configured representation of the layer in the Masterportal
|
|
331
|
+
* @param {string} transactionMethod which transaction to perform. Possible values are: "insert"|"delete"|"selectedUpdate"
|
|
332
|
+
* @returns {ol/Feature} the given feature
|
|
333
|
+
* @throws {Error} error if occurs
|
|
334
|
+
*/
|
|
335
|
+
async function sendTransaction (srsName, feature, url, layer, transactionMethod) {
|
|
336
|
+
let exception,
|
|
337
|
+
response,
|
|
338
|
+
xmlDocument = null,
|
|
339
|
+
transactionSummary = null,
|
|
340
|
+
data = null;
|
|
341
|
+
|
|
342
|
+
const {featureNS, featurePrefix, featureType, version} = layer;
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
response = await fetch(url, {
|
|
346
|
+
method: "POST",
|
|
347
|
+
headers: {"Content-Type": "text/xml"},
|
|
348
|
+
credentials: layer.isSecured ? "include" : "omit",
|
|
349
|
+
body: writeTransactionBody(feature,
|
|
350
|
+
{featureNS, featurePrefix, featureType, version, srsName},
|
|
351
|
+
transactionMethod,
|
|
352
|
+
version),
|
|
353
|
+
responseType: "text"
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
data = await response.text();
|
|
357
|
+
|
|
358
|
+
xmlDocument = new DOMParser().parseFromString(data, "text/xml");
|
|
359
|
+
transactionSummary = xmlDocument.getElementsByTagName("wfs:TransactionSummary");
|
|
360
|
+
|
|
361
|
+
// NOTE: WFS-T services respond errors with the transaction as an XML response, even though it's the http code indicates different...
|
|
362
|
+
if (transactionSummary.length === 0) {
|
|
363
|
+
exception = getExceptionFromTransactionResponse(xmlDocument);
|
|
364
|
+
throw new Error(exception.code ? exception.code + ": " + exception.message : exception.message);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
catch (e) {
|
|
368
|
+
console.error(e);
|
|
369
|
+
throw e;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return feature;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Parses the response of a DescribeFeatureType request
|
|
377
|
+
* and prepares its values for later use as an input value for the user.
|
|
378
|
+
*
|
|
379
|
+
* @param {string} responseData XML response data
|
|
380
|
+
* @param {string} featureType Name of the feature type of the service.
|
|
381
|
+
* @returns {Array} If an <element> with a name of the featureType is present, an array of prepared feature properties; else an empty Array.
|
|
382
|
+
*/
|
|
383
|
+
function parseDescribeFeatureTypeResponse (responseData, featureType) {
|
|
384
|
+
|
|
385
|
+
const parsedResponse = new DOMParser().parseFromString(responseData, "application/xml");
|
|
386
|
+
|
|
387
|
+
let prefix = "",
|
|
388
|
+
foundElement = null;
|
|
389
|
+
|
|
390
|
+
if (parsedResponse.getElementsByTagName("xsd:element").length > 0) {
|
|
391
|
+
prefix = "xsd:";
|
|
392
|
+
}
|
|
393
|
+
else if (parsedResponse.getElementsByTagName("xs:element").length > 0) {
|
|
394
|
+
prefix = "xs";
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Check if featureType applies to the response
|
|
398
|
+
foundElement = Object.values(parsedResponse.getElementsByTagName(prefix + "element")).find(element => element.getAttribute("name") === featureType);
|
|
399
|
+
|
|
400
|
+
if (foundElement) {
|
|
401
|
+
let sequenceElements;
|
|
402
|
+
|
|
403
|
+
if (foundElement.hasChildNodes()) {
|
|
404
|
+
sequenceElements = Object.values(foundElement.getElementsByTagName(prefix + "sequence"));
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
sequenceElements = Object.values(parsedResponse.getElementsByTagName(prefix + "sequence"));
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const elements = [];
|
|
411
|
+
|
|
412
|
+
sequenceElements.forEach(sequenceElement => {
|
|
413
|
+
elements.push(...Object.values(sequenceElement.getElementsByTagName(prefix + "element")));
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
return elements.map(el => Object.values(el.attributes).reduce((obj, att) => {
|
|
417
|
+
if (att.localName === "minOccurs") {
|
|
418
|
+
obj.required = att.value === "1";
|
|
419
|
+
}
|
|
420
|
+
else if (att.localName === "type") {
|
|
421
|
+
if (att.value.trim().startsWith("gml")) {
|
|
422
|
+
obj.type = "geometry";
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
let value = att.value;
|
|
426
|
+
|
|
427
|
+
if (prefix.length > 0) {
|
|
428
|
+
value = value.replace(prefix, "");
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
switch (value) {
|
|
432
|
+
case "long":
|
|
433
|
+
obj.type = "integer";
|
|
434
|
+
break;
|
|
435
|
+
default:
|
|
436
|
+
obj.type = value;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
else if (att.localName === "name") {
|
|
441
|
+
obj.label = obj.key = att.value;
|
|
442
|
+
}
|
|
443
|
+
return obj;
|
|
444
|
+
}, {
|
|
445
|
+
label: "",
|
|
446
|
+
key: "",
|
|
447
|
+
value: null,
|
|
448
|
+
type: "string",
|
|
449
|
+
required: false
|
|
450
|
+
}));
|
|
451
|
+
}
|
|
452
|
+
return [];
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Requests the possible properties of a feature and further values;
|
|
457
|
+
* for more {@see FeatureProperty}.
|
|
458
|
+
*
|
|
459
|
+
* @param {string} url from the WFS-T
|
|
460
|
+
* @param {string} version of the WFS-T
|
|
461
|
+
* @param {string} featureType Name of the FeatureType according to the capabilities document
|
|
462
|
+
* @param {boolean} isSecured Whether the layer is secured by BasicAuth and should include or omit the credentials prompt
|
|
463
|
+
* @returns {Promise<Array>} If the request is successful, an array of prepared feature properties.
|
|
464
|
+
*/
|
|
465
|
+
async function receivePossibleProperties (url, version, featureType, isSecured) {
|
|
466
|
+
const baseUrl = `${url}?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=${version}&TYPENAME=${featureType}`;
|
|
467
|
+
let response;
|
|
468
|
+
|
|
469
|
+
try {
|
|
470
|
+
response = await fetch(baseUrl, {
|
|
471
|
+
responseType: "text/xml",
|
|
472
|
+
credentials: isSecured ? "include" : "omit"
|
|
473
|
+
});
|
|
474
|
+
return parseDescribeFeatureTypeResponse(await response.text(), featureType);
|
|
475
|
+
}
|
|
476
|
+
catch (e) {
|
|
477
|
+
console.error(e);
|
|
478
|
+
throw e;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
256
482
|
/**
|
|
257
483
|
* Load the features manually.
|
|
258
484
|
* @param {Object} layerAttributes raw layer attributes.
|
|
259
485
|
* @param {module:ol/vector/Source} layerSource - the source of the layer
|
|
260
486
|
* @returns {void}
|
|
261
487
|
*/
|
|
262
|
-
|
|
488
|
+
function loadFeaturesManually (layerAttributes, layerSource) {
|
|
263
489
|
const getUrl = createUrl(layerAttributes, layerAttributes.version, {getCode: () => layerAttributes.crs}, "");
|
|
264
490
|
|
|
265
491
|
fetch(getUrl, layerSource)
|
|
@@ -271,3 +497,5 @@ export function loadFeaturesManually (layerAttributes, layerSource) {
|
|
|
271
497
|
console.error(error);
|
|
272
498
|
});
|
|
273
499
|
}
|
|
500
|
+
|
|
501
|
+
export default {createLayerSource, createLayer, sendTransaction, receivePossibleProperties, parseDescribeFeatureTypeResponse, writeTransactionBody, loadFeaturesManually};
|
|
@@ -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/
|
|
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.
|
|
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 (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
|
|
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.
|
|
83
|
-
* @param {
|
|
84
|
-
* @param {
|
|
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.
|
|
116
|
+
if ((drawType === "doubleCircle" || options.interactive === false) && options.innerRadius > 0) {
|
|
89
117
|
drawInteraction.on("drawstart", event => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
97
|
-
|
|
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
|
};
|
package/src/maps/ol/olMap.js
CHANGED
|
@@ -6,7 +6,7 @@ import defaults from "../../defaults";
|
|
|
6
6
|
import * as wms from "../../layer/wms";
|
|
7
7
|
import wmts from "../../layer/wmts";
|
|
8
8
|
import * as geojson from "../../layer/geojson";
|
|
9
|
-
import
|
|
9
|
+
import wfs from "../../layer/wfs";
|
|
10
10
|
import * as vectorBase from "../../layer/vectorBase";
|
|
11
11
|
import * as vectortile from "../../layer/vectorTile";
|
|
12
12
|
import * as oaf from "../../layer/oaf";
|
package/src/renderer/webgl.js
CHANGED
|
@@ -21,15 +21,13 @@ const defaultStyle = {
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
|
|
24
|
-
/** @type {import('
|
|
24
|
+
/** @type {import('ol/style/literal.js').LiteralStyle} */
|
|
25
25
|
style = {
|
|
26
26
|
"stroke-color": ["get", "STROKECOLOR"],
|
|
27
|
-
|
|
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
|
-
|
|
90
|
-
|
|
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",
|
|
95
|
-
feature.set("STROKEWIDTH",
|
|
96
|
-
feature.set("OPACITY",
|
|
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 === "
|
|
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
|
}
|