@masterportal/masterportalapi 2.48.0 → 2.50.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 +50 -0
- package/babel.config.json +1 -1
- package/bitbucket-pipelines.yml +43 -0
- package/jest.config.js +3 -2
- package/package.json +4 -3
- package/publiccode.yml +88 -0
- package/src/layer/oaf.js +5 -0
- package/src/layer/vectorTile.js +2 -2
- package/src/layer/wms.js +12 -2
- package/src/layer/wmts.js +1 -1
- package/src/maps/interactions/drawInteraction.js +2 -0
- package/src/renderer/webgl.js +41 -78
- package/src/vectorStyle/styleList.js +25 -0
- package/src/vectorStyle/styles/styleText.js +1 -1
- package/test/layer/oaf.test.js +10 -0
- package/test/layer/wms.test.js +2 -2
- package/test/maps/interactions/drawInteraction.test.js +4 -1
- package/test/renderer/webgl.test.js +54 -13
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,56 @@
|
|
|
3
3
|
|
|
4
4
|
The [Semantic Versioning](https://semver.org/spec/v2.0.0.html) is used.
|
|
5
5
|
|
|
6
|
+
## Unreleased - in development
|
|
7
|
+
### __Breaking Changes__
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
### Deprecated
|
|
14
|
+
|
|
15
|
+
### Removed
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 2.50.0 - 2025-08-214
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- vectorStyle: added function `initStyleAndAddToList` to styleList. Adds a style contained in style.json to list of styles.
|
|
25
|
+
- A new parameter "doNotLoadInitially" for OAF layer so that the layer can be loaded without features, which is necessary for external filtering.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- The following packages have been updated:
|
|
29
|
+
- dependencies:
|
|
30
|
+
- ol: 10.4.1 to 10.6.0
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- WMTS-Layer: Fixed layers without capabilities.
|
|
34
|
+
- WFTS-Layer: Ensured zIndex is applied correctly to layers using webgl renderer.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2.49.0 - 2025-04-29
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
- Add new parameters polygonStrokeDash, polygonStrokeDashOffset in styleObject of drawInteraction.
|
|
42
|
+
- webgl: extended default style for points.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
- The following packages have been updated:
|
|
46
|
+
- dependencies:
|
|
47
|
+
- ol-mapbox-style: 12.4.0 to 12.5.0
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
- wms: Fix passing layerParams from layerBuilder.
|
|
51
|
+
- wms-time: layers that are updated daily don't run into errors due to late promise-resolving anymore.
|
|
52
|
+
- Issue #1386: handle label creation if values are empty.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
6
56
|
## 2.48.0 - 2025-04-01
|
|
7
57
|
|
|
8
58
|
### Fixed
|
package/babel.config.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
image: node:20.12.2
|
|
2
|
+
|
|
3
|
+
clone:
|
|
4
|
+
depth: 5000 # include the last five hundred commits
|
|
5
|
+
|
|
6
|
+
pipelines:
|
|
7
|
+
# Start pipeline with tag to build examples zips and copy them to the Bitbucket download folder
|
|
8
|
+
tags:
|
|
9
|
+
'v2.*.*':
|
|
10
|
+
- step:
|
|
11
|
+
name: deploy on openCode
|
|
12
|
+
script:
|
|
13
|
+
- echo 'deploy to opencode:'$BITBUCKET_TAG
|
|
14
|
+
- git fetch --all --tags
|
|
15
|
+
- git checkout tags/$BITBUCKET_TAG
|
|
16
|
+
- git push https://$OpenCode_User:$OpenCode_Password@gitlab.opencode.de/geowerkstatt-hamburg/masterportalapi.git $BITBUCKET_TAG
|
|
17
|
+
- git clone --single-branch --branch master https://geowerkstatt@bitbucket.org/geowerkstatt-hamburg/masterportalapi.git
|
|
18
|
+
- cd masterportalapi
|
|
19
|
+
- git push https://$OpenCode_User:$OpenCode_Password@gitlab.opencode.de/geowerkstatt-hamburg/masterportalapi.git -f
|
|
20
|
+
custom: # Pipelines that are triggered manually
|
|
21
|
+
npm audit:
|
|
22
|
+
- step:
|
|
23
|
+
name: npm audit (security)
|
|
24
|
+
caches:
|
|
25
|
+
- node
|
|
26
|
+
script:
|
|
27
|
+
- npm install
|
|
28
|
+
- npm audit --json
|
|
29
|
+
deploy last tag on openCode:
|
|
30
|
+
- variables:
|
|
31
|
+
- name: BITBUCKET_TAG
|
|
32
|
+
description: tag to publish docs for
|
|
33
|
+
- step:
|
|
34
|
+
name: deploy last tag on openCode
|
|
35
|
+
script:
|
|
36
|
+
- apt-get update && apt-get install -y curl wput jq
|
|
37
|
+
- git fetch --all --tags
|
|
38
|
+
- echo 'deply to opencode:'$BITBUCKET_TAG
|
|
39
|
+
- git checkout tags/$BITBUCKET_TAG
|
|
40
|
+
- git push https://$OpenCode_User:$OpenCode_Password@gitlab.opencode.de/geowerkstatt-hamburg/masterportalapi.git $BITBUCKET_TAG
|
|
41
|
+
- git clone --single-branch --branch master https://geowerkstatt@bitbucket.org/geowerkstatt-hamburg/masterportalapi.git
|
|
42
|
+
- cd masterportalapi
|
|
43
|
+
- git push https://$OpenCode_User:$OpenCode_Password@gitlab.opencode.de/geowerkstatt-hamburg/masterportalapi.git -f
|
package/jest.config.js
CHANGED
|
@@ -6,7 +6,7 @@ module.exports = {
|
|
|
6
6
|
/** ol prints errors without HTMLCanvasElement being available in test environment */
|
|
7
7
|
"setupFiles": ["jest-canvas-mock"],
|
|
8
8
|
/** node_modules are usually ignored by babel-jest, but ol is published in ES6 */
|
|
9
|
-
"transformIgnorePatterns": ["/node_modules/(?!(ol|olcs|ol-mapbox-style|geotiff|quick-lru|color-space|color-rgba|color-parse|color-name|rbush|quickselect|earcut|pbf)/).*/"],
|
|
9
|
+
"transformIgnorePatterns": ["/node_modules/(?!(ol|olcs|ol-mapbox-style|mapbox-to-css-font|geotiff|quick-lru|color-space|color-rgba|color-parse|color-name|rbush|quickselect|earcut|pbf)/).*/"],
|
|
10
10
|
/** only consider files in src/ for coverage */
|
|
11
11
|
"collectCoverageFrom": ["src/**/*.js"],
|
|
12
12
|
/** coverage reporters */
|
|
@@ -14,7 +14,8 @@ module.exports = {
|
|
|
14
14
|
/** mapping svg to string representation since jest can't handle svg and mapping olcs paths*/
|
|
15
15
|
"moduleNameMapper": {
|
|
16
16
|
"marker.svg": "<rootDir>/public/stringMarker.js",
|
|
17
|
-
"olcs/lib/olcs/(.*)$": "<rootDir>/node_modules/olcs/lib/olcs/$1"
|
|
17
|
+
"olcs/lib/olcs/(.*)$": "<rootDir>/node_modules/olcs/lib/olcs/$1",
|
|
18
|
+
"ol-mapbox-style$": "<rootDir>/node_modules/ol-mapbox-style/src/$1"
|
|
18
19
|
},
|
|
19
20
|
"testEnvironment": "jsdom",
|
|
20
21
|
"setupFilesAfterEnv": ["./jest.setup.js"],
|
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.50.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Basic functions of the Masterportal as api",
|
|
7
7
|
"repository": {
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"core-js": "^3.33.1",
|
|
23
23
|
"dayjs": "^1.11.10",
|
|
24
|
-
"ol": "^10.
|
|
25
|
-
"ol-mapbox-style": "12.
|
|
24
|
+
"ol": "^10.6.0",
|
|
25
|
+
"ol-mapbox-style": "12.5.0",
|
|
26
26
|
"olcs": "^2.22.1",
|
|
27
27
|
"proj4": "^2.10.0",
|
|
28
28
|
"xml2js": "^0.6.2"
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
"homepage": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi#readme",
|
|
66
66
|
"directories": {
|
|
67
|
+
"doc": "docs",
|
|
67
68
|
"example": "example",
|
|
68
69
|
"test": "test"
|
|
69
70
|
},
|
package/publiccode.yml
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# This repository adheres to the publiccode.yml standard by including this
|
|
2
|
+
# metadata file that makes public software easily discoverable.
|
|
3
|
+
# More info at https://github.com/italia/publiccode.yml
|
|
4
|
+
|
|
5
|
+
publiccodeYmlVersion: '0.3'
|
|
6
|
+
categories:
|
|
7
|
+
- geographic-information-systems, api
|
|
8
|
+
description:
|
|
9
|
+
de:
|
|
10
|
+
apiDocumentation: 'https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/src/master/README.md'
|
|
11
|
+
documentation: 'https://www.masterportal.org/dokumentation'
|
|
12
|
+
features:
|
|
13
|
+
- OGC-konform
|
|
14
|
+
- Konfigurierbar
|
|
15
|
+
- OpenSource
|
|
16
|
+
- Adminfreundlich
|
|
17
|
+
- Modular
|
|
18
|
+
genericName: 'MasterportalAPI'
|
|
19
|
+
localisedName: MasterportalAPI
|
|
20
|
+
longDescription: |2
|
|
21
|
+
Die MasterportalAPI ist eine API zum Einbinden und Anzeigen von Karteninhalten auf Ihrer Webseite. Sie basiert auf OpenLayers und wurde um Funktionen erweitert, die die einfache Nutzung von Konfigurations- und Infrastrukturdateien des Masterportals, einer funktionsreichen Mapping-App der Geowerkstatt Hamburg, ermöglichen. Sie ermöglicht außerdem die Erstellung einer 3D-Karte mithilfe von OLCS und Cäsium. Weitere Informationen finden Sie auf masterportal.org. Die MasterportalAPI ist Open-Source-Software. Es ist unter der [++MIT-Lizenz++](https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/src/master/License.txt) veröffentlicht.
|
|
22
|
+
shortDescription: 'Die MasterportalAPI ist eine auf OpenLayers basierende API zum Einbinden und Anzeigen von Karteninhalten auf Ihrer Webseite'
|
|
23
|
+
developmentStatus: stable
|
|
24
|
+
intendedAudience:
|
|
25
|
+
countries:
|
|
26
|
+
- de
|
|
27
|
+
- en
|
|
28
|
+
- es
|
|
29
|
+
- it
|
|
30
|
+
- pt
|
|
31
|
+
- ru
|
|
32
|
+
- tr
|
|
33
|
+
- ua
|
|
34
|
+
- nl
|
|
35
|
+
scope:
|
|
36
|
+
- welfare
|
|
37
|
+
- agriculture
|
|
38
|
+
- culture
|
|
39
|
+
- defence
|
|
40
|
+
- education
|
|
41
|
+
- emergency-services
|
|
42
|
+
- employment
|
|
43
|
+
- energy
|
|
44
|
+
- environment
|
|
45
|
+
- finance-and-economic-development
|
|
46
|
+
- foreign-affairs
|
|
47
|
+
- government
|
|
48
|
+
- healthcare
|
|
49
|
+
- infrastructures
|
|
50
|
+
- local-authorities
|
|
51
|
+
- manufacturing
|
|
52
|
+
- research
|
|
53
|
+
- justice
|
|
54
|
+
- science-and-technology
|
|
55
|
+
- security
|
|
56
|
+
- society
|
|
57
|
+
- sport
|
|
58
|
+
- tourism
|
|
59
|
+
- transportation
|
|
60
|
+
landingURL: 'https://www.masterportal.org'
|
|
61
|
+
legal:
|
|
62
|
+
license: MIT
|
|
63
|
+
mainCopyrightOwner: 'Freie und Hansestadt Hamburg, Landesbetrieb Geoinformation und Vermessung'
|
|
64
|
+
repoOwner: 'Freie und Hansestadt Hamburg, Landesbetrieb Geoinformation und Vermessung'
|
|
65
|
+
localisation:
|
|
66
|
+
availableLanguages:
|
|
67
|
+
- de
|
|
68
|
+
- en
|
|
69
|
+
localisationReady: true
|
|
70
|
+
logo: |-
|
|
71
|
+
https://www.masterportal.org/fileadmin/_processed_/7/d/csm_news_masterportal_ce24f3cc3d.jpg
|
|
72
|
+
maintenance:
|
|
73
|
+
contacts:
|
|
74
|
+
- name: Betrieb Webanwendungen
|
|
75
|
+
affiliation: Freie und Hansestadt Hamburg, Landesbetrieb Geoinformation und Vermessung
|
|
76
|
+
contractors:
|
|
77
|
+
- name: Landesbetrieb Geoinformation und Vermessung
|
|
78
|
+
until: '2025-12-01'
|
|
79
|
+
website: 'https://www.hamburg.de/bsw/landesbetrieb-geoinformation-und-vermessung/'
|
|
80
|
+
type: community
|
|
81
|
+
name: Masterportal
|
|
82
|
+
platforms:
|
|
83
|
+
- web
|
|
84
|
+
releaseDate: '2025-04-29'
|
|
85
|
+
roadmap: 'https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/src/master/'
|
|
86
|
+
softwareType: api
|
|
87
|
+
softwareVersion: 2.49.0
|
|
88
|
+
url: 'https://bitbucket.org/geowerkstatt-hamburg/masterportalapi.git'
|
package/src/layer/oaf.js
CHANGED
|
@@ -23,6 +23,7 @@ import * as webgl from "../renderer/webgl";
|
|
|
23
23
|
* @property {function} beforeLoading - function called before loading
|
|
24
24
|
* @property {function} afterLoading - function called after loading, gets parameter features
|
|
25
25
|
* @property {function} featuresFilter - function called after loading to filter features, gets parameter features
|
|
26
|
+
* @property {function} doNotLoadInitially - default false, if set to true the layer will be initialized without network call, an empty array of features is promoted - this is useful to add features later on (e.g. by filtering) to a full functional but initially empty layer
|
|
26
27
|
* @property {function} clusterGeometryFunction - used in cluster source. Returns the geometry of the cluster, gets parameter feature
|
|
27
28
|
* @property {function} style - style function to style the layer
|
|
28
29
|
* @property {object} loadingParams - added as params to url
|
|
@@ -173,6 +174,10 @@ function getLayerSource (rawLayer, options) {
|
|
|
173
174
|
let source = null;
|
|
174
175
|
|
|
175
176
|
function loader (extent, _, __, success, failure) {
|
|
177
|
+
if (options.doNotLoadInitially) {
|
|
178
|
+
onLoad(source, [], onError, success, failure, options);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
176
181
|
const bboxParam = options.loadingStrategy === bbox ? extent : options.loadingParams.bbox,
|
|
177
182
|
url = createUrl(rawLayer, {
|
|
178
183
|
...options.loadingParams,
|
package/src/layer/vectorTile.js
CHANGED
|
@@ -4,11 +4,11 @@ import VectorTileSource from "ol/source/VectorTile";
|
|
|
4
4
|
import OpenLayersTileGrid from "ol/tilegrid/TileGrid";
|
|
5
5
|
import {extentFromProjection} from "ol/tilegrid";
|
|
6
6
|
import * as webgl from "../renderer/webgl";
|
|
7
|
-
|
|
8
|
-
import {stylefunction, apply} from "ol-mapbox-style";
|
|
7
|
+
import {apply, stylefunction} from "ol-mapbox-style";
|
|
9
8
|
|
|
10
9
|
import defaults from "../defaults";
|
|
11
10
|
|
|
11
|
+
|
|
12
12
|
const OL_DEFAULT_VECTOR_TILE_GRID_CRS = "EPSG:3857";
|
|
13
13
|
|
|
14
14
|
/**
|
package/src/layer/wms.js
CHANGED
|
@@ -112,6 +112,14 @@ export function createLayerSource (rawLayer, options) {
|
|
|
112
112
|
projection = rawLayer.crs ? getProjection(rawLayer.crs) : undefined;
|
|
113
113
|
let tileGrid = null;
|
|
114
114
|
|
|
115
|
+
|
|
116
|
+
// Fix for daily updated WMS-Time Layer, which use 'current' as the default value of the time-Extent in their getCapabilities
|
|
117
|
+
// The promise isn't resolved quickly enough for the continued work with the layer.
|
|
118
|
+
// Its resolved value would be the current date, so it is hardcoded here.
|
|
119
|
+
if (rawLayer.TIME && rawLayer.TIME.toString() === "[object Promise]") {
|
|
120
|
+
params.TIME = new Date().toISOString();
|
|
121
|
+
}
|
|
122
|
+
|
|
115
123
|
if (rawLayer.singleTile) {
|
|
116
124
|
return new ImageWMS({
|
|
117
125
|
url: rawLayer.url,
|
|
@@ -154,13 +162,15 @@ export function createLayerSource (rawLayer, options) {
|
|
|
154
162
|
* @param {function} [rawLayer.olAttribution] - optional function that takes a module:ol/Map~FrameState and returns a string or an array of strings representing source attributions
|
|
155
163
|
* @param {string|number} [rawLayer.tilesize] - optional needed to create the tileGrid
|
|
156
164
|
* @param {string|"anonymous"} [rawLayer.crossOrigin] - optional needed for CORS requests of image data, to enable canvas export
|
|
157
|
-
* @param {object}
|
|
165
|
+
* @param {object} [optionalParams] - optional params
|
|
166
|
+
* @param {object} [optionalParams.layerParams] - additional layer params
|
|
167
|
+
* @param {options} [optionalParams.options] - additional options
|
|
158
168
|
* @param {object} options - optional resolutions and origin to create the TileGrid
|
|
159
169
|
* @param {Array} [options.resolutions] - optional resolutions to create the TileGrid, must be in descending order
|
|
160
170
|
* @param {Array} [options.origin] - optional origin to create the TileGrid
|
|
161
171
|
* @returns {ol.Layer} Layer that can be added to map.
|
|
162
172
|
*/
|
|
163
|
-
export function createLayer (rawLayer, layerParams = {}, options) {
|
|
173
|
+
export function createLayer (rawLayer = {}, {layerParams = {}, options = {}} = {}) {
|
|
164
174
|
const source = createLayerSource(rawLayer, options),
|
|
165
175
|
Layer = rawLayer.singleTile ? ImageLayer : TileLayer;
|
|
166
176
|
|
package/src/layer/wmts.js
CHANGED
|
@@ -186,7 +186,7 @@ function createLayer (rawLayer, layerParams = {}) {
|
|
|
186
186
|
infoFormat: rawLayer.infoFormat
|
|
187
187
|
}, layerParams));
|
|
188
188
|
|
|
189
|
-
if (rawLayer.optionsFromCapabilities
|
|
189
|
+
if (!rawLayer.optionsFromCapabilities || !rawLayer.capabilitiesUrl) {
|
|
190
190
|
createLayerSourceByDefinitions(rawLayer, tileLayer);
|
|
191
191
|
}
|
|
192
192
|
else {
|
|
@@ -169,6 +169,8 @@ function setStyleObject (currentLayout, outerCircle = false) {
|
|
|
169
169
|
lineStrokeWidth: currentLayout.strokeWidth,
|
|
170
170
|
polygonFillColor: fillColorRgba,
|
|
171
171
|
polygonStrokeColor: currentLayout.strokeColor,
|
|
172
|
+
polygonStrokeDash: currentLayout.polygonDash,
|
|
173
|
+
polygonStrokeDashOffset: currentLayout.polygonStrokeDashOffset,
|
|
172
174
|
polygonStrokeWidth: currentLayout.strokeWidth
|
|
173
175
|
}
|
|
174
176
|
}
|
package/src/renderer/webgl.js
CHANGED
|
@@ -1,27 +1,38 @@
|
|
|
1
|
-
import WebGLPointsLayer from "ol/layer/WebGLVector";
|
|
2
1
|
import WebGLVectorLayerRenderer from "ol/renderer/webgl/VectorLayer";
|
|
3
2
|
import WebGLVectorTileLayerRenderer from "ol/renderer/webgl/VectorTileLayer.js";
|
|
4
3
|
import VectorTile from "ol/layer/VectorTile.js";
|
|
5
4
|
import VectorLayer from "ol/layer/Layer";
|
|
5
|
+
import WebGLVectorLayer from "ol/layer/WebGLVector.js";
|
|
6
6
|
import styleList from "../vectorStyle/styleList";
|
|
7
7
|
import {getRulesForFeature} from "../vectorStyle/lib/getRuleForIndex";
|
|
8
8
|
import {returnColor} from "../vectorStyle/lib/colorConvertions";
|
|
9
|
-
import {asArray} from "ol/color.js";
|
|
10
|
-
import {packColor, parseLiteralStyle} from "ol/webgl/styleparser.js";
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* The default style for OpenLayers WebGLPoints class
|
|
14
12
|
* @see https://openlayers.org/en/latest/examples/webgl-points-layer.html
|
|
15
13
|
* @private
|
|
16
14
|
*/
|
|
17
|
-
const defaultPointStyle =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
const defaultPointStyle = [
|
|
16
|
+
{
|
|
17
|
+
style: {
|
|
18
|
+
"circle-fill-color": ["match", ["get", "selected"], 1, "#0c2026", "#006688"],
|
|
19
|
+
"circle-radius": [
|
|
20
|
+
"interpolate",
|
|
21
|
+
["exponential", 1.5],
|
|
22
|
+
["zoom"],
|
|
23
|
+
3, 6,
|
|
24
|
+
6, 10,
|
|
25
|
+
9, 20,
|
|
26
|
+
12, 35,
|
|
27
|
+
15, 60,
|
|
28
|
+
18, 110
|
|
29
|
+
],
|
|
30
|
+
"circle-rotate-with-view": false,
|
|
31
|
+
"circle-displacement": [0, 0],
|
|
32
|
+
"circle-opacity": 0.6
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
],
|
|
25
36
|
defaultPolygonStyle = {
|
|
26
37
|
fillColor: "#006688",
|
|
27
38
|
strokeColor: "#006688",
|
|
@@ -52,6 +63,11 @@ export function createVectorLayerRenderer () {
|
|
|
52
63
|
* @description the temporary class with a custom renderer to render the vector data with WebGL
|
|
53
64
|
*/
|
|
54
65
|
class LocalWebGLLayer extends VectorLayer {
|
|
66
|
+
constructor (options) {
|
|
67
|
+
super(options);
|
|
68
|
+
// Initialize with any default style variables
|
|
69
|
+
this.styleVariables = options.styleVariables || {};
|
|
70
|
+
}
|
|
55
71
|
/**
|
|
56
72
|
* Creates a new renderer that takes the defined style of the new layer as an input.
|
|
57
73
|
* @returns {module:ol/renderer/webgl/WebGLVectorLayerRenderer} the custom renderer
|
|
@@ -62,6 +78,13 @@ export function createVectorLayerRenderer () {
|
|
|
62
78
|
style
|
|
63
79
|
});
|
|
64
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the current style variables.
|
|
83
|
+
* @returns {Object} - The current style variables.
|
|
84
|
+
*/
|
|
85
|
+
getStyleVariables () {
|
|
86
|
+
return this.styleVariables;
|
|
87
|
+
}
|
|
65
88
|
}
|
|
66
89
|
|
|
67
90
|
return LocalWebGLLayer;
|
|
@@ -72,9 +95,10 @@ export function createVectorLayerRenderer () {
|
|
|
72
95
|
* @augments VectorTile
|
|
73
96
|
* @private
|
|
74
97
|
* @implements {WebGLVectorTileLayerRenderer}
|
|
98
|
+
* @param {Object} attrs - the attributes of the layer
|
|
75
99
|
* @returns {module:ol/layer/VectorTile} the LocalWebGLLayer with a custom renderer for WebGL styling of vectorTile layers.
|
|
76
100
|
*/
|
|
77
|
-
export function createVectorTileLayerRenderer () {
|
|
101
|
+
export function createVectorTileLayerRenderer (attrs) {
|
|
78
102
|
/**
|
|
79
103
|
* @class LocalWebGLLayer
|
|
80
104
|
* @see https://openlayers.org/en/latest/examples/webgl-vector-tiles.html
|
|
@@ -88,70 +112,8 @@ export function createVectorTileLayerRenderer () {
|
|
|
88
112
|
* @experimental
|
|
89
113
|
*/
|
|
90
114
|
createRenderer () {
|
|
91
|
-
const result = parseLiteralStyle(style),
|
|
92
|
-
invisible = [255, 255, 255, 0],
|
|
93
|
-
grey = [119, 119, 119, 1];
|
|
94
|
-
|
|
95
|
-
|
|
96
115
|
return new WebGLVectorTileLayerRenderer(this, {
|
|
97
|
-
style:
|
|
98
|
-
fill: {
|
|
99
|
-
fragment: result.builder.getFillFragmentShader(),
|
|
100
|
-
vertex: result.builder.getFillVertexShader()
|
|
101
|
-
},
|
|
102
|
-
stroke: {
|
|
103
|
-
fragment: result.builder.getStrokeFragmentShader(),
|
|
104
|
-
vertex: result.builder.getStrokeVertexShader()
|
|
105
|
-
},
|
|
106
|
-
symbol: {
|
|
107
|
-
fragment: result.builder.getSymbolFragmentShader(),
|
|
108
|
-
vertex: result.builder.getSymbolVertexShader()
|
|
109
|
-
},
|
|
110
|
-
builder: result.builder,
|
|
111
|
-
attributes: {
|
|
112
|
-
fillColor: {
|
|
113
|
-
size: 2,
|
|
114
|
-
callback: (feature) => {
|
|
115
|
-
const featureStyle = this.getStyle()(feature, 1);
|
|
116
|
-
|
|
117
|
-
if (featureStyle && featureStyle[0]) {
|
|
118
|
-
const color = featureStyle[0]?.getFill()?.getColor();
|
|
119
|
-
|
|
120
|
-
return packColor(color && typeof color === "string" ? asArray(color) : invisible);
|
|
121
|
-
}
|
|
122
|
-
return packColor(grey);
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
strokeColor: {
|
|
126
|
-
size: 2,
|
|
127
|
-
callback: (feature) => {
|
|
128
|
-
const featureStyle = this.getStyle()(feature, 1);
|
|
129
|
-
|
|
130
|
-
if (featureStyle && featureStyle[0]) {
|
|
131
|
-
const color = featureStyle[0]?.getStroke()?.getColor();
|
|
132
|
-
|
|
133
|
-
return packColor(color ? asArray(color) : invisible);
|
|
134
|
-
}
|
|
135
|
-
return packColor(grey);
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
strokeWidth: {
|
|
139
|
-
size: 1,
|
|
140
|
-
callback: (feature) => {
|
|
141
|
-
const featureStyle = this.getStyle()(feature, 1);
|
|
142
|
-
|
|
143
|
-
if (featureStyle && featureStyle[0]) {
|
|
144
|
-
const width = featureStyle[0]?.getStroke()?.getWidth();
|
|
145
|
-
|
|
146
|
-
if (width !== undefined) {
|
|
147
|
-
return width > 10 ? width / 10 : 1;/** @todo needs refactoring in later versions */
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return 1;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
116
|
+
style: attrs.style ? attrs.style : style
|
|
155
117
|
});
|
|
156
118
|
}
|
|
157
119
|
}
|
|
@@ -275,10 +237,10 @@ export function afterLoading (features, styleId, excludeTypesFromParsing, isPoin
|
|
|
275
237
|
* Creates the OL Layer instance, used to rebuild the layer when shown again after layer has been disposed
|
|
276
238
|
* @param {Object} attrs - the attributes of the layer
|
|
277
239
|
* @public
|
|
278
|
-
* @returns {VectorLayer |
|
|
240
|
+
* @returns {VectorLayer | WebGLVectorLayer} returns the layer instance
|
|
279
241
|
*/
|
|
280
242
|
export function createLayer (attrs) {
|
|
281
|
-
let LayerConstructor =
|
|
243
|
+
let LayerConstructor = WebGLVectorLayer;
|
|
282
244
|
const options = {
|
|
283
245
|
id: attrs.id,
|
|
284
246
|
source: attrs.source,
|
|
@@ -292,7 +254,8 @@ export function createLayer (attrs) {
|
|
|
292
254
|
renderer: "webgl",
|
|
293
255
|
styleId: attrs.styleId,
|
|
294
256
|
excludeTypesFromParsing: attrs.excludeTypesFromParsing,
|
|
295
|
-
extent: attrs.extent
|
|
257
|
+
extent: attrs.extent,
|
|
258
|
+
zIndex: attrs.zIndex
|
|
296
259
|
};
|
|
297
260
|
|
|
298
261
|
/**
|
|
@@ -274,6 +274,30 @@ function addToStyleList (jsonStyles) {
|
|
|
274
274
|
});
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Fetches the style.json file and adds the style for the styleId to the style list, if contained in style.json.
|
|
279
|
+
* @param {object} [Config] - the Config.js object
|
|
280
|
+
* @param {string} [styleId] - the styleId to add
|
|
281
|
+
* @returns {object} the style object for the styleId
|
|
282
|
+
*/
|
|
283
|
+
async function initStyleAndAddToList (Config, styleId) {
|
|
284
|
+
let style;
|
|
285
|
+
|
|
286
|
+
await fetch(Config.styleConf)
|
|
287
|
+
.then(response => response.json())
|
|
288
|
+
.then(data => {
|
|
289
|
+
style = data.find(aStyle => aStyle.styleId === styleId);
|
|
290
|
+
|
|
291
|
+
if (style) {
|
|
292
|
+
styleList.push(style);
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
.catch(error => {
|
|
296
|
+
console.error(error);
|
|
297
|
+
});
|
|
298
|
+
return style;
|
|
299
|
+
}
|
|
300
|
+
|
|
277
301
|
/**
|
|
278
302
|
* Returns style object by styleId or by layerId
|
|
279
303
|
* @param {string} layerId layerId
|
|
@@ -285,6 +309,7 @@ function returnStyleObject (layerId) {
|
|
|
285
309
|
|
|
286
310
|
export default {
|
|
287
311
|
initializeStyleList,
|
|
312
|
+
initStyleAndAddToList,
|
|
288
313
|
addToStyleList,
|
|
289
314
|
returnStyleObject
|
|
290
315
|
};
|
|
@@ -120,7 +120,7 @@ class TextStyle extends StyleClass {
|
|
|
120
120
|
const feature = this.feature,
|
|
121
121
|
featureProperties = feature.getProperties(),
|
|
122
122
|
textSuffix = this.attributes.textSuffix;
|
|
123
|
-
let text = mapAttributes(featureProperties, this.attributes.labelField, false);
|
|
123
|
+
let text = mapAttributes(featureProperties, this.attributes.labelField, false) ?? "";
|
|
124
124
|
|
|
125
125
|
if (textSuffix !== "") {
|
|
126
126
|
text = text + " " + textSuffix;
|
package/test/layer/oaf.test.js
CHANGED
|
@@ -52,6 +52,16 @@ describe("oaf.js", function () {
|
|
|
52
52
|
expect(layer.get("id")).toEqual("id");
|
|
53
53
|
expect(layer.getSource()).toBeInstanceOf(VectorSource);
|
|
54
54
|
});
|
|
55
|
+
it("creates empty layer if doNotLoadInitially is true", function () {
|
|
56
|
+
const options = {
|
|
57
|
+
doNotLoadInitially: true
|
|
58
|
+
},
|
|
59
|
+
layer = oaf.createLayer({id: "id"}, {options});
|
|
60
|
+
|
|
61
|
+
expect(layer).toBeInstanceOf(VectorLayer);
|
|
62
|
+
expect(layer.getSource()).toBeInstanceOf(VectorSource);
|
|
63
|
+
expect(layer.getSource().getFeatures().length).toEqual(0);
|
|
64
|
+
});
|
|
55
65
|
it("creates a VectorLayer with style in rawLayer", function () {
|
|
56
66
|
function styleFunction () {
|
|
57
67
|
const icon = new Style({
|
package/test/layer/wms.test.js
CHANGED
|
@@ -250,7 +250,7 @@ describe("wms.js", function () {
|
|
|
250
250
|
name: "name",
|
|
251
251
|
layers: "layer1, layer2"
|
|
252
252
|
},
|
|
253
|
-
layer = wms.createLayer({singleTile: false, tilesize: "10", extent: [10, 20, 11, 22]}, layerParams, options);
|
|
253
|
+
layer = wms.createLayer({singleTile: false, tilesize: "10", extent: [10, 20, 11, 22]}, {layerParams, options});
|
|
254
254
|
|
|
255
255
|
expect(layer).toBeInstanceOf(TileLayer);
|
|
256
256
|
expect(layer.get("name")).toEqual("name");
|
|
@@ -266,7 +266,7 @@ describe("wms.js", function () {
|
|
|
266
266
|
name: "name",
|
|
267
267
|
layers: "layer1, layer2"
|
|
268
268
|
},
|
|
269
|
-
layer = wms.createLayer({singleTile: true}, layerParams);
|
|
269
|
+
layer = wms.createLayer({singleTile: true}, {layerParams});
|
|
270
270
|
|
|
271
271
|
expect(layer).toBeInstanceOf(ImageLayer);
|
|
272
272
|
expect(layer.get("name")).toEqual("name");
|
|
@@ -86,7 +86,8 @@ describe("src/maps/interactions/drawInteraction.js", () => {
|
|
|
86
86
|
fillColor: [55, 126, 184],
|
|
87
87
|
fillTransparency: 0,
|
|
88
88
|
strokeColor: [0, 0, 0],
|
|
89
|
-
strokeWidth: 1
|
|
89
|
+
strokeWidth: 1,
|
|
90
|
+
polygonDash: [4]
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
drawInteractions.setStyleObject(currentLayout);
|
|
@@ -124,6 +125,8 @@ describe("src/maps/interactions/drawInteraction.js", () => {
|
|
|
124
125
|
0,
|
|
125
126
|
0
|
|
126
127
|
],
|
|
128
|
+
polygonStrokeDash: [4],
|
|
129
|
+
polygonStrokeDashOffset: undefined,
|
|
127
130
|
polygonStrokeWidth: 1
|
|
128
131
|
}
|
|
129
132
|
}
|
|
@@ -5,7 +5,7 @@ import Feature from "ol/Feature";
|
|
|
5
5
|
import Polygon from "ol/geom/Polygon";
|
|
6
6
|
import MultiPoint from "ol/geom/MultiPoint";
|
|
7
7
|
import * as webgl from "../../src/renderer/webgl";
|
|
8
|
-
import
|
|
8
|
+
import WebGLVectorLayer from "ol/layer/WebGLVector.js";
|
|
9
9
|
import Layer from "ol/layer/Layer";
|
|
10
10
|
import {returnColor} from "../../src/vectorStyle/lib/colorConvertions";
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ jest.mock("../../src/vectorStyle/styleList.js", () => {
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
describe("webgl.js", () => {
|
|
21
|
-
let layerParams, layerParamsVectorTile, rawLayer, rawLayerVectorTile, styleRule, styleObject,
|
|
21
|
+
let layerParams, layerParamsVectorTile, rawLayer, rawLayerVectorTile, styleRule, styleObject, defaultPointStyle;
|
|
22
22
|
|
|
23
23
|
beforeEach(() => {
|
|
24
24
|
layerParams = {
|
|
@@ -68,23 +68,30 @@ describe("webgl.js", () => {
|
|
|
68
68
|
styleObject = {
|
|
69
69
|
rules: [styleRule]
|
|
70
70
|
};
|
|
71
|
-
|
|
71
|
+
defaultPointStyle = {
|
|
72
72
|
fillColor: "#006688",
|
|
73
73
|
strokeColor: "#006688",
|
|
74
74
|
strokeWidth: 1,
|
|
75
75
|
opacity: 1,
|
|
76
|
-
|
|
76
|
+
zoom: [
|
|
77
|
+
3, 6,
|
|
78
|
+
6, 10,
|
|
79
|
+
9, 20,
|
|
80
|
+
12, 35,
|
|
81
|
+
15, 60,
|
|
82
|
+
18, 110
|
|
83
|
+
]
|
|
77
84
|
};
|
|
78
85
|
});
|
|
79
86
|
|
|
80
87
|
describe("createLayer", () => {
|
|
81
88
|
let source = new VectorSource();
|
|
82
89
|
|
|
83
|
-
it("should return a
|
|
90
|
+
it("should return a WebGLVectorLayer", () => {
|
|
84
91
|
layerParams.isPointLayer = true;
|
|
85
92
|
const webglLayer = webgl.createLayer({...rawLayer, ...layerParams, source});
|
|
86
93
|
|
|
87
|
-
expect(webglLayer).toBeInstanceOf(
|
|
94
|
+
expect(webglLayer).toBeInstanceOf(WebGLVectorLayer);
|
|
88
95
|
expect(webglLayer.get("isPointLayer")).toBeTruthy();
|
|
89
96
|
});
|
|
90
97
|
it("should return a custom Layer", () => {
|
|
@@ -92,7 +99,7 @@ describe("webgl.js", () => {
|
|
|
92
99
|
const webglLayer = webgl.createLayer({...rawLayer, ...layerParams, source});
|
|
93
100
|
|
|
94
101
|
expect(webglLayer).toBeInstanceOf(Layer);
|
|
95
|
-
expect(webglLayer).not.toBeInstanceOf(
|
|
102
|
+
expect(webglLayer).not.toBeInstanceOf(WebGLVectorLayer);
|
|
96
103
|
expect(webglLayer.get("isPointLayer")).toBeFalsy();
|
|
97
104
|
});
|
|
98
105
|
it("vectorTile: should return a VectorTile layer", () => {
|
|
@@ -102,7 +109,7 @@ describe("webgl.js", () => {
|
|
|
102
109
|
|
|
103
110
|
expect(webglLayer).toBeInstanceOf(Layer);
|
|
104
111
|
expect(webglLayer).toBeInstanceOf(VectorTile);
|
|
105
|
-
expect(webglLayer).not.toBeInstanceOf(
|
|
112
|
+
expect(webglLayer).not.toBeInstanceOf(WebGLVectorLayer);
|
|
106
113
|
expect(webglLayer.get("isPointLayer")).toBeFalsy();
|
|
107
114
|
});
|
|
108
115
|
});
|
|
@@ -187,12 +194,46 @@ describe("webgl.js", () => {
|
|
|
187
194
|
rules: [styleRule]
|
|
188
195
|
};
|
|
189
196
|
webgl.formatFeatureStyles($feature, styleObject);
|
|
190
|
-
expect($feature.get("fillColor")).toEqual(
|
|
191
|
-
expect($feature.get("strokeColor")).toEqual(
|
|
192
|
-
expect($feature.get("strokeWidth")).toEqual(
|
|
193
|
-
expect($feature.get("opacity")).toEqual(
|
|
194
|
-
expect($feature.get("circleSize")).toEqual(defaultStyle.size);
|
|
197
|
+
expect($feature.get("fillColor")).toEqual(defaultPointStyle.fillColor);
|
|
198
|
+
expect($feature.get("strokeColor")).toEqual(defaultPointStyle.strokeColor);
|
|
199
|
+
expect($feature.get("strokeWidth")).toEqual(defaultPointStyle.strokeWidth);
|
|
200
|
+
expect($feature.get("opacity")).toEqual(defaultPointStyle.opacity);
|
|
195
201
|
});
|
|
202
|
+
|
|
203
|
+
it("should calculate circle-radius based on zoom level", () => {
|
|
204
|
+
const zoomLevels = [3, 6, 9, 12, 15, 18],
|
|
205
|
+
expectedRadii = [6, 10, 20, 35, 60, 110];
|
|
206
|
+
|
|
207
|
+
// eslint-disable-next-line no-use-before-define, max-nested-callbacks
|
|
208
|
+
zoomLevels.forEach((zoom, index) => testZoomLevel(zoom, index, expectedRadii));
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
function interpolateCircleRadius (zoom, zoomArray) {
|
|
212
|
+
for (let i = 0; i < zoomArray.length; i += 2) {
|
|
213
|
+
const z = zoomArray[i],
|
|
214
|
+
r = zoomArray[i + 1];
|
|
215
|
+
|
|
216
|
+
if (zoom <= z) {
|
|
217
|
+
if (i === 0) {
|
|
218
|
+
return r;
|
|
219
|
+
}
|
|
220
|
+
const zPrev = zoomArray[i - 2],
|
|
221
|
+
rPrev = zoomArray[i - 1],
|
|
222
|
+
t = (zoom - zPrev) / (z - zPrev);
|
|
223
|
+
|
|
224
|
+
return rPrev + (t * (r - rPrev));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return zoomArray[zoomArray.length - 1];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function testZoomLevel (zoom, index, expectedRadii) {
|
|
231
|
+
const expectedRadius = expectedRadii[index],
|
|
232
|
+
actualRadius = interpolateCircleRadius(zoom, defaultPointStyle.zoom);
|
|
233
|
+
|
|
234
|
+
expect(actualRadius).toEqual(expectedRadius);
|
|
235
|
+
}
|
|
236
|
+
|
|
196
237
|
});
|
|
197
238
|
});
|
|
198
239
|
});
|