@open-pioneer/map 1.0.0 → 1.1.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 -0
- package/layers/AbstractLayer.d.ts +36 -0
- package/layers/AbstractLayer.js +119 -1
- package/layers/AbstractLayer.js.map +1 -1
- package/layers/WMSLayer.js +4 -2
- package/layers/WMSLayer.js.map +1 -1
- package/layers/WMTSLayer.js +1 -1
- package/layers/WMTSLayer.js.map +1 -1
- package/layers/shared/LayerConfig.d.ts +16 -0
- package/layers/wms/WMSSublayer.js.map +1 -1
- package/model/Highlights.js.map +1 -1
- package/model/LayerCollection.js +3 -0
- package/model/LayerCollection.js.map +1 -1
- package/model/MapModel.js +1 -1
- package/model/MapModel.js.map +1 -1
- package/model/createMapModel.js.map +1 -1
- package/package.json +10 -10
- package/ui/MapContainer.js.map +1 -1
- package/ui/hooks/useMapModel.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @open-pioneer/map
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 10338fa: Update OpenLayers to 10.7.0
|
|
8
|
+
- a8b8a36: Update trails core packages to 4.3.0
|
|
9
|
+
- 10338fa: Update Chakra to 3.29.0
|
|
10
|
+
- c38b619: Adds optional configuration properties to all `Layers` to restrict the visibility of layers to a range of zoom levels or resolutions.
|
|
11
|
+
The visibility can be restricted either to a `minResolution` and `maxResolution` or to a `minZoom` and `maxZoom`.
|
|
12
|
+
Using only a minimum or maximum limit is possible.
|
|
13
|
+
Missing properties are considered as no limitation.
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
layerFactory.create({
|
|
17
|
+
type: WMTSLayer,
|
|
18
|
+
isBaseLayer: true,
|
|
19
|
+
title: "Basemap",
|
|
20
|
+
name: "basemap",
|
|
21
|
+
minZoom: 10,
|
|
22
|
+
maxZoom: 16
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The boolean property `visibleInScale` of a layer indicates the visibility of this layer depending on the current resolution of the map.
|
|
27
|
+
|
|
28
|
+
Restrictions of a `GroupLayer` are inherited to child layers.
|
|
29
|
+
If no restrictions are configured for a child layer, its visibility limitations are equal to the parent `GroupLayer`.
|
|
30
|
+
By configuring additional limits for the child layer, its visibility can be further restricted.
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- fce7fa9: Implement stricter null safety checks.
|
|
35
|
+
|
|
3
36
|
## 1.0.0
|
|
4
37
|
|
|
5
38
|
### Major Changes
|
|
@@ -44,6 +44,42 @@ export declare abstract class AbstractLayer extends AbstractLayerBase {
|
|
|
44
44
|
* The load state of a layer.
|
|
45
45
|
*/
|
|
46
46
|
get loadState(): LayerLoadState;
|
|
47
|
+
/**
|
|
48
|
+
* The minimum resolution (inclusive) at which this layer will be visible.
|
|
49
|
+
*/
|
|
50
|
+
get minResolution(): number;
|
|
51
|
+
/**
|
|
52
|
+
* The maximum resolution (exclusive) below which this layer will be visible.
|
|
53
|
+
*/
|
|
54
|
+
get maxResolution(): number;
|
|
55
|
+
/**
|
|
56
|
+
* The minimum view zoom level (exclusive) above which this layer will be visible.
|
|
57
|
+
*/
|
|
58
|
+
get minZoom(): number;
|
|
59
|
+
/**
|
|
60
|
+
* The maximum view zoom level (inclusive) at which this layer will be visible.
|
|
61
|
+
*/
|
|
62
|
+
get maxZoom(): number;
|
|
63
|
+
/**
|
|
64
|
+
* Whether the layer is visible in the current map scale or not.
|
|
65
|
+
*/
|
|
66
|
+
get visibleInScale(): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* The minimum resolution (inclusive) at which this layer will be visible.
|
|
69
|
+
*/
|
|
70
|
+
setMinResolution(value: number): void;
|
|
71
|
+
/**
|
|
72
|
+
* The maximum resolution (exclusive) below which this layer will be visible.
|
|
73
|
+
*/
|
|
74
|
+
setMaxResolution(value: number): void;
|
|
75
|
+
/**
|
|
76
|
+
* The minimum view zoom level (exclusive) above which this layer will be visible.
|
|
77
|
+
*/
|
|
78
|
+
setMinZoom(value: number): void;
|
|
79
|
+
/**
|
|
80
|
+
* The maximum view zoom level (inclusive) at which this layer will be visible.
|
|
81
|
+
*/
|
|
82
|
+
setMaxZoom(value: number): void;
|
|
47
83
|
/**
|
|
48
84
|
* Called by the map model when the layer is added to the map.
|
|
49
85
|
*
|
package/layers/AbstractLayer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { synchronized, reactive } from '@conterra/reactivity-core';
|
|
1
|
+
import { synchronized, reactive, computed } from '@conterra/reactivity-core';
|
|
2
2
|
import { createLogger, destroyResource } from '@open-pioneer/core';
|
|
3
3
|
import OlLayer from 'ol/layer/Layer.js';
|
|
4
4
|
import { unByKey } from 'ol/Observable.js';
|
|
@@ -15,8 +15,13 @@ class AbstractLayer extends AbstractLayerBase {
|
|
|
15
15
|
#isBaseLayer;
|
|
16
16
|
#healthCheck;
|
|
17
17
|
#visible;
|
|
18
|
+
#minResolution;
|
|
19
|
+
#maxResolution;
|
|
20
|
+
#minZoom;
|
|
21
|
+
#maxZoom;
|
|
18
22
|
#loadState;
|
|
19
23
|
#stateWatchResource;
|
|
24
|
+
#visibleInScale;
|
|
20
25
|
constructor(config, deps, internalTag) {
|
|
21
26
|
super(config);
|
|
22
27
|
this.#deps = getLayerDependencies(deps, internalTag);
|
|
@@ -30,8 +35,67 @@ class AbstractLayer extends AbstractLayerBase {
|
|
|
30
35
|
return () => unByKey(key);
|
|
31
36
|
}
|
|
32
37
|
);
|
|
38
|
+
this.#minResolution = synchronized(
|
|
39
|
+
() => this.#olLayer.getMinResolution(),
|
|
40
|
+
(cb) => {
|
|
41
|
+
const key = this.#olLayer.on("change:minResolution", cb);
|
|
42
|
+
return () => unByKey(key);
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
this.#maxResolution = synchronized(
|
|
46
|
+
() => this.#olLayer.getMaxResolution(),
|
|
47
|
+
(cb) => {
|
|
48
|
+
const key = this.#olLayer.on("change:maxResolution", cb);
|
|
49
|
+
return () => unByKey(key);
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
this.#minZoom = synchronized(
|
|
53
|
+
() => this.#olLayer.getMinZoom(),
|
|
54
|
+
(cb) => {
|
|
55
|
+
const key = this.#olLayer.on("change:minZoom", cb);
|
|
56
|
+
return () => unByKey(key);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
this.#maxZoom = synchronized(
|
|
60
|
+
() => this.#olLayer.getMaxZoom(),
|
|
61
|
+
(cb) => {
|
|
62
|
+
const key = this.#olLayer.on("change:maxZoom", cb);
|
|
63
|
+
return () => unByKey(key);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
33
66
|
this.#loadState = reactive(getSourceState(getSource(this.#olLayer)));
|
|
34
67
|
this[SET_VISIBLE](config.visible ?? true);
|
|
68
|
+
this.#visibleInScale = computed(() => {
|
|
69
|
+
const map = this.nullableMap;
|
|
70
|
+
if (!map) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
const zoom = map.zoomLevel;
|
|
74
|
+
const resolution = map.resolution;
|
|
75
|
+
if (zoom == null || resolution == null) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const parent = this.parent;
|
|
79
|
+
if (parent && parent.type === "group" && !parent.visibleInScale) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (resolution < this.minResolution || resolution >= this.maxResolution) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
return zoom > this.minZoom && zoom <= this.maxZoom;
|
|
86
|
+
});
|
|
87
|
+
if (config.maxResolution) {
|
|
88
|
+
this.#olLayer.setMaxResolution(config.maxResolution);
|
|
89
|
+
}
|
|
90
|
+
if (config.minResolution) {
|
|
91
|
+
this.#olLayer.setMinResolution(config.minResolution);
|
|
92
|
+
}
|
|
93
|
+
if (config.maxZoom) {
|
|
94
|
+
this.#olLayer.setMaxZoom(config.maxZoom);
|
|
95
|
+
}
|
|
96
|
+
if (config.minZoom) {
|
|
97
|
+
this.#olLayer.setMinZoom(config.minZoom);
|
|
98
|
+
}
|
|
35
99
|
}
|
|
36
100
|
destroy() {
|
|
37
101
|
if (this.isDestroyed) {
|
|
@@ -64,6 +128,60 @@ class AbstractLayer extends AbstractLayerBase {
|
|
|
64
128
|
get loadState() {
|
|
65
129
|
return this.#loadState.value;
|
|
66
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* The minimum resolution (inclusive) at which this layer will be visible.
|
|
133
|
+
*/
|
|
134
|
+
get minResolution() {
|
|
135
|
+
return this.#minResolution.value;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The maximum resolution (exclusive) below which this layer will be visible.
|
|
139
|
+
*/
|
|
140
|
+
get maxResolution() {
|
|
141
|
+
return this.#maxResolution.value;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The minimum view zoom level (exclusive) above which this layer will be visible.
|
|
145
|
+
*/
|
|
146
|
+
get minZoom() {
|
|
147
|
+
return this.#minZoom.value;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The maximum view zoom level (inclusive) at which this layer will be visible.
|
|
151
|
+
*/
|
|
152
|
+
get maxZoom() {
|
|
153
|
+
return this.#maxZoom.value;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Whether the layer is visible in the current map scale or not.
|
|
157
|
+
*/
|
|
158
|
+
get visibleInScale() {
|
|
159
|
+
return this.#visibleInScale.value;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The minimum resolution (inclusive) at which this layer will be visible.
|
|
163
|
+
*/
|
|
164
|
+
setMinResolution(value) {
|
|
165
|
+
this.#olLayer.setMinResolution(value);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The maximum resolution (exclusive) below which this layer will be visible.
|
|
169
|
+
*/
|
|
170
|
+
setMaxResolution(value) {
|
|
171
|
+
this.#olLayer.setMaxResolution(value);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The minimum view zoom level (exclusive) above which this layer will be visible.
|
|
175
|
+
*/
|
|
176
|
+
setMinZoom(value) {
|
|
177
|
+
this.#olLayer.setMinZoom(value);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The maximum view zoom level (inclusive) at which this layer will be visible.
|
|
181
|
+
*/
|
|
182
|
+
setMaxZoom(value) {
|
|
183
|
+
this.#olLayer.setMaxZoom(value);
|
|
184
|
+
}
|
|
67
185
|
/**
|
|
68
186
|
* Called by the map model when the layer is added to the map.
|
|
69
187
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractLayer.js","sources":["AbstractLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { reactive, Reactive, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport { createLogger, destroyResource, Resource } from \"@open-pioneer/core\";\nimport { EventsKey } from \"ol/events\";\nimport OlBaseLayer from \"ol/layer/Base\";\nimport OlLayer from \"ol/layer/Layer\";\nimport { unByKey } from \"ol/Observable\";\nimport OlSource from \"ol/source/Source\";\nimport { MapModel } from \"../model/MapModel\";\nimport { InternalConstructorTag } from \"../utils/InternalConstructorTag\";\nimport { AbstractLayerBase } from \"./AbstractLayerBase\";\nimport {\n ATTACH_TO_MAP,\n GET_DEPS,\n getLayerDependencies,\n LAYER_DEPS,\n LayerDependencies,\n SET_VISIBLE\n} from \"./shared/internals\";\nimport { HealthCheckFunction, LayerConfig } from \"./shared/LayerConfig\";\nimport { SimpleLayer, SimpleLayerConfig } from \"./SimpleLayer\";\nimport { Layer, LayerTypes } from \"./unions\";\n\nconst LOG = createLogger(\"map:AbstractLayer\");\n\n/**\n * The load state of a layer.\n *\n * @group Layer Utilities\n **/\nexport type LayerLoadState = \"not-loaded\" | \"loading\" | \"loaded\" | \"error\";\n\n/**\n * Represents an operational layer in the map.\n *\n * These layers always have an associated OpenLayers layer.\n *\n * Instances of this interface cannot be constructed directly; use a real layer\n * class such as {@link SimpleLayer} instead.\n *\n * @group Layers\n */\nexport abstract class AbstractLayer extends AbstractLayerBase {\n // Layer dependencies are present when the LayerFactory API was used to construct the layer.\n // They may currently be undefined for compatibility reasons (in which case they will be used\n // from the map, once connected).\n #deps: LayerDependencies | undefined;\n #olLayer: OlBaseLayer;\n #isBaseLayer: boolean;\n #healthCheck?: string | HealthCheckFunction;\n\n #visible: ReadonlyReactive<boolean>;\n #loadState: Reactive<LayerLoadState>;\n\n #stateWatchResource: Resource | undefined;\n\n constructor(\n config: SimpleLayerConfig,\n deps?: LayerDependencies,\n internalTag?: InternalConstructorTag\n ) {\n super(config);\n this.#deps = getLayerDependencies(deps, internalTag);\n this.#olLayer = config.olLayer;\n this.#isBaseLayer = config.isBaseLayer ?? false;\n this.#healthCheck = config.healthCheck;\n this.#visible = synchronized(\n () => this.#olLayer.getVisible(),\n (cb) => {\n const key = this.#olLayer.on(\"change:visible\", cb);\n return () => unByKey(key);\n }\n );\n this.#loadState = reactive(getSourceState(getSource(this.#olLayer)));\n\n this[SET_VISIBLE](config.visible ?? true); // apply initial visibility\n }\n\n override destroy() {\n if (this.isDestroyed) {\n return;\n }\n\n this.#stateWatchResource = destroyResource(this.#stateWatchResource);\n this.olLayer.dispose();\n super.destroy();\n }\n\n /**\n * Identifies the type of this layer.\n */\n abstract override readonly type: LayerTypes;\n\n override get visible(): boolean {\n return this.#visible.value;\n }\n\n /**\n * The raw OpenLayers layer.\n */\n get olLayer(): OlBaseLayer {\n return this.#olLayer;\n }\n\n /**\n * True if this layer is a base layer.\n *\n * Only one base layer can be visible at a time.\n */\n get isBaseLayer(): boolean {\n return this.#isBaseLayer;\n }\n\n /**\n * The load state of a layer.\n */\n get loadState(): LayerLoadState {\n return this.#loadState.value;\n }\n\n /**\n * Called by the map model when the layer is added to the map.\n *\n * @internal\n */\n override [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n\n if (!this.#stateWatchResource) {\n const { initial: initialState, resource: stateWatchResource } = watchLoadState(\n this,\n this.#healthCheck,\n (state) => {\n this.#loadState.value = state;\n }\n );\n this.#stateWatchResource = stateWatchResource;\n this.#loadState.value = initialState;\n }\n }\n\n override setVisible(newVisibility: boolean): void {\n if (this.isBaseLayer) {\n LOG.warn(\n `Cannot change visibility of base layer '${this.id}': use activateBaseLayer() on the map's LayerCollection instead.`\n );\n return;\n }\n\n this[SET_VISIBLE](newVisibility);\n }\n\n /** @internal */\n [SET_VISIBLE](newVisibility: boolean): void {\n if (this.#olLayer.getVisible() !== newVisibility) {\n this.#olLayer.setVisible(newVisibility);\n }\n }\n\n /** @internal */\n [GET_DEPS](): LayerDependencies {\n const deps = this.#deps;\n if (deps) {\n return deps;\n }\n\n const map = this.nullableMap;\n if (map) {\n return map[LAYER_DEPS];\n }\n throw new Error(\n `Layer '${this.id}' has not been attached to a map yet. \"\n + \"Use the LayerFactory to create an instance or add the layer to the map first.`\n );\n }\n}\n\nfunction watchLoadState(\n layer: AbstractLayer,\n healthCheck: LayerConfig[\"healthCheck\"],\n onChange: (newState: LayerLoadState) => void\n): { initial: LayerLoadState; resource: Resource } {\n const olLayer = layer.olLayer;\n\n if (!(olLayer instanceof OlLayer)) {\n // Some layers don't have a source (such as group)\n return {\n initial: \"loaded\",\n resource: {\n destroy() {\n void 0;\n }\n }\n };\n }\n\n let currentSource = getSource(olLayer);\n const currentOlLayerState = getSourceState(currentSource);\n\n let currentLoadState: LayerLoadState = currentOlLayerState;\n let currentHealthState = \"loading\"; // initial state loading until health check finished\n\n // custom health check not needed when OpenLayers already returning an error state\n if (currentOlLayerState !== \"error\") {\n // health check only once during initialization\n doHealthCheck(layer, healthCheck).then((state: LayerLoadState) => {\n currentHealthState = state;\n updateState();\n });\n }\n\n const updateState = () => {\n const olLayerState = getSourceState(currentSource);\n const nextLoadState: LayerLoadState =\n currentHealthState === \"error\" ? \"error\" : olLayerState;\n\n if (currentLoadState !== nextLoadState) {\n currentLoadState = nextLoadState;\n onChange(currentLoadState);\n }\n };\n\n let stateHandle: EventsKey | undefined;\n stateHandle = currentSource?.on(\"change\", () => {\n updateState();\n });\n\n const sourceHandle = olLayer.on(\"change:source\", () => {\n // unsubscribe from old source\n stateHandle && unByKey(stateHandle);\n stateHandle = undefined;\n\n // subscribe to new source and update state\n currentSource = getSource(olLayer);\n stateHandle = currentSource?.on(\"change\", () => {\n updateState();\n });\n updateState();\n });\n return {\n initial: currentLoadState,\n resource: {\n destroy() {\n stateHandle && unByKey(stateHandle);\n unByKey(sourceHandle);\n }\n }\n };\n}\n\nasync function doHealthCheck(\n layer: AbstractLayer,\n healthCheck: LayerConfig[\"healthCheck\"]\n): Promise<LayerLoadState> {\n if (healthCheck == null) {\n return \"loaded\";\n }\n\n let healthCheckFn: HealthCheckFunction;\n if (typeof healthCheck === \"function\") {\n healthCheckFn = healthCheck;\n } else if (typeof healthCheck === \"string\") {\n healthCheckFn = async () => {\n const httpService = layer[GET_DEPS]().httpService;\n const response = await httpService.fetch(healthCheck);\n if (response.ok) {\n return \"loaded\";\n }\n LOG.warn(\n `Health check failed for layer '${layer.id}' (http status ${response.status})`\n );\n return \"error\";\n };\n } else {\n LOG.error(\n `Unexpected object for 'healthCheck' parameter of layer '${layer.id}'`,\n healthCheck\n );\n return \"error\";\n }\n\n try {\n return await healthCheckFn(layer as Layer);\n } catch (e) {\n LOG.warn(`Health check failed for layer '${layer.id}'`, e);\n return \"error\";\n }\n}\n\nfunction getSource(olLayer: OlLayer | OlBaseLayer) {\n if (!(olLayer instanceof OlLayer)) {\n return undefined;\n }\n return (olLayer?.getSource() as OlSource | null) ?? undefined;\n}\n\nfunction getSourceState(olSource: OlSource | undefined) {\n const state = olSource?.getState();\n switch (state) {\n case undefined:\n return \"loaded\";\n case \"undefined\":\n return \"not-loaded\";\n case \"loading\":\n return \"loading\";\n case \"ready\":\n return \"loaded\";\n case \"error\":\n return \"error\";\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AbstractLayer.js","sources":["AbstractLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n computed,\n reactive,\n Reactive,\n ReadonlyReactive,\n synchronized\n} from \"@conterra/reactivity-core\";\nimport { createLogger, destroyResource, Resource } from \"@open-pioneer/core\";\nimport { EventsKey } from \"ol/events\";\nimport OlBaseLayer from \"ol/layer/Base\";\nimport OlLayer from \"ol/layer/Layer\";\nimport { unByKey } from \"ol/Observable\";\nimport OlSource from \"ol/source/Source\";\nimport { MapModel } from \"../model/MapModel\";\nimport { InternalConstructorTag } from \"../utils/InternalConstructorTag\";\nimport { AbstractLayerBase } from \"./AbstractLayerBase\";\nimport {\n ATTACH_TO_MAP,\n GET_DEPS,\n getLayerDependencies,\n LAYER_DEPS,\n LayerDependencies,\n SET_VISIBLE\n} from \"./shared/internals\";\nimport { HealthCheckFunction, LayerConfig } from \"./shared/LayerConfig\";\nimport { SimpleLayer, SimpleLayerConfig } from \"./SimpleLayer\";\nimport { Layer, LayerTypes } from \"./unions\";\n\nconst LOG = createLogger(\"map:AbstractLayer\");\n\n/**\n * The load state of a layer.\n *\n * @group Layer Utilities\n **/\nexport type LayerLoadState = \"not-loaded\" | \"loading\" | \"loaded\" | \"error\";\n\n/**\n * Represents an operational layer in the map.\n *\n * These layers always have an associated OpenLayers layer.\n *\n * Instances of this interface cannot be constructed directly; use a real layer\n * class such as {@link SimpleLayer} instead.\n *\n * @group Layers\n */\nexport abstract class AbstractLayer extends AbstractLayerBase {\n // Layer dependencies are present when the LayerFactory API was used to construct the layer.\n // They may currently be undefined for compatibility reasons (in which case they will be used\n // from the map, once connected).\n #deps: LayerDependencies | undefined;\n #olLayer: OlBaseLayer;\n #isBaseLayer: boolean;\n #healthCheck?: string | HealthCheckFunction;\n\n #visible: ReadonlyReactive<boolean>;\n #minResolution: ReadonlyReactive<number>;\n #maxResolution: ReadonlyReactive<number>;\n #minZoom: ReadonlyReactive<number>;\n #maxZoom: ReadonlyReactive<number>;\n #loadState: Reactive<LayerLoadState>;\n\n #stateWatchResource: Resource | undefined;\n\n #visibleInScale: ReadonlyReactive<boolean>;\n\n constructor(\n config: SimpleLayerConfig,\n deps?: LayerDependencies,\n internalTag?: InternalConstructorTag\n ) {\n super(config);\n this.#deps = getLayerDependencies(deps, internalTag);\n this.#olLayer = config.olLayer;\n this.#isBaseLayer = config.isBaseLayer ?? false;\n this.#healthCheck = config.healthCheck;\n this.#visible = synchronized(\n () => this.#olLayer.getVisible(),\n (cb) => {\n const key = this.#olLayer.on(\"change:visible\", cb);\n return () => unByKey(key);\n }\n );\n this.#minResolution = synchronized(\n () => this.#olLayer.getMinResolution(),\n (cb) => {\n const key = this.#olLayer.on(\"change:minResolution\", cb);\n return () => unByKey(key);\n }\n );\n this.#maxResolution = synchronized(\n () => this.#olLayer.getMaxResolution(),\n (cb) => {\n const key = this.#olLayer.on(\"change:maxResolution\", cb);\n return () => unByKey(key);\n }\n );\n this.#minZoom = synchronized(\n () => this.#olLayer.getMinZoom(),\n (cb) => {\n const key = this.#olLayer.on(\"change:minZoom\", cb);\n return () => unByKey(key);\n }\n );\n this.#maxZoom = synchronized(\n () => this.#olLayer.getMaxZoom(),\n (cb) => {\n const key = this.#olLayer.on(\"change:maxZoom\", cb);\n return () => unByKey(key);\n }\n );\n\n this.#loadState = reactive(getSourceState(getSource(this.#olLayer)));\n\n this[SET_VISIBLE](config.visible ?? true); // apply initial visibility\n\n this.#visibleInScale = computed(() => {\n const map = this.nullableMap; // handle case where not in the map yet\n if (!map) {\n return true; // or false? doesn't really matter\n }\n\n const zoom = map.zoomLevel;\n const resolution = map.resolution;\n if (zoom == null || resolution == null) {\n return false;\n }\n\n const parent = this.parent;\n if (parent && parent.type === \"group\" && !parent.visibleInScale) {\n return false;\n }\n\n if (resolution < this.minResolution || resolution >= this.maxResolution) {\n return false;\n }\n\n return zoom > this.minZoom && zoom <= this.maxZoom;\n });\n\n if (config.maxResolution) {\n this.#olLayer.setMaxResolution(config.maxResolution);\n }\n if (config.minResolution) {\n this.#olLayer.setMinResolution(config.minResolution);\n }\n\n if (config.maxZoom) {\n this.#olLayer.setMaxZoom(config.maxZoom);\n }\n if (config.minZoom) {\n this.#olLayer.setMinZoom(config.minZoom);\n }\n }\n\n override destroy() {\n if (this.isDestroyed) {\n return;\n }\n\n this.#stateWatchResource = destroyResource(this.#stateWatchResource);\n this.olLayer.dispose();\n super.destroy();\n }\n\n /**\n * Identifies the type of this layer.\n */\n abstract override readonly type: LayerTypes;\n\n override get visible(): boolean {\n return this.#visible.value;\n }\n\n /**\n * The raw OpenLayers layer.\n */\n get olLayer(): OlBaseLayer {\n return this.#olLayer;\n }\n\n /**\n * True if this layer is a base layer.\n *\n * Only one base layer can be visible at a time.\n */\n get isBaseLayer(): boolean {\n return this.#isBaseLayer;\n }\n\n /**\n * The load state of a layer.\n */\n get loadState(): LayerLoadState {\n return this.#loadState.value;\n }\n\n /**\n * The minimum resolution (inclusive) at which this layer will be visible.\n */\n get minResolution() {\n return this.#minResolution.value;\n }\n\n /**\n * The maximum resolution (exclusive) below which this layer will be visible.\n */\n get maxResolution() {\n return this.#maxResolution.value;\n }\n\n /**\n * The minimum view zoom level (exclusive) above which this layer will be visible.\n */\n get minZoom() {\n return this.#minZoom.value;\n }\n\n /**\n * The maximum view zoom level (inclusive) at which this layer will be visible.\n */\n get maxZoom() {\n return this.#maxZoom.value;\n }\n\n /**\n * Whether the layer is visible in the current map scale or not.\n */\n get visibleInScale(): boolean {\n return this.#visibleInScale.value;\n }\n\n /**\n * The minimum resolution (inclusive) at which this layer will be visible.\n */\n setMinResolution(value: number): void {\n this.#olLayer.setMinResolution(value);\n }\n\n /**\n * The maximum resolution (exclusive) below which this layer will be visible.\n */\n setMaxResolution(value: number): void {\n this.#olLayer.setMaxResolution(value);\n }\n\n /**\n * The minimum view zoom level (exclusive) above which this layer will be visible.\n */\n setMinZoom(value: number): void {\n this.#olLayer.setMinZoom(value);\n }\n\n /**\n * The maximum view zoom level (inclusive) at which this layer will be visible.\n */\n setMaxZoom(value: number): void {\n this.#olLayer.setMaxZoom(value);\n }\n\n /**\n * Called by the map model when the layer is added to the map.\n *\n * @internal\n */\n override [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n\n if (!this.#stateWatchResource) {\n const { initial: initialState, resource: stateWatchResource } = watchLoadState(\n this,\n this.#healthCheck,\n (state) => {\n this.#loadState.value = state;\n }\n );\n this.#stateWatchResource = stateWatchResource;\n this.#loadState.value = initialState;\n }\n }\n\n override setVisible(newVisibility: boolean): void {\n if (this.isBaseLayer) {\n LOG.warn(\n `Cannot change visibility of base layer '${this.id}': use activateBaseLayer() on the map's LayerCollection instead.`\n );\n return;\n }\n\n this[SET_VISIBLE](newVisibility);\n }\n\n /** @internal */\n [SET_VISIBLE](newVisibility: boolean): void {\n if (this.#olLayer.getVisible() !== newVisibility) {\n this.#olLayer.setVisible(newVisibility);\n }\n }\n\n /** @internal */\n [GET_DEPS](): LayerDependencies {\n const deps = this.#deps;\n if (deps) {\n return deps;\n }\n\n const map = this.nullableMap;\n if (map) {\n return map[LAYER_DEPS];\n }\n throw new Error(\n `Layer '${this.id}' has not been attached to a map yet. \"\n + \"Use the LayerFactory to create an instance or add the layer to the map first.`\n );\n }\n}\n\nfunction watchLoadState(\n layer: AbstractLayer,\n healthCheck: LayerConfig[\"healthCheck\"],\n onChange: (newState: LayerLoadState) => void\n): { initial: LayerLoadState; resource: Resource } {\n const olLayer = layer.olLayer;\n\n if (!(olLayer instanceof OlLayer)) {\n // Some layers don't have a source (such as group)\n return {\n initial: \"loaded\",\n resource: {\n destroy() {\n void 0;\n }\n }\n };\n }\n\n let currentSource = getSource(olLayer);\n const currentOlLayerState = getSourceState(currentSource);\n\n let currentLoadState: LayerLoadState = currentOlLayerState;\n let currentHealthState = \"loading\"; // initial state loading until health check finished\n\n // custom health check not needed when OpenLayers already returning an error state\n if (currentOlLayerState !== \"error\") {\n // health check only once during initialization\n doHealthCheck(layer, healthCheck).then((state: LayerLoadState) => {\n currentHealthState = state;\n updateState();\n });\n }\n\n const updateState = () => {\n const olLayerState = getSourceState(currentSource);\n const nextLoadState: LayerLoadState =\n currentHealthState === \"error\" ? \"error\" : olLayerState;\n\n if (currentLoadState !== nextLoadState) {\n currentLoadState = nextLoadState;\n onChange(currentLoadState);\n }\n };\n\n let stateHandle: EventsKey | undefined;\n stateHandle = currentSource?.on(\"change\", () => {\n updateState();\n });\n\n const sourceHandle = olLayer.on(\"change:source\", () => {\n // unsubscribe from old source\n stateHandle && unByKey(stateHandle);\n stateHandle = undefined;\n\n // subscribe to new source and update state\n currentSource = getSource(olLayer);\n stateHandle = currentSource?.on(\"change\", () => {\n updateState();\n });\n updateState();\n });\n return {\n initial: currentLoadState,\n resource: {\n destroy() {\n stateHandle && unByKey(stateHandle);\n unByKey(sourceHandle);\n }\n }\n };\n}\n\nasync function doHealthCheck(\n layer: AbstractLayer,\n healthCheck: LayerConfig[\"healthCheck\"]\n): Promise<LayerLoadState> {\n if (healthCheck == null) {\n return \"loaded\";\n }\n\n let healthCheckFn: HealthCheckFunction;\n if (typeof healthCheck === \"function\") {\n healthCheckFn = healthCheck;\n } else if (typeof healthCheck === \"string\") {\n healthCheckFn = async () => {\n const httpService = layer[GET_DEPS]().httpService;\n const response = await httpService.fetch(healthCheck);\n if (response.ok) {\n return \"loaded\";\n }\n LOG.warn(\n `Health check failed for layer '${layer.id}' (http status ${response.status})`\n );\n return \"error\";\n };\n } else {\n LOG.error(\n `Unexpected object for 'healthCheck' parameter of layer '${layer.id}'`,\n healthCheck\n );\n return \"error\";\n }\n\n try {\n return await healthCheckFn(layer as Layer);\n } catch (e) {\n LOG.warn(`Health check failed for layer '${layer.id}'`, e);\n return \"error\";\n }\n}\n\nfunction getSource(olLayer: OlLayer | OlBaseLayer) {\n if (!(olLayer instanceof OlLayer)) {\n return undefined;\n }\n return (olLayer?.getSource() as OlSource | null) ?? undefined;\n}\n\nfunction getSourceState(olSource: OlSource | undefined) {\n const state = olSource?.getState();\n switch (state) {\n case undefined:\n return \"loaded\";\n case \"undefined\":\n return \"not-loaded\";\n case \"loading\":\n return \"loading\";\n case \"ready\":\n return \"loaded\";\n case \"error\":\n return \"error\";\n }\n}\n"],"names":[],"mappings":"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"}
|
package/layers/WMSLayer.js
CHANGED
|
@@ -147,8 +147,10 @@ class WMSLayer extends AbstractLayer {
|
|
|
147
147
|
const layers = [];
|
|
148
148
|
getNestedSublayer(this.#sublayers.getSublayers(), layers);
|
|
149
149
|
for (const layer of layers) {
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
if (layer.name) {
|
|
151
|
+
const legendUrl = getLegendUrl(capabilities, layer.name);
|
|
152
|
+
layer[SET_LEGEND](legendUrl);
|
|
153
|
+
}
|
|
152
154
|
}
|
|
153
155
|
});
|
|
154
156
|
}).catch((error) => {
|
package/layers/WMSLayer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WMSLayer.js","sources":["WMSLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, computed, ReadonlyReactive, watch } from \"@conterra/reactivity-core\";\nimport {\n createLogger,\n deprecated,\n destroyResource,\n isAbortError,\n Resource\n} from \"@open-pioneer/core\";\nimport { ImageWrapper } from \"ol\";\nimport WMSCapabilities from \"ol/format/WMSCapabilities\";\nimport ImageLayer from \"ol/layer/Image\";\nimport type ImageSource from \"ol/source/Image\";\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport ImageWMS from \"ol/source/ImageWMS\";\nimport type { LayerFactory } from \"../LayerFactory\";\nimport { MapModel } from \"../model/MapModel\";\nimport { fetchText } from \"../utils/fetch\";\nimport { INTERNAL_CONSTRUCTOR_TAG, InternalConstructorTag } from \"../utils/InternalConstructorTag\";\nimport { AbstractLayer } from \"./AbstractLayer\";\nimport {\n ATTACH_TO_MAP,\n ATTACH_TO_PARENT,\n DETACH_FROM_MAP,\n GET_DEPS,\n GET_RAW_SUBLAYERS,\n LayerConstructor,\n LayerDependencies,\n SET_LEGEND\n} from \"./shared/internals\";\nimport { LayerConfig } from \"./shared/LayerConfig\";\nimport { SublayersCollection } from \"./shared/SublayersCollection\";\nimport { getLegendUrl } from \"./wms/getLegendUrl\";\nimport { constructSublayers, WMSSublayer, WMSSublayerConfig } from \"./wms/WMSSublayer\";\n\n/**\n * Configuration options to construct a {@link WMSLayer}.\n *\n * @group Layers\n */\nexport interface WMSLayerConfig extends LayerConfig {\n /** URL of the WMS service. */\n url: string;\n\n /** Configures the layer's sublayers. */\n sublayers?: WMSSublayerConfig[];\n\n /**\n * Additional source options for the layer's WMS source.\n *\n * NOTE: These options are intended for advanced configuration:\n * the WMS Layer manages some of the OpenLayers source options itself.\n */\n sourceOptions?: Partial<WMSSourceOptions>;\n\n /**\n * Whether to automatically fetch capabilities from the service when needed (default: `true`).\n *\n * Setting this to `false` can be useful as a performance optimization when capabilities are not really required by the application.\n * Note that this will disable some features of the WMS layer: for example, the legend URL will not be available.\n */\n fetchCapabilities?: boolean;\n}\n\nconst LOG = createLogger(\"map:WMSLayer\");\n\nconst deprecatedConstructor = deprecated({\n name: \"WMSLayer constructor\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.0.0\",\n alternative: \"use LayerFactory.create() instead\"\n});\n\n/**\n * Displays an OGC Web Map Service (WMS).\n *\n * @group Layers\n */\nexport class WMSLayer extends AbstractLayer {\n #url: string;\n #sublayers: SublayersCollection<WMSSublayer>;\n #layer: ImageLayer<ImageSource>;\n #source: ImageWMS;\n #fetchCapabilities: boolean;\n\n #loadStarted = false;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #capabilities: Record<string, any> | undefined;\n readonly #abortController = new AbortController();\n\n #visibleSublayers: ReadonlyReactive<string[]>;\n #sublayersWatch: Resource | undefined;\n\n /**\n * @deprecated Prefer using {@link LayerFactory.create} instead of calling the constructor directly\n */\n constructor(config: WMSLayerConfig);\n\n /**\n * NOTE: Do not use this overload. Use {@link LayerFactory.create} instead.\n *\n * @internal\n */\n constructor(\n config: WMSLayerConfig,\n deps: LayerDependencies,\n internalTag: InternalConstructorTag\n );\n constructor(\n config: WMSLayerConfig,\n deps?: LayerDependencies,\n internalTag?: InternalConstructorTag\n ) {\n if (!internalTag) {\n deprecatedConstructor();\n }\n\n const layer = new ImageLayer();\n super(\n {\n ...config,\n olLayer: layer\n },\n deps,\n internalTag\n );\n const source = new ImageWMS({\n ...config.sourceOptions,\n url: config.url,\n params: {\n ...config.sourceOptions?.params\n },\n // Use http service to load tiles; needed for authentication etc.\n imageLoadFunction: (wrapper, url) => {\n return this.#loadImage(wrapper, url).catch((error) => {\n LOG.error(`Failed to load tile at '${url}'`, error);\n });\n }\n });\n this.#url = config.url;\n this.#fetchCapabilities = config.fetchCapabilities ?? true;\n this.#source = source;\n this.#layer = layer;\n\n this.#sublayers = new SublayersCollection(\n constructSublayers(config.sublayers),\n INTERNAL_CONSTRUCTOR_TAG\n );\n this.#sublayers\n [GET_RAW_SUBLAYERS]()\n .forEach((sublayer) => sublayer[ATTACH_TO_PARENT](this, this));\n\n this.#visibleSublayers = computed(() => this.#getVisibleLayerNames(), {\n equal(a, b) {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n });\n\n this.#sublayersWatch = watch(\n () => [this.#visibleSublayers.value],\n ([layers]) => {\n this.#updateLayersParam(layers);\n },\n {\n immediate: true\n }\n );\n }\n\n override destroy() {\n this.#abortController.abort();\n this.#sublayersWatch = destroyResource(this.#sublayersWatch);\n super.destroy();\n }\n\n get type() {\n return \"wms\" as const;\n }\n\n get legend() {\n return undefined;\n }\n\n /** The URL of the WMS service that was used during layer construction. */\n get url(): string {\n return this.#url;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n /**\n * Holds the sublayers of this layer.\n */\n get sublayers(): SublayersCollection<WMSSublayer> {\n return this.#sublayers;\n }\n\n get capabilities() {\n return this.#capabilities;\n }\n\n /** @internal */\n [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer[ATTACH_TO_MAP](map);\n }\n\n this.#load();\n }\n\n /** @internal */\n [DETACH_FROM_MAP](): void {\n super[DETACH_FROM_MAP]();\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer[DETACH_FROM_MAP]();\n }\n }\n\n #load() {\n if (this.#loadStarted || !this.#fetchCapabilities) {\n return;\n }\n this.#loadStarted = true;\n\n /** Find all leaf nodes representing a layer in the structure */\n const getNestedSublayer = (sublayers: WMSSublayer[], layers: WMSSublayer[]) => {\n for (const sublayer of sublayers) {\n const nested = sublayer.sublayers.getSublayers();\n if (nested.length) {\n getNestedSublayer(nested, layers);\n } else {\n if (sublayer.name) {\n layers.push(sublayer);\n }\n }\n }\n };\n\n this.#fetchWMSCapabilities()\n .then((result: string) => {\n batch(() => {\n const parser = new WMSCapabilities();\n const capabilities = parser.read(result);\n this.#capabilities = capabilities;\n\n const layers: WMSSublayer[] = [];\n getNestedSublayer(this.#sublayers.getSublayers(), layers);\n\n for (const layer of layers) {\n const legendUrl = getLegendUrl(capabilities, layer.name!);\n layer[SET_LEGEND](legendUrl);\n }\n });\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer '${this.id}' has been destroyed before fetching capabilities`);\n return;\n }\n LOG.error(`Failed to fetch WMS capabilities for layer '${this.id}'`, error);\n });\n }\n\n /**\n * Gathers the visibility of _all_ sublayers and assembles the 'layers' WMS parameter.\n * The parameters are then applied to the WMS source.\n */\n #updateLayersParam(layers: string[]) {\n this.#source.updateParams({\n \"LAYERS\": layers\n });\n\n // only set source if there are visible sublayers, otherwise\n // we send an invalid http request\n const source = layers.length === 0 ? null : this.#source;\n if (this.#layer.getSource() !== source) {\n this.#layer.setSource(source);\n }\n }\n\n #getVisibleLayerNames() {\n const layers: string[] = [];\n const visitSublayer = (sublayer: WMSSublayer) => {\n if (!sublayer.visible) {\n return;\n }\n\n const nestedSublayers = sublayer.sublayers[GET_RAW_SUBLAYERS]();\n if (nestedSublayers.length) {\n for (const nestedSublayer of nestedSublayers) {\n visitSublayer(nestedSublayer);\n }\n } else {\n /**\n * Push sublayer only, if layer name is not an empty string | undefined | ...\n */\n if (sublayer.name) {\n layers.push(sublayer.name);\n }\n }\n };\n\n for (const sublayer of this.sublayers[GET_RAW_SUBLAYERS]()) {\n visitSublayer(sublayer);\n }\n return layers;\n }\n\n async #fetchWMSCapabilities(): Promise<string> {\n const httpService = this[GET_DEPS]().httpService;\n const url = `${this.#url}?LANGUAGE=ger&SERVICE=WMS&REQUEST=GetCapabilities`;\n return fetchText(url, httpService, this.#abortController.signal);\n }\n\n async #loadImage(imageWrapper: ImageWrapper, imageUrl: string): Promise<void> {\n const httpService = this[GET_DEPS]().httpService;\n const image = imageWrapper.getImage() as HTMLImageElement;\n\n const response = await httpService.fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n }\n}\n\n// Ensure layer class is assignable to the constructor interface (there is no \"implements\" for the class itself).\n// eslint-disable-next-line no-constant-condition\nif (false) {\n const check: LayerConstructor<WMSLayerConfig, WMSLayer> = WMSLayer;\n void check;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WMSLayer.js","sources":["WMSLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, computed, ReadonlyReactive, watch } from \"@conterra/reactivity-core\";\nimport {\n createLogger,\n deprecated,\n destroyResource,\n isAbortError,\n Resource\n} from \"@open-pioneer/core\";\nimport { ImageWrapper } from \"ol\";\nimport WMSCapabilities from \"ol/format/WMSCapabilities\";\nimport ImageLayer from \"ol/layer/Image\";\nimport type ImageSource from \"ol/source/Image\";\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport ImageWMS from \"ol/source/ImageWMS\";\nimport type { LayerFactory } from \"../LayerFactory\";\nimport { MapModel } from \"../model/MapModel\";\nimport { fetchText } from \"../utils/fetch\";\nimport { INTERNAL_CONSTRUCTOR_TAG, InternalConstructorTag } from \"../utils/InternalConstructorTag\";\nimport { AbstractLayer } from \"./AbstractLayer\";\nimport {\n ATTACH_TO_MAP,\n ATTACH_TO_PARENT,\n DETACH_FROM_MAP,\n GET_DEPS,\n GET_RAW_SUBLAYERS,\n LayerConstructor,\n LayerDependencies,\n SET_LEGEND\n} from \"./shared/internals\";\nimport { LayerConfig } from \"./shared/LayerConfig\";\nimport { SublayersCollection } from \"./shared/SublayersCollection\";\nimport { getLegendUrl } from \"./wms/getLegendUrl\";\nimport { constructSublayers, WMSSublayer, WMSSublayerConfig } from \"./wms/WMSSublayer\";\n\n/**\n * Configuration options to construct a {@link WMSLayer}.\n *\n * @group Layers\n */\nexport interface WMSLayerConfig extends LayerConfig {\n /** URL of the WMS service. */\n url: string;\n\n /** Configures the layer's sublayers. */\n sublayers?: WMSSublayerConfig[];\n\n /**\n * Additional source options for the layer's WMS source.\n *\n * NOTE: These options are intended for advanced configuration:\n * the WMS Layer manages some of the OpenLayers source options itself.\n */\n sourceOptions?: Partial<WMSSourceOptions>;\n\n /**\n * Whether to automatically fetch capabilities from the service when needed (default: `true`).\n *\n * Setting this to `false` can be useful as a performance optimization when capabilities are not really required by the application.\n * Note that this will disable some features of the WMS layer: for example, the legend URL will not be available.\n */\n fetchCapabilities?: boolean;\n}\n\nconst LOG = createLogger(\"map:WMSLayer\");\n\nconst deprecatedConstructor = deprecated({\n name: \"WMSLayer constructor\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.0.0\",\n alternative: \"use LayerFactory.create() instead\"\n});\n\n/**\n * Displays an OGC Web Map Service (WMS).\n *\n * @group Layers\n */\nexport class WMSLayer extends AbstractLayer {\n #url: string;\n #sublayers: SublayersCollection<WMSSublayer>;\n #layer: ImageLayer<ImageSource>;\n #source: ImageWMS;\n #fetchCapabilities: boolean;\n\n #loadStarted = false;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #capabilities: Record<string, any> | undefined;\n readonly #abortController = new AbortController();\n\n #visibleSublayers: ReadonlyReactive<string[]>;\n #sublayersWatch: Resource | undefined;\n\n /**\n * @deprecated Prefer using {@link LayerFactory.create} instead of calling the constructor directly\n */\n constructor(config: WMSLayerConfig);\n\n /**\n * NOTE: Do not use this overload. Use {@link LayerFactory.create} instead.\n *\n * @internal\n */\n constructor(\n config: WMSLayerConfig,\n deps: LayerDependencies,\n internalTag: InternalConstructorTag\n );\n constructor(\n config: WMSLayerConfig,\n deps?: LayerDependencies,\n internalTag?: InternalConstructorTag\n ) {\n if (!internalTag) {\n deprecatedConstructor();\n }\n\n const layer = new ImageLayer();\n\n super(\n {\n ...config,\n olLayer: layer\n },\n deps,\n internalTag\n );\n\n const source = new ImageWMS({\n ...config.sourceOptions,\n url: config.url,\n params: {\n ...config.sourceOptions?.params\n },\n // Use http service to load tiles; needed for authentication etc.\n imageLoadFunction: (wrapper, url) => {\n return this.#loadImage(wrapper, url).catch((error) => {\n LOG.error(`Failed to load tile at '${url}'`, error);\n });\n }\n });\n this.#url = config.url;\n this.#fetchCapabilities = config.fetchCapabilities ?? true;\n this.#source = source;\n this.#layer = layer;\n\n this.#sublayers = new SublayersCollection(\n constructSublayers(config.sublayers),\n INTERNAL_CONSTRUCTOR_TAG\n );\n this.#sublayers\n [GET_RAW_SUBLAYERS]()\n .forEach((sublayer) => sublayer[ATTACH_TO_PARENT](this, this));\n\n this.#visibleSublayers = computed(() => this.#getVisibleLayerNames(), {\n equal(a, b) {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n });\n\n this.#sublayersWatch = watch(\n () => [this.#visibleSublayers.value],\n ([layers]) => {\n this.#updateLayersParam(layers);\n },\n {\n immediate: true\n }\n );\n }\n\n override destroy() {\n this.#abortController.abort();\n this.#sublayersWatch = destroyResource(this.#sublayersWatch);\n super.destroy();\n }\n\n get type() {\n return \"wms\" as const;\n }\n\n get legend() {\n return undefined;\n }\n\n /** The URL of the WMS service that was used during layer construction. */\n get url(): string {\n return this.#url;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n /**\n * Holds the sublayers of this layer.\n */\n get sublayers(): SublayersCollection<WMSSublayer> {\n return this.#sublayers;\n }\n\n get capabilities() {\n return this.#capabilities;\n }\n\n /** @internal */\n [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer[ATTACH_TO_MAP](map);\n }\n\n this.#load();\n }\n\n /** @internal */\n [DETACH_FROM_MAP](): void {\n super[DETACH_FROM_MAP]();\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer[DETACH_FROM_MAP]();\n }\n }\n\n #load() {\n if (this.#loadStarted || !this.#fetchCapabilities) {\n return;\n }\n this.#loadStarted = true;\n\n /** Find all leaf nodes representing a layer in the structure */\n const getNestedSublayer = (sublayers: WMSSublayer[], layers: WMSSublayer[]) => {\n for (const sublayer of sublayers) {\n const nested = sublayer.sublayers.getSublayers();\n if (nested.length) {\n getNestedSublayer(nested, layers);\n } else {\n if (sublayer.name) {\n layers.push(sublayer);\n }\n }\n }\n };\n\n this.#fetchWMSCapabilities()\n .then((result: string) => {\n batch(() => {\n const parser = new WMSCapabilities();\n const capabilities = parser.read(result);\n this.#capabilities = capabilities;\n\n const layers: WMSSublayer[] = [];\n getNestedSublayer(this.#sublayers.getSublayers(), layers);\n\n for (const layer of layers) {\n if (layer.name) {\n const legendUrl = getLegendUrl(capabilities, layer.name);\n layer[SET_LEGEND](legendUrl);\n }\n }\n });\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer '${this.id}' has been destroyed before fetching capabilities`);\n return;\n }\n LOG.error(`Failed to fetch WMS capabilities for layer '${this.id}'`, error);\n });\n }\n\n /**\n * Gathers the visibility of _all_ sublayers and assembles the 'layers' WMS parameter.\n * The parameters are then applied to the WMS source.\n */\n #updateLayersParam(layers: string[]) {\n this.#source.updateParams({\n \"LAYERS\": layers\n });\n\n // only set source if there are visible sublayers, otherwise\n // we send an invalid http request\n const source = layers.length === 0 ? null : this.#source;\n if (this.#layer.getSource() !== source) {\n this.#layer.setSource(source);\n }\n }\n\n #getVisibleLayerNames() {\n const layers: string[] = [];\n const visitSublayer = (sublayer: WMSSublayer) => {\n if (!sublayer.visible) {\n return;\n }\n\n const nestedSublayers = sublayer.sublayers[GET_RAW_SUBLAYERS]();\n if (nestedSublayers.length) {\n for (const nestedSublayer of nestedSublayers) {\n visitSublayer(nestedSublayer);\n }\n } else {\n /**\n * Push sublayer only, if layer name is not an empty string | undefined | ...\n */\n if (sublayer.name) {\n layers.push(sublayer.name);\n }\n }\n };\n\n for (const sublayer of this.sublayers[GET_RAW_SUBLAYERS]()) {\n visitSublayer(sublayer);\n }\n return layers;\n }\n\n async #fetchWMSCapabilities(): Promise<string> {\n const httpService = this[GET_DEPS]().httpService;\n const url = `${this.#url}?LANGUAGE=ger&SERVICE=WMS&REQUEST=GetCapabilities`;\n return fetchText(url, httpService, this.#abortController.signal);\n }\n\n async #loadImage(imageWrapper: ImageWrapper, imageUrl: string): Promise<void> {\n const httpService = this[GET_DEPS]().httpService;\n const image = imageWrapper.getImage() as HTMLImageElement;\n\n const response = await httpService.fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n }\n}\n\n// Ensure layer class is assignable to the constructor interface (there is no \"implements\" for the class itself).\n// eslint-disable-next-line no-constant-condition\nif (false) {\n const check: LayerConstructor<WMSLayerConfig, WMSLayer> = WMSLayer;\n void check;\n}\n"],"names":[],"mappings":"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"}
|
package/layers/WMTSLayer.js
CHANGED
package/layers/WMTSLayer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WMTSLayer.js","sources":["WMTSLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { reactive } from \"@conterra/reactivity-core\";\nimport { createLogger, deprecated, isAbortError } from \"@open-pioneer/core\";\nimport { ImageTile } from \"ol\";\nimport Tile from \"ol/Tile\";\nimport TileState from \"ol/TileState\";\nimport WMTSCapabilities from \"ol/format/WMTSCapabilities\";\nimport TileLayer from \"ol/layer/Tile\";\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport type TileSourceType from \"ol/source/Tile\";\nimport WMTS, { optionsFromCapabilities } from \"ol/source/WMTS\";\nimport type { LayerFactory } from \"../LayerFactory\";\nimport { MapModel } from \"../model/MapModel\";\nimport { InternalConstructorTag } from \"../utils/InternalConstructorTag\";\nimport { fetchText } from \"../utils/fetch\";\nimport { AbstractLayer } from \"./AbstractLayer\";\nimport { LayerConfig } from \"./shared/LayerConfig\";\nimport { ATTACH_TO_MAP, GET_DEPS, LayerConstructor, LayerDependencies } from \"./shared/internals\";\nimport { getLegendUrl } from \"./wmts/getLegendUrl\";\n\n/**\n * Configuration options supported by {@link WMTSLayer}.\n *\n * @group Layers\n */\nexport interface WMTSLayerConfig extends LayerConfig {\n /** URL of the WMTS service. */\n url: string;\n\n /** The name of the WMTS layer in the service's capabilities. */\n name: string;\n\n /** The name of the tile matrix set in the service's capabilities. */\n matrixSet: string;\n\n /**\n * Additional source options for the layer's WMTS source.\n *\n * NOTE: These options are intended for advanced configuration:\n * the WMTS Layer manages some of the OpenLayers source options itself.\n */\n sourceOptions?: Partial<WMSSourceOptions>;\n}\n\nconst LOG = createLogger(\"map:WMTSLayer\");\n\nconst deprecatedConstructor = deprecated({\n name: \"WMTSLayer constructor\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.0.0\",\n alternative: \"use LayerFactory.create() instead\"\n});\n\n/**\n * Displays an OGC Web Map Tile Service (WMTS).\n *\n * @group Layers\n */\nexport class WMTSLayer extends AbstractLayer {\n #url: string;\n #name: string;\n #matrixSet: string;\n #layer: TileLayer<TileSourceType>;\n #source: WMTS | undefined;\n #sourceOptions?: Partial<WMSSourceOptions>;\n #legend = reactive<string | undefined>();\n\n #loadStarted = false;\n\n readonly #abortController = new AbortController();\n\n /**\n * @deprecated Prefer using {@link LayerFactory.create} instead of calling the constructor directly\n */\n constructor(config: WMTSLayerConfig);\n\n /**\n * NOTE: Do not use this overload. Use {@link LayerFactory.create} instead.\n *\n * @internal\n */\n constructor(\n config: WMTSLayerConfig,\n deps: LayerDependencies,\n internalTag: InternalConstructorTag\n );\n\n constructor(\n config: WMTSLayerConfig,\n deps?: LayerDependencies,\n internalTag?: InternalConstructorTag\n ) {\n if (!internalTag) {\n deprecatedConstructor();\n }\n\n const layer = new TileLayer();\n super(\n {\n ...config,\n olLayer: layer\n },\n deps,\n internalTag\n );\n this.#url = config.url;\n this.#name = config.name;\n this.#layer = layer;\n this.#matrixSet = config.matrixSet;\n this.#sourceOptions = config.sourceOptions;\n }\n\n destroy(): void {\n this.#abortController.abort();\n super.destroy();\n }\n\n get type() {\n return \"wmts\" as const;\n }\n\n /** URL of the WMTS service. */\n override get legend(): string | undefined {\n return this.#legend.value;\n }\n\n override get sublayers(): undefined {\n return undefined;\n }\n\n override get layers(): undefined {\n return undefined;\n }\n\n get url() {\n return this.#url;\n }\n\n /** The name of the WMTS layer in the service's capabilities. */\n get name() {\n return this.#name;\n }\n\n /** The name of the tile matrix set in the service's capabilities. */\n get matrixSet() {\n return this.#matrixSet;\n }\n\n override [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n this.#load();\n }\n\n #load() {\n if (this.#loadStarted) {\n return;\n }\n this.#loadStarted = true;\n this.#fetchWMTSCapabilities()\n .then((result: string) => {\n const parser = new WMTSCapabilities();\n const capabilities = parser.read(result);\n const options = optionsFromCapabilities(capabilities, {\n layer: this.#name,\n matrixSet: this.#matrixSet\n });\n if (!options) {\n throw new Error(\"Layer was not found in capabilities\");\n }\n const source = new WMTS({\n ...options,\n ...this.#sourceOptions,\n tileLoadFunction: (tile, tileUrl) => {\n this.#loadTile(tile, tileUrl);\n }\n });\n this.#source = source;\n this.#layer.setSource(this.#source);\n const activeStyleId = source.getStyle();\n const legendUrl = getLegendUrl(capabilities, this.name, activeStyleId);\n this.#legend.value = legendUrl;\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer ${this.name} has been destroyed before fetching the data`);\n LOG.debug(`Layer ${this.name} has been destroyed before fetching the data`);\n return;\n }\n LOG.error(`Failed fetching WMTS capabilities for Layer ${this.name}`, error);\n });\n }\n\n async #fetchWMTSCapabilities(): Promise<string> {\n const httpService = this[GET_DEPS]().httpService;\n return fetchText(this.#url, httpService, this.#abortController.signal);\n }\n\n async #loadTile(tile: Tile, tileUrl: string): Promise<void> {\n const httpService = this[GET_DEPS]().httpService;\n try {\n if (!(tile instanceof ImageTile)) {\n throw new Error(\"Only 'ImageTile' is supported for now.\");\n }\n\n const image = tile.getImage();\n if (!isHtmlImage(image)) {\n // Could also be canvas or video\n throw new Error(\"Only <img> tags are supported as tiles for now.\");\n }\n\n const response = await httpService.fetch(tileUrl);\n if (!response.ok) {\n throw new Error(`Tile request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n } catch (e) {\n tile.setState(TileState.ERROR);\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load tile\", e);\n }\n }\n }\n}\n\n// Ensure layer class is assignable to the constructor interface (there is no \"implements\" for the class itself).\n// eslint-disable-next-line no-constant-condition\nif (false) {\n const check: LayerConstructor<WMTSLayerConfig, WMTSLayer> = WMTSLayer;\n void check;\n}\n\nfunction isHtmlImage(htmlElement: HTMLElement): htmlElement is HTMLImageElement {\n return htmlElement.tagName === \"IMG\";\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WMTSLayer.js","sources":["WMTSLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { reactive } from \"@conterra/reactivity-core\";\nimport { createLogger, deprecated, isAbortError } from \"@open-pioneer/core\";\nimport { ImageTile } from \"ol\";\nimport Tile from \"ol/Tile\";\nimport TileState from \"ol/TileState\";\nimport WMTSCapabilities from \"ol/format/WMTSCapabilities\";\nimport TileLayer from \"ol/layer/Tile\";\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport type TileSourceType from \"ol/source/Tile\";\nimport WMTS, { optionsFromCapabilities } from \"ol/source/WMTS\";\nimport type { LayerFactory } from \"../LayerFactory\";\nimport { MapModel } from \"../model/MapModel\";\nimport { InternalConstructorTag } from \"../utils/InternalConstructorTag\";\nimport { fetchText } from \"../utils/fetch\";\nimport { AbstractLayer } from \"./AbstractLayer\";\nimport { LayerConfig } from \"./shared/LayerConfig\";\nimport { ATTACH_TO_MAP, GET_DEPS, LayerConstructor, LayerDependencies } from \"./shared/internals\";\nimport { getLegendUrl } from \"./wmts/getLegendUrl\";\n\n/**\n * Configuration options supported by {@link WMTSLayer}.\n *\n * @group Layers\n */\nexport interface WMTSLayerConfig extends LayerConfig {\n /** URL of the WMTS service. */\n url: string;\n\n /** The name of the WMTS layer in the service's capabilities. */\n name: string;\n\n /** The name of the tile matrix set in the service's capabilities. */\n matrixSet: string;\n\n /**\n * Additional source options for the layer's WMTS source.\n *\n * NOTE: These options are intended for advanced configuration:\n * the WMTS Layer manages some of the OpenLayers source options itself.\n */\n sourceOptions?: Partial<WMSSourceOptions>;\n}\n\nconst LOG = createLogger(\"map:WMTSLayer\");\n\nconst deprecatedConstructor = deprecated({\n name: \"WMTSLayer constructor\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.0.0\",\n alternative: \"use LayerFactory.create() instead\"\n});\n\n/**\n * Displays an OGC Web Map Tile Service (WMTS).\n *\n * @group Layers\n */\nexport class WMTSLayer extends AbstractLayer {\n #url: string;\n #name: string;\n #matrixSet: string;\n #layer: TileLayer<TileSourceType>;\n #source: WMTS | undefined;\n #sourceOptions?: Partial<WMSSourceOptions>;\n #legend = reactive<string | undefined>();\n\n #loadStarted = false;\n\n readonly #abortController = new AbortController();\n\n /**\n * @deprecated Prefer using {@link LayerFactory.create} instead of calling the constructor directly\n */\n constructor(config: WMTSLayerConfig);\n\n /**\n * NOTE: Do not use this overload. Use {@link LayerFactory.create} instead.\n *\n * @internal\n */\n constructor(\n config: WMTSLayerConfig,\n deps: LayerDependencies,\n internalTag: InternalConstructorTag\n );\n\n constructor(\n config: WMTSLayerConfig,\n deps?: LayerDependencies,\n internalTag?: InternalConstructorTag\n ) {\n if (!internalTag) {\n deprecatedConstructor();\n }\n\n const layer = new TileLayer();\n super(\n {\n ...config,\n olLayer: layer\n },\n deps,\n internalTag\n );\n this.#url = config.url;\n this.#name = config.name;\n this.#layer = layer;\n this.#matrixSet = config.matrixSet;\n this.#sourceOptions = config.sourceOptions;\n }\n\n destroy(): void {\n this.#abortController.abort();\n super.destroy();\n }\n\n get type() {\n return \"wmts\" as const;\n }\n\n /** URL of the WMTS service. */\n override get legend(): string | undefined {\n return this.#legend.value;\n }\n\n override get sublayers(): undefined {\n return undefined;\n }\n\n override get layers(): undefined {\n return undefined;\n }\n\n get url() {\n return this.#url;\n }\n\n /** The name of the WMTS layer in the service's capabilities. */\n get name() {\n return this.#name;\n }\n\n /** The name of the tile matrix set in the service's capabilities. */\n get matrixSet() {\n return this.#matrixSet;\n }\n\n override [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n this.#load();\n }\n\n #load() {\n if (this.#loadStarted) {\n return;\n }\n this.#loadStarted = true;\n this.#fetchWMTSCapabilities()\n .then((result: string) => {\n const parser = new WMTSCapabilities();\n const capabilities = parser.read(result);\n const options = optionsFromCapabilities(capabilities, {\n layer: this.#name,\n matrixSet: this.#matrixSet\n });\n if (!options) {\n throw new Error(\"Layer was not found in capabilities\");\n }\n const source = new WMTS({\n ...options,\n ...this.#sourceOptions,\n tileLoadFunction: (tile, tileUrl) => {\n this.#loadTile(tile, tileUrl);\n }\n });\n this.#source = source;\n this.#layer.setSource(this.#source);\n const activeStyleId = source.getStyle();\n const legendUrl = getLegendUrl(capabilities, this.name, activeStyleId);\n this.#legend.value = legendUrl;\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer ${this.name} has been destroyed before fetching the data`);\n LOG.debug(`Layer ${this.name} has been destroyed before fetching the data`);\n return;\n }\n LOG.error(`Failed fetching WMTS capabilities for Layer ${this.name}`, error);\n });\n }\n\n async #fetchWMTSCapabilities(): Promise<string> {\n const httpService = this[GET_DEPS]().httpService;\n return fetchText(this.#url, httpService, this.#abortController.signal);\n }\n\n async #loadTile(tile: Tile, tileUrl: string): Promise<void> {\n const httpService = this[GET_DEPS]().httpService;\n try {\n if (!(tile instanceof ImageTile)) {\n throw new Error(\"Only 'ImageTile' is supported for now.\");\n }\n\n const image = tile.getImage();\n if (!isHtmlImage(image)) {\n // Could also be canvas or video\n throw new Error(\"Only <img> tags are supported as tiles for now.\");\n }\n\n const response = await httpService.fetch(tileUrl);\n if (!response.ok) {\n throw new Error(`Tile request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n } catch (e) {\n tile.setState(TileState.ERROR);\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load tile\", e);\n }\n }\n }\n}\n\n// Ensure layer class is assignable to the constructor interface (there is no \"implements\" for the class itself).\n// eslint-disable-next-line no-constant-condition\nif (false) {\n const check: LayerConstructor<WMTSLayerConfig, WMTSLayer> = WMTSLayer;\n void check;\n}\n\nfunction isHtmlImage(htmlElement: HTMLElement | OffscreenCanvas): htmlElement is HTMLImageElement {\n return \"tagName\" in htmlElement && htmlElement.tagName === \"IMG\";\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,22 @@ export interface LayerConfig extends LayerBaseConfig {
|
|
|
56
56
|
* or a {@link HealthCheckFunction} performing a custom check and returning the state.
|
|
57
57
|
*/
|
|
58
58
|
healthCheck?: string | HealthCheckFunction;
|
|
59
|
+
/**
|
|
60
|
+
* Optional property to restrict the visibility of a layer to a minimum resolution (inclusive).
|
|
61
|
+
*/
|
|
62
|
+
minResolution?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Optional property to restrict the visibility of a layer to a maximum resolution (exclusive).
|
|
65
|
+
*/
|
|
66
|
+
maxResolution?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Optional property to restrict the visibility of a layer to a minimum zoom level (inclusive).
|
|
69
|
+
*/
|
|
70
|
+
minZoom?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Optional property to restrict the visibility of a layer to a maximum zoom level (exclusive).
|
|
73
|
+
*/
|
|
74
|
+
maxZoom?: number;
|
|
59
75
|
}
|
|
60
76
|
/**
|
|
61
77
|
* Custom function to check the state of a layer and returning a "loaded" or "error".
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WMSSublayer.js","sources":["WMSSublayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Reactive, reactive } from \"@conterra/reactivity-core\";\nimport { MapModel } from \"../../model/MapModel\";\nimport { AbstractLayerBase } from \"../AbstractLayerBase\";\nimport {\n ATTACH_TO_MAP,\n ATTACH_TO_PARENT,\n DETACH_FROM_MAP,\n GET_RAW_SUBLAYERS,\n SET_LEGEND\n} from \"../shared/internals\";\nimport {\n assertInternalConstructor,\n INTERNAL_CONSTRUCTOR_TAG,\n InternalConstructorTag\n} from \"../../utils/InternalConstructorTag\";\nimport { LayerBaseConfig } from \"../shared/LayerConfig\";\nimport { SublayerBaseType } from \"../shared/SublayerBaseType\";\nimport { SublayersCollection } from \"../shared/SublayersCollection\";\nimport { WMSLayer } from \"../WMSLayer\";\n\n/**\n * Configuration options to construct the sublayers of a {@link WMSLayer}.\n *\n * @group Layers\n */\nexport interface WMSSublayerConfig extends LayerBaseConfig {\n /**\n * The name of the WMS sublayer in the service's capabilities.\n * Not mandatory, e.g. for WMS group layer. See [WMS spec](https://www.ogc.org/standard/wms/).\n */\n name?: string;\n\n /** Configuration for nested sublayers. */\n sublayers?: WMSSublayerConfig[];\n}\n\n/**\n * Represents a sublayer of a {@link WMSLayer}.\n *\n * @group Layers\n */\nexport class WMSSublayer extends AbstractLayerBase implements SublayerBaseType {\n #parent: WMSSublayer | WMSLayer | undefined;\n #parentLayer: WMSLayer | undefined;\n #name: string | undefined;\n #legend = reactive<string | undefined>();\n #sublayers: SublayersCollection<WMSSublayer>;\n #visible: Reactive<boolean>;\n\n /**\n * @internal\n */\n constructor(config: WMSSublayerConfig, tag: InternalConstructorTag) {\n assertInternalConstructor(tag);\n\n super(config);\n this.#name = config.name;\n this.#visible = reactive(config.visible ?? true);\n this.#sublayers = new SublayersCollection(\n constructSublayers(config.sublayers),\n INTERNAL_CONSTRUCTOR_TAG\n );\n }\n\n override get type() {\n return \"wms-sublayer\" as const;\n }\n\n /**\n * The name of the WMS sublayer in the service's capabilities.\n *\n * Is optional as a WMS group layer in a WMS service does not need to have a name.\n */\n get name(): string | undefined {\n return this.#name;\n }\n\n override get layers(): undefined {\n return undefined;\n }\n\n override get sublayers(): SublayersCollection<WMSSublayer> {\n return this.#sublayers;\n }\n\n override get parent(): WMSSublayer | WMSLayer {\n const parent = this.#parent;\n if (!parent) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parent;\n }\n\n get parentLayer(): WMSLayer {\n const parentLayer = this.#parentLayer;\n if (!parentLayer) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parentLayer;\n }\n\n override get legend(): string | undefined {\n return this.#legend.value;\n }\n\n override get visible(): boolean {\n return this.#visible.value;\n }\n\n /**\n * Called by the parent layer when it is attached to the map to attach all sublayers.\n *\n * @internal\n */\n override [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n\n // Recurse into nested sublayers\n for (const sublayer of this.sublayers[GET_RAW_SUBLAYERS]()) {\n sublayer[ATTACH_TO_MAP](map);\n }\n }\n\n /** @internal */\n override [DETACH_FROM_MAP](): void {\n super[DETACH_FROM_MAP]();\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer[DETACH_FROM_MAP]();\n }\n }\n\n /**\n * Attaches this sublayer to its parent _layer_ and its immediate parent _layer or sublayer_.\n *\n * @internal\n */\n [ATTACH_TO_PARENT](parentLayer: WMSLayer, parent: WMSLayer | WMSSublayer): void {\n if (this.#parent) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent '${this.#parent.id}'`\n );\n }\n this.#parent = parent;\n\n if (this.#parentLayer) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent layer '${this.#parentLayer.id}'`\n );\n }\n this.#parentLayer = parentLayer;\n\n // Recurse into nested sublayers\n for (const sublayer of this.sublayers[GET_RAW_SUBLAYERS]()) {\n sublayer[ATTACH_TO_PARENT](parentLayer, this);\n }\n }\n\n /**\n * Called by the parent layer to update the legend on load.\n *\n * @internal\n */\n [SET_LEGEND](legendUrl: string | undefined) {\n this.#legend.value = legendUrl;\n }\n\n override setVisible(newVisibility: boolean): void {\n this.#visible.value = newVisibility;\n }\n}\n\n/**\n * Constructs a tree of wms sublayers from a nested configuration object.\n */\nexport function constructSublayers(sublayerConfigs: WMSSublayerConfig[] = []): WMSSublayer[] {\n const sublayers: WMSSublayer[] = [];\n try {\n for (const sublayerConfig of sublayerConfigs) {\n sublayers.push(new WMSSublayer(sublayerConfig, INTERNAL_CONSTRUCTOR_TAG));\n }\n return sublayers;\n } catch (e) {\n // Ensure previous sublayers are destroyed if a single constructor throws\n while (sublayers.length) {\n const layer = sublayers.pop()
|
|
1
|
+
{"version":3,"file":"WMSSublayer.js","sources":["WMSSublayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Reactive, reactive } from \"@conterra/reactivity-core\";\nimport { MapModel } from \"../../model/MapModel\";\nimport { AbstractLayerBase } from \"../AbstractLayerBase\";\nimport {\n ATTACH_TO_MAP,\n ATTACH_TO_PARENT,\n DETACH_FROM_MAP,\n GET_RAW_SUBLAYERS,\n SET_LEGEND\n} from \"../shared/internals\";\nimport {\n assertInternalConstructor,\n INTERNAL_CONSTRUCTOR_TAG,\n InternalConstructorTag\n} from \"../../utils/InternalConstructorTag\";\nimport { LayerBaseConfig } from \"../shared/LayerConfig\";\nimport { SublayerBaseType } from \"../shared/SublayerBaseType\";\nimport { SublayersCollection } from \"../shared/SublayersCollection\";\nimport { WMSLayer } from \"../WMSLayer\";\n\n/**\n * Configuration options to construct the sublayers of a {@link WMSLayer}.\n *\n * @group Layers\n */\nexport interface WMSSublayerConfig extends LayerBaseConfig {\n /**\n * The name of the WMS sublayer in the service's capabilities.\n * Not mandatory, e.g. for WMS group layer. See [WMS spec](https://www.ogc.org/standard/wms/).\n */\n name?: string;\n\n /** Configuration for nested sublayers. */\n sublayers?: WMSSublayerConfig[];\n}\n\n/**\n * Represents a sublayer of a {@link WMSLayer}.\n *\n * @group Layers\n */\nexport class WMSSublayer extends AbstractLayerBase implements SublayerBaseType {\n #parent: WMSSublayer | WMSLayer | undefined;\n #parentLayer: WMSLayer | undefined;\n #name: string | undefined;\n #legend = reactive<string | undefined>();\n #sublayers: SublayersCollection<WMSSublayer>;\n #visible: Reactive<boolean>;\n\n /**\n * @internal\n */\n constructor(config: WMSSublayerConfig, tag: InternalConstructorTag) {\n assertInternalConstructor(tag);\n\n super(config);\n this.#name = config.name;\n this.#visible = reactive(config.visible ?? true);\n this.#sublayers = new SublayersCollection(\n constructSublayers(config.sublayers),\n INTERNAL_CONSTRUCTOR_TAG\n );\n }\n\n override get type() {\n return \"wms-sublayer\" as const;\n }\n\n /**\n * The name of the WMS sublayer in the service's capabilities.\n *\n * Is optional as a WMS group layer in a WMS service does not need to have a name.\n */\n get name(): string | undefined {\n return this.#name;\n }\n\n override get layers(): undefined {\n return undefined;\n }\n\n override get sublayers(): SublayersCollection<WMSSublayer> {\n return this.#sublayers;\n }\n\n override get parent(): WMSSublayer | WMSLayer {\n const parent = this.#parent;\n if (!parent) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parent;\n }\n\n get parentLayer(): WMSLayer {\n const parentLayer = this.#parentLayer;\n if (!parentLayer) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parentLayer;\n }\n\n override get legend(): string | undefined {\n return this.#legend.value;\n }\n\n override get visible(): boolean {\n return this.#visible.value;\n }\n\n /**\n * Called by the parent layer when it is attached to the map to attach all sublayers.\n *\n * @internal\n */\n override [ATTACH_TO_MAP](map: MapModel): void {\n super[ATTACH_TO_MAP](map);\n\n // Recurse into nested sublayers\n for (const sublayer of this.sublayers[GET_RAW_SUBLAYERS]()) {\n sublayer[ATTACH_TO_MAP](map);\n }\n }\n\n /** @internal */\n override [DETACH_FROM_MAP](): void {\n super[DETACH_FROM_MAP]();\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer[DETACH_FROM_MAP]();\n }\n }\n\n /**\n * Attaches this sublayer to its parent _layer_ and its immediate parent _layer or sublayer_.\n *\n * @internal\n */\n [ATTACH_TO_PARENT](parentLayer: WMSLayer, parent: WMSLayer | WMSSublayer): void {\n if (this.#parent) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent '${this.#parent.id}'`\n );\n }\n this.#parent = parent;\n\n if (this.#parentLayer) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent layer '${this.#parentLayer.id}'`\n );\n }\n this.#parentLayer = parentLayer;\n\n // Recurse into nested sublayers\n for (const sublayer of this.sublayers[GET_RAW_SUBLAYERS]()) {\n sublayer[ATTACH_TO_PARENT](parentLayer, this);\n }\n }\n\n /**\n * Called by the parent layer to update the legend on load.\n *\n * @internal\n */\n [SET_LEGEND](legendUrl: string | undefined) {\n this.#legend.value = legendUrl;\n }\n\n override setVisible(newVisibility: boolean): void {\n this.#visible.value = newVisibility;\n }\n}\n\n/**\n * Constructs a tree of wms sublayers from a nested configuration object.\n */\nexport function constructSublayers(sublayerConfigs: WMSSublayerConfig[] = []): WMSSublayer[] {\n const sublayers: WMSSublayer[] = [];\n try {\n for (const sublayerConfig of sublayerConfigs) {\n sublayers.push(new WMSSublayer(sublayerConfig, INTERNAL_CONSTRUCTOR_TAG));\n }\n return sublayers;\n } catch (e) {\n // Ensure previous sublayers are destroyed if a single constructor throws\n while (sublayers.length) {\n const layer = sublayers.pop();\n layer?.destroy();\n }\n throw new Error(\"Failed to construct sublayers.\", { cause: e });\n }\n}\n"],"names":[],"mappings":"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"}
|