@open-pioneer/map 1.3.0-dev.20260422120518 → 1.3.0-dev.20260519140411
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 +5 -1
- package/MapRegistry.d.ts +1 -1
- package/MapRegistry.js +9 -4
- package/MapRegistry.js.map +1 -1
- package/README.md +2 -12
- package/layers/WMSLayer.d.ts +12 -0
- package/layers/WMSLayer.js +13 -0
- package/layers/WMSLayer.js.map +1 -1
- package/layers/WMTSLayer.d.ts +7 -1
- package/layers/WMTSLayer.js +10 -1
- package/layers/WMTSLayer.js.map +1 -1
- package/model/MapAttributions.d.ts +2 -1
- package/model/MapAttributions.js +11 -2
- package/model/MapAttributions.js.map +1 -1
- package/model/MapModel.d.ts +2 -1
- package/model/MapModel.js +1 -1
- package/model/MapModel.js.map +1 -1
- package/model/createMapModel.d.ts +2 -1
- package/model/createMapModel.js +6 -6
- package/model/createMapModel.js.map +1 -1
- package/package.json +13 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @open-pioneer/map
|
|
2
2
|
|
|
3
|
-
## 1.3.0-dev.
|
|
3
|
+
## 1.3.0-dev.20260519140411
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- 9b5d5f3: Support for new common container props (role, aria-\*, data-\* and css)
|
|
9
9
|
- c62698d: Add `MapConfig.showAttributions` property to explicitly show or hide the default attributions widget.
|
|
10
10
|
`showAttributions: false` is intended for situations where the map's attributions are displayed in a custom widget.
|
|
11
|
+
- 194f2ab: Add `olSource` property to layer classes that manage their own sources (WMS, WMTS).
|
|
11
12
|
- fcbd505: WMSLayer, WMTSLayer: Derive `attributions` from service capabilities if no explicit attributions have been configured.
|
|
12
13
|
- 2ceb1ca: MapModel: implement new `loading` property.
|
|
13
14
|
This property is `true` if the map is currently loading any resources, `false` otherwise.
|
|
@@ -33,8 +34,11 @@
|
|
|
33
34
|
|
|
34
35
|
### Patch Changes
|
|
35
36
|
|
|
37
|
+
- 989144d: update packages for hmr i18n usage
|
|
36
38
|
- 36da1be: Do not animate the view when changing the map padding during initialization.
|
|
37
39
|
- 30f75bf: Fix map center / map extent not being animated correctly if view padding changes multiple times in short succession (see [#587](https://github.com/open-pioneer/trails-openlayers-base-packages/issues/587)).
|
|
40
|
+
- 28cf317: Fix baselayer documentation of the map package: use `olLayer` instead of `layer`.
|
|
41
|
+
- 8e526b1: Removed `stopEvents` documentation from the map package README
|
|
38
42
|
- 4bcc8ce: Prevent update of `olMap.padding` by MapContainer if viewPadding did not change.
|
|
39
43
|
This caused running map animation to be cancelled.
|
|
40
44
|
|
package/MapRegistry.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ interface References {
|
|
|
54
54
|
export declare class MapRegistry implements Service {
|
|
55
55
|
#private;
|
|
56
56
|
[DECLARE_SERVICE_INTERFACE]: "map.MapRegistry";
|
|
57
|
-
constructor({ references,
|
|
57
|
+
constructor({ references, currentIntl }: ServiceOptions<References>);
|
|
58
58
|
destroy(): void;
|
|
59
59
|
/**
|
|
60
60
|
* Returns the map model associated with the given id.
|
package/MapRegistry.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createMapModel } from './model/createMapModel.js';
|
|
|
6
6
|
|
|
7
7
|
const LOG = createLogger(sourceId);
|
|
8
8
|
class MapRegistry {
|
|
9
|
-
#
|
|
9
|
+
#currentIntl;
|
|
10
10
|
#httpService;
|
|
11
11
|
#layerFactory;
|
|
12
12
|
#configProviders = /* @__PURE__ */ new Map();
|
|
@@ -14,8 +14,8 @@ class MapRegistry {
|
|
|
14
14
|
#modelCreationJobs = /* @__PURE__ */ new Map();
|
|
15
15
|
#modelsByOlMap = /* @__PURE__ */ new WeakMap();
|
|
16
16
|
#destroyed = false;
|
|
17
|
-
constructor({ references,
|
|
18
|
-
this.#
|
|
17
|
+
constructor({ references, currentIntl }) {
|
|
18
|
+
this.#currentIntl = currentIntl;
|
|
19
19
|
this.#httpService = references.httpService;
|
|
20
20
|
this.#layerFactory = references.layerFactory;
|
|
21
21
|
const providers = references.providers;
|
|
@@ -146,7 +146,12 @@ class MapRegistry {
|
|
|
146
146
|
async #createMapModelImpl(mapId, configProvider) {
|
|
147
147
|
LOG.info(`Creating map with id '${mapId}'`);
|
|
148
148
|
const mapConfig = await configProvider();
|
|
149
|
-
const mapModel = await createMapModel(
|
|
149
|
+
const mapModel = await createMapModel(
|
|
150
|
+
mapId,
|
|
151
|
+
mapConfig,
|
|
152
|
+
this.#currentIntl,
|
|
153
|
+
this.#httpService
|
|
154
|
+
);
|
|
150
155
|
return mapModel;
|
|
151
156
|
}
|
|
152
157
|
#isDynamic(mapId) {
|
package/MapRegistry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapRegistry.js","sources":["MapRegistry.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch } from \"@conterra/reactivity-core\";\nimport { on } from \"@conterra/reactivity-events\";\nimport { createLogger, Resource } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport {\n DECLARE_SERVICE_INTERFACE,\n PackageIntl,\n Service,\n ServiceOptions\n} from \"@open-pioneer/runtime\";\nimport OlMap from \"ol/Map\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LayerFactory } from \"./LayerFactory\";\nimport { createMapModel } from \"./model/createMapModel\";\nimport { MapConfig } from \"./model/MapConfig\";\nimport { MapModel } from \"./model/MapModel\";\n\nconst LOG = createLogger(sourceId);\n\n/**\n * Options passed to the {@link MapConfigProvider.getMapConfig} method.\n *\n * @group Services\n */\nexport interface MapConfigProviderOptions {\n /**\n * A reference to the layer factory, for the construction of new layer instances.\n */\n layerFactory: LayerFactory;\n}\n\n/**\n * Provides an OpenLayers map configuration with a given map id.\n *\n * The implementor must also provide the interface name `\"map.MapConfigProvider\"`.\n *\n * @group Services\n */\nexport interface MapConfigProvider {\n /**\n * Unique identifier of the map.\n */\n readonly mapId: string;\n\n /**\n * Returns the map configuration for this map.\n *\n * Called by the {@link MapRegistry} when the map is requested for the first time.\n *\n * See {@link MapConfig} for supported options during map creation.\n * Use {@link MapConfigProviderOptions.layerFactory} to construct new layers.\n */\n getMapConfig(options: MapConfigProviderOptions): Promise<MapConfig>;\n}\n\ninterface References {\n providers: MapConfigProvider[];\n httpService: HttpService;\n layerFactory: LayerFactory;\n}\n\ntype ModelJobResult =\n | { kind: \"model\"; model: MapModel; listener: Resource }\n | { kind: \"error\"; error: Error };\n\n/**\n * Provides access to registered map instances.\n *\n * Maps are identified by a unique id.\n *\n * Inject an instance of this service by referencing the interface name `\"map.MapRegistry\"`.\n *\n * @group Services\n */\nexport class MapRegistry implements Service {\n declare [DECLARE_SERVICE_INTERFACE]: \"map.MapRegistry\";\n\n #intl: PackageIntl;\n #httpService: HttpService;\n #layerFactory: LayerFactory;\n\n #configProviders = new Map<string, MapConfigProvider>();\n #entries = new Map<string, ModelJobResult>();\n #modelCreationJobs = new Map<string, Promise<ModelJobResult>>();\n #modelsByOlMap = new WeakMap<OlMap, MapModel>();\n #destroyed = false;\n\n constructor({ references, intl }: ServiceOptions<References>) {\n this.#intl = intl;\n this.#httpService = references.httpService;\n this.#layerFactory = references.layerFactory;\n\n const providers = references.providers;\n for (const provider of providers) {\n this.#configProviders.set(provider.mapId, provider);\n }\n }\n\n destroy(): void {\n if (this.#destroyed) {\n return;\n }\n\n batch(() => {\n LOG.debug(`Destroy map registry and all maps`);\n this.#destroyed = true;\n this.#entries.forEach((entry) => {\n if (entry.kind === \"model\") {\n entry.listener.destroy();\n entry.model.destroy();\n }\n });\n this.#entries.clear();\n this.#modelCreationJobs.clear();\n });\n }\n\n /**\n * Returns the map model associated with the given id.\n * Returns undefined if there is no such model.\n */\n async getMapModel(mapId: string): Promise<MapModel | undefined> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n\n const entry = this.#entries.get(mapId);\n if (entry) {\n return unbox(entry);\n }\n\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n return await waitForResult(creationJob);\n }\n\n const provider = this.#configProviders.get(mapId);\n if (!provider) {\n LOG.debug(`Failed to find a config provider for map id '${mapId}'.`);\n return undefined;\n }\n\n return await this.#createMapModel(mapId, () =>\n provider.getMapConfig({\n layerFactory: this.#layerFactory\n })\n );\n }\n\n /**\n * Like {@link getMapModel}, but throws if no model exists for the given `mapId`.\n */\n async expectMapModel(mapId: string): Promise<MapModel> {\n const model = await this.getMapModel(mapId);\n if (!model) {\n throw new Error(`No configuration available for map with id '${mapId}'.`);\n }\n return model;\n }\n\n /**\n * Creates a MapModel without the need to provide a {@link MapConfigProvider}.\n * Throws an error if a map with the given id already exists or if the map config is invalid.\n */\n async createMapModel(mapId: string, options?: MapConfig): Promise<MapModel> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n if (this.#entries.has(mapId)) {\n throw new Error(`Map id '${mapId}' is not unique.`);\n }\n if (this.#modelCreationJobs.has(mapId)) {\n throw new Error(`A map with the id '${mapId}' is already under construction.`);\n }\n return await this.#createMapModel(mapId, () => Promise.resolve(options ?? {}));\n }\n\n /**\n * Given a raw OpenLayers map instance, returns the associated {@link MapModel} - or undefined\n * if the map is unknown to this registry.\n *\n * All OpenLayers maps created by this registry (e.g. via {@link MapConfigProvider} or {@link createMapModel}) have an associated map model.\n */\n getMapModelByRawInstance(olMap: OlMap): MapModel | undefined {\n return this.#modelsByOlMap.get(olMap);\n }\n\n // Wrapper method to ensure that in-progress construction of maps can be observed.\n #createMapModel(mapId: string, configProvider: () => Promise<MapConfig>): Promise<MapModel> {\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n throw new Error(\"Internal error: a map model is already being created for this mapId\");\n }\n\n const modelPromise = this.#createMapModelImpl(mapId, configProvider)\n .then((mapModel) => {\n if (this.#destroyed) {\n mapModel.destroy();\n throw new Error(`MapRegistry has been destroyed.`);\n }\n\n const listener = on(\n mapModel.destroyed,\n () => {\n // Allow id reuse for dynamically created maps\n if (this.#isDynamic(mapId)) {\n const currentEntry = this.#entries.get(mapId);\n if (currentEntry === entry) {\n this.#entries.delete(mapId);\n }\n }\n },\n { dispatch: \"sync\" }\n );\n\n const entry: ModelJobResult = { kind: \"model\", model: mapModel, listener };\n this.#entries.set(mapId, entry);\n this.#modelCreationJobs.delete(mapId);\n this.#modelsByOlMap.set(mapModel.olMap, mapModel);\n return entry;\n })\n .catch((cause) => {\n const error = new Error(`Failed to construct map '${mapId}'`, { cause });\n const entry: ModelJobResult = { kind: \"error\", error };\n this.#modelCreationJobs.delete(mapId);\n if (!this.#isDynamic(mapId)) {\n // Don't store errors for dynamically created maps (the caller already got the error via promise).\n this.#entries.set(mapId, entry);\n }\n return entry;\n });\n this.#modelCreationJobs.set(mapId, modelPromise);\n return waitForResult(modelPromise);\n }\n\n async #createMapModelImpl(\n mapId: string,\n configProvider: () => Promise<MapConfig>\n ): Promise<MapModel> {\n LOG.info(`Creating map with id '${mapId}'`);\n const mapConfig = await configProvider();\n const mapModel = await createMapModel(mapId, mapConfig, this.#intl, this.#httpService);\n return mapModel;\n }\n\n #isDynamic(mapId: string): boolean {\n return !this.#configProviders.has(mapId);\n }\n}\n\nasync function waitForResult(job: Promise<ModelJobResult>): Promise<MapModel> {\n return unbox(await job);\n}\n\nfunction unbox(entry: ModelJobResult): MapModel {\n if (entry.kind === \"error\") {\n throw entry.error;\n }\n return entry.model;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapRegistry.js","sources":["MapRegistry.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { on } from \"@conterra/reactivity-events\";\nimport { createLogger, Resource } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport {\n DECLARE_SERVICE_INTERFACE,\n PackageIntl,\n Service,\n ServiceOptions\n} from \"@open-pioneer/runtime\";\nimport OlMap from \"ol/Map\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LayerFactory } from \"./LayerFactory\";\nimport { createMapModel } from \"./model/createMapModel\";\nimport { MapConfig } from \"./model/MapConfig\";\nimport { MapModel } from \"./model/MapModel\";\n\nconst LOG = createLogger(sourceId);\n\n/**\n * Options passed to the {@link MapConfigProvider.getMapConfig} method.\n *\n * @group Services\n */\nexport interface MapConfigProviderOptions {\n /**\n * A reference to the layer factory, for the construction of new layer instances.\n */\n layerFactory: LayerFactory;\n}\n\n/**\n * Provides an OpenLayers map configuration with a given map id.\n *\n * The implementor must also provide the interface name `\"map.MapConfigProvider\"`.\n *\n * @group Services\n */\nexport interface MapConfigProvider {\n /**\n * Unique identifier of the map.\n */\n readonly mapId: string;\n\n /**\n * Returns the map configuration for this map.\n *\n * Called by the {@link MapRegistry} when the map is requested for the first time.\n *\n * See {@link MapConfig} for supported options during map creation.\n * Use {@link MapConfigProviderOptions.layerFactory} to construct new layers.\n */\n getMapConfig(options: MapConfigProviderOptions): Promise<MapConfig>;\n}\n\ninterface References {\n providers: MapConfigProvider[];\n httpService: HttpService;\n layerFactory: LayerFactory;\n}\n\ntype ModelJobResult =\n | { kind: \"model\"; model: MapModel; listener: Resource }\n | { kind: \"error\"; error: Error };\n\n/**\n * Provides access to registered map instances.\n *\n * Maps are identified by a unique id.\n *\n * Inject an instance of this service by referencing the interface name `\"map.MapRegistry\"`.\n *\n * @group Services\n */\nexport class MapRegistry implements Service {\n declare [DECLARE_SERVICE_INTERFACE]: \"map.MapRegistry\";\n\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #httpService: HttpService;\n #layerFactory: LayerFactory;\n\n #configProviders = new Map<string, MapConfigProvider>();\n #entries = new Map<string, ModelJobResult>();\n #modelCreationJobs = new Map<string, Promise<ModelJobResult>>();\n #modelsByOlMap = new WeakMap<OlMap, MapModel>();\n #destroyed = false;\n\n constructor({ references, currentIntl }: ServiceOptions<References>) {\n this.#currentIntl = currentIntl;\n this.#httpService = references.httpService;\n this.#layerFactory = references.layerFactory;\n\n const providers = references.providers;\n for (const provider of providers) {\n this.#configProviders.set(provider.mapId, provider);\n }\n }\n\n destroy(): void {\n if (this.#destroyed) {\n return;\n }\n\n batch(() => {\n LOG.debug(`Destroy map registry and all maps`);\n this.#destroyed = true;\n this.#entries.forEach((entry) => {\n if (entry.kind === \"model\") {\n entry.listener.destroy();\n entry.model.destroy();\n }\n });\n this.#entries.clear();\n this.#modelCreationJobs.clear();\n });\n }\n\n /**\n * Returns the map model associated with the given id.\n * Returns undefined if there is no such model.\n */\n async getMapModel(mapId: string): Promise<MapModel | undefined> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n\n const entry = this.#entries.get(mapId);\n if (entry) {\n return unbox(entry);\n }\n\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n return await waitForResult(creationJob);\n }\n\n const provider = this.#configProviders.get(mapId);\n if (!provider) {\n LOG.debug(`Failed to find a config provider for map id '${mapId}'.`);\n return undefined;\n }\n\n return await this.#createMapModel(mapId, () =>\n provider.getMapConfig({\n layerFactory: this.#layerFactory\n })\n );\n }\n\n /**\n * Like {@link getMapModel}, but throws if no model exists for the given `mapId`.\n */\n async expectMapModel(mapId: string): Promise<MapModel> {\n const model = await this.getMapModel(mapId);\n if (!model) {\n throw new Error(`No configuration available for map with id '${mapId}'.`);\n }\n return model;\n }\n\n /**\n * Creates a MapModel without the need to provide a {@link MapConfigProvider}.\n * Throws an error if a map with the given id already exists or if the map config is invalid.\n */\n async createMapModel(mapId: string, options?: MapConfig): Promise<MapModel> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n if (this.#entries.has(mapId)) {\n throw new Error(`Map id '${mapId}' is not unique.`);\n }\n if (this.#modelCreationJobs.has(mapId)) {\n throw new Error(`A map with the id '${mapId}' is already under construction.`);\n }\n return await this.#createMapModel(mapId, () => Promise.resolve(options ?? {}));\n }\n\n /**\n * Given a raw OpenLayers map instance, returns the associated {@link MapModel} - or undefined\n * if the map is unknown to this registry.\n *\n * All OpenLayers maps created by this registry (e.g. via {@link MapConfigProvider} or {@link createMapModel}) have an associated map model.\n */\n getMapModelByRawInstance(olMap: OlMap): MapModel | undefined {\n return this.#modelsByOlMap.get(olMap);\n }\n\n // Wrapper method to ensure that in-progress construction of maps can be observed.\n #createMapModel(mapId: string, configProvider: () => Promise<MapConfig>): Promise<MapModel> {\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n throw new Error(\"Internal error: a map model is already being created for this mapId\");\n }\n\n const modelPromise = this.#createMapModelImpl(mapId, configProvider)\n .then((mapModel) => {\n if (this.#destroyed) {\n mapModel.destroy();\n throw new Error(`MapRegistry has been destroyed.`);\n }\n\n const listener = on(\n mapModel.destroyed,\n () => {\n // Allow id reuse for dynamically created maps\n if (this.#isDynamic(mapId)) {\n const currentEntry = this.#entries.get(mapId);\n if (currentEntry === entry) {\n this.#entries.delete(mapId);\n }\n }\n },\n { dispatch: \"sync\" }\n );\n\n const entry: ModelJobResult = { kind: \"model\", model: mapModel, listener };\n this.#entries.set(mapId, entry);\n this.#modelCreationJobs.delete(mapId);\n this.#modelsByOlMap.set(mapModel.olMap, mapModel);\n return entry;\n })\n .catch((cause) => {\n const error = new Error(`Failed to construct map '${mapId}'`, { cause });\n const entry: ModelJobResult = { kind: \"error\", error };\n this.#modelCreationJobs.delete(mapId);\n if (!this.#isDynamic(mapId)) {\n // Don't store errors for dynamically created maps (the caller already got the error via promise).\n this.#entries.set(mapId, entry);\n }\n return entry;\n });\n this.#modelCreationJobs.set(mapId, modelPromise);\n return waitForResult(modelPromise);\n }\n\n async #createMapModelImpl(\n mapId: string,\n configProvider: () => Promise<MapConfig>\n ): Promise<MapModel> {\n LOG.info(`Creating map with id '${mapId}'`);\n const mapConfig = await configProvider();\n const mapModel = await createMapModel(\n mapId,\n mapConfig,\n this.#currentIntl,\n this.#httpService\n );\n return mapModel;\n }\n\n #isDynamic(mapId: string): boolean {\n return !this.#configProviders.has(mapId);\n }\n}\n\nasync function waitForResult(job: Promise<ModelJobResult>): Promise<MapModel> {\n return unbox(await job);\n}\n\nfunction unbox(entry: ModelJobResult): MapModel {\n if (entry.kind === \"error\") {\n throw entry.error;\n }\n return entry.model;\n}\n"],"names":[],"mappings":"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"}
|
package/README.md
CHANGED
|
@@ -100,16 +100,6 @@ If no `verticalGap` is configured, a default vertical gap of `30px` is used.
|
|
|
100
100
|
|
|
101
101
|
> NOTE: To get the correct tab order, add the container anchor-points before other components.
|
|
102
102
|
|
|
103
|
-
By default, certain pointer events from map anchor children (such as `pointer-down`) are stopped from bubbling up towards the map.
|
|
104
|
-
This is done to "hide" those events from map interactions (such as drawing): this makes it possible to click into text or controls within a map anchor without interacting with the map.
|
|
105
|
-
This behavior can be disabled by setting the `stopEvents` property to `false`:
|
|
106
|
-
|
|
107
|
-
```jsx
|
|
108
|
-
<MapAnchor position="top-right" stopEvents={false}>
|
|
109
|
-
{/* Click events etc. will be seen by the map. This could be appropriate for non-interactive text-only overlays, for example. */}
|
|
110
|
-
</MapAnchor>
|
|
111
|
-
```
|
|
112
|
-
|
|
113
103
|
### Using the DefaultMapProvider
|
|
114
104
|
|
|
115
105
|
You can use the `DefaultMapProvider` to globally specify the `map` in your application's UI.
|
|
@@ -627,7 +617,7 @@ export class MapConfigProviderImpl implements MapConfigProvider {
|
|
|
627
617
|
title: "TopPlus Open",
|
|
628
618
|
isBaseLayer: true,
|
|
629
619
|
visible: true,
|
|
630
|
-
|
|
620
|
+
olLayer: new TileLayer({
|
|
631
621
|
source: createWMTSSource("web")
|
|
632
622
|
})
|
|
633
623
|
})
|
|
@@ -728,7 +718,7 @@ if (wmtsOptions) {
|
|
|
728
718
|
id: "topplus_open_optionsFromCapabilities",
|
|
729
719
|
title: "TopPlus Open - created with optionsFromCapabilities()",
|
|
730
720
|
visible: false,
|
|
731
|
-
|
|
721
|
+
olLayer: new TileLayer({
|
|
732
722
|
source: new WMTS(wmtsOptions)
|
|
733
723
|
})
|
|
734
724
|
}));
|
package/layers/WMSLayer.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Options as WMSSourceOptions } from "ol/source/ImageWMS";
|
|
2
|
+
import ImageWMS from "ol/source/ImageWMS";
|
|
2
3
|
import { MapModel } from "../model/MapModel";
|
|
3
4
|
import { InternalConstructorTag } from "../utils/InternalConstructorTag";
|
|
4
5
|
import { AbstractLayer } from "./AbstractLayer";
|
|
@@ -51,6 +52,12 @@ export declare class WMSLayer extends AbstractLayer {
|
|
|
51
52
|
destroy(): void;
|
|
52
53
|
get type(): "wms";
|
|
53
54
|
get legend(): undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the current source associated with this layer as a reactive property.
|
|
57
|
+
*
|
|
58
|
+
* Note that the return type may be expanded in the future with additional source types.
|
|
59
|
+
*/
|
|
60
|
+
get olSource(): ImageWMS | undefined;
|
|
54
61
|
/** The URL of the WMS service that was used during layer construction. */
|
|
55
62
|
get url(): string;
|
|
56
63
|
get layers(): undefined;
|
|
@@ -58,6 +65,11 @@ export declare class WMSLayer extends AbstractLayer {
|
|
|
58
65
|
* Holds the sublayers of this layer.
|
|
59
66
|
*/
|
|
60
67
|
get sublayers(): SublayersCollection<WMSSublayer>;
|
|
68
|
+
/**
|
|
69
|
+
* @internal
|
|
70
|
+
*
|
|
71
|
+
* Note: this property was never documented and has been exposed by accident.
|
|
72
|
+
**/
|
|
61
73
|
get capabilities(): Record<string, any> | undefined;
|
|
62
74
|
/** @internal */
|
|
63
75
|
[ATTACH_TO_MAP](map: MapModel): void;
|
package/layers/WMSLayer.js
CHANGED
|
@@ -93,6 +93,14 @@ class WMSLayer extends AbstractLayer {
|
|
|
93
93
|
get legend() {
|
|
94
94
|
return void 0;
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Returns the current source associated with this layer as a reactive property.
|
|
98
|
+
*
|
|
99
|
+
* Note that the return type may be expanded in the future with additional source types.
|
|
100
|
+
*/
|
|
101
|
+
get olSource() {
|
|
102
|
+
return this.#source;
|
|
103
|
+
}
|
|
96
104
|
/** The URL of the WMS service that was used during layer construction. */
|
|
97
105
|
get url() {
|
|
98
106
|
return this.#url;
|
|
@@ -106,6 +114,11 @@ class WMSLayer extends AbstractLayer {
|
|
|
106
114
|
get sublayers() {
|
|
107
115
|
return this.#sublayers;
|
|
108
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* @internal
|
|
119
|
+
*
|
|
120
|
+
* Note: this property was never documented and has been exposed by accident.
|
|
121
|
+
**/
|
|
109
122
|
get capabilities() {
|
|
110
123
|
return this.#capabilities;
|
|
111
124
|
}
|
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 { sourceId } from \"open-pioneer:source-info\";\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 { getAttributions } from \"./wms/getAttributions\";\nimport { getLegendUrl } from \"./wms/getLegendUrl\";\nimport { constructSublayers, WMSSublayer, WMSSublayerConfig } from \"./wms/WMSSublayer\";\nimport { Sublayer } from \"./unions\";\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(sourceId);\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 this.#fetchWMSCapabilities()\n .then((result: string) => {\n batch(() => {\n this.#initializeWithMetadata(result);\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 initialize WMS 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 filter = (sublayer: Sublayer) => sublayer.visible;\n for (const sublayer of walkLeaves(this.#sublayers, filter)) {\n // Push sublayer if layer name is not an empty string | undefined | ...\n if (sublayer.name) {\n layers.push(sublayer.name);\n }\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 #initializeWithMetadata(metadata: string) {\n const parser = new WMSCapabilities();\n const capabilities = parser.read(metadata);\n this.#capabilities = capabilities;\n\n // Apply attributions from metadata if none are set.\n if (this.#source.getAttributions() == null) {\n const attributions = getAttributions(capabilities);\n if (attributions) {\n this.#source.setAttributions(attributions);\n }\n }\n\n for (const layer of walkLeaves(this.#sublayers)) {\n if (layer.name) {\n const legendUrl = getLegendUrl(capabilities, layer.name);\n layer[SET_LEGEND](legendUrl);\n }\n }\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/**\n * Yields all leaf notes in the given collection (recursively).\n */\nfunction* walkLeaves(\n sublayers: SublayersCollection<WMSSublayer>,\n filter?: (sublayer: Sublayer) => boolean\n): Generator<WMSSublayer> {\n for (const sublayer of sublayers[GET_RAW_SUBLAYERS]()) {\n if (filter && !filter(sublayer)) {\n continue;\n }\n\n const nested = sublayer.sublayers[GET_RAW_SUBLAYERS]();\n if (nested.length) {\n yield* walkLeaves(sublayer.sublayers, filter);\n } else {\n yield sublayer;\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<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 { sourceId } from \"open-pioneer:source-info\";\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 { getAttributions } from \"./wms/getAttributions\";\nimport { getLegendUrl } from \"./wms/getLegendUrl\";\nimport { constructSublayers, WMSSublayer, WMSSublayerConfig } from \"./wms/WMSSublayer\";\nimport { Sublayer } from \"./unions\";\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(sourceId);\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 /**\n * Returns the current source associated with this layer as a reactive property.\n *\n * Note that the return type may be expanded in the future with additional source types.\n */\n get olSource(): ImageWMS | undefined {\n // source does not change in this class; no signal is required\n return this.#source;\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 /**\n * @internal\n *\n * Note: this property was never documented and has been exposed by accident.\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 this.#fetchWMSCapabilities()\n .then((result: string) => {\n batch(() => {\n this.#initializeWithMetadata(result);\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 initialize WMS 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 filter = (sublayer: Sublayer) => sublayer.visible;\n for (const sublayer of walkLeaves(this.#sublayers, filter)) {\n // Push sublayer if layer name is not an empty string | undefined | ...\n if (sublayer.name) {\n layers.push(sublayer.name);\n }\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 #initializeWithMetadata(metadata: string) {\n const parser = new WMSCapabilities();\n const capabilities = parser.read(metadata);\n this.#capabilities = capabilities;\n\n // Apply attributions from metadata if none are set.\n if (this.#source.getAttributions() == null) {\n const attributions = getAttributions(capabilities);\n if (attributions) {\n this.#source.setAttributions(attributions);\n }\n }\n\n for (const layer of walkLeaves(this.#sublayers)) {\n if (layer.name) {\n const legendUrl = getLegendUrl(capabilities, layer.name);\n layer[SET_LEGEND](legendUrl);\n }\n }\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/**\n * Yields all leaf notes in the given collection (recursively).\n */\nfunction* walkLeaves(\n sublayers: SublayersCollection<WMSSublayer>,\n filter?: (sublayer: Sublayer) => boolean\n): Generator<WMSSublayer> {\n for (const sublayer of sublayers[GET_RAW_SUBLAYERS]()) {\n if (filter && !filter(sublayer)) {\n continue;\n }\n\n const nested = sublayer.sublayers[GET_RAW_SUBLAYERS]();\n if (nested.length) {\n yield* walkLeaves(sublayer.sublayers, filter);\n } else {\n yield sublayer;\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<WMSLayerConfig, WMSLayer> = WMSLayer;\n void check;\n}\n"],"names":[],"mappings":"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"}
|
package/layers/WMTSLayer.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Options as WMTSSourceOptions } from "ol/source/WMTS";
|
|
1
|
+
import WMTS, { Options as WMTSSourceOptions } from "ol/source/WMTS";
|
|
2
2
|
import { MapModel } from "../model/MapModel";
|
|
3
3
|
import { InternalConstructorTag } from "../utils/InternalConstructorTag";
|
|
4
4
|
import { AbstractLayer } from "./AbstractLayer";
|
|
@@ -43,6 +43,12 @@ export declare class WMTSLayer extends AbstractLayer {
|
|
|
43
43
|
constructor(config: WMTSLayerConfig, deps: LayerDependencies, internalTag: InternalConstructorTag);
|
|
44
44
|
destroy(): void;
|
|
45
45
|
get type(): "wmts";
|
|
46
|
+
/**
|
|
47
|
+
* Returns the current source associated with this layer as a reactive property.
|
|
48
|
+
*
|
|
49
|
+
* Note that the return type may be expanded in the future with additional source types.
|
|
50
|
+
*/
|
|
51
|
+
get olSource(): WMTS | undefined;
|
|
46
52
|
/** URL of the WMTS service. */
|
|
47
53
|
get legend(): string | undefined;
|
|
48
54
|
get sublayers(): undefined;
|
package/layers/WMTSLayer.js
CHANGED
|
@@ -25,6 +25,7 @@ class WMTSLayer extends AbstractLayer {
|
|
|
25
25
|
#matrixSet;
|
|
26
26
|
#layer;
|
|
27
27
|
#sourceOptions;
|
|
28
|
+
#olSource = reactive();
|
|
28
29
|
#legend = reactive();
|
|
29
30
|
#loadStarted = false;
|
|
30
31
|
#abortController = new AbortController();
|
|
@@ -54,6 +55,14 @@ class WMTSLayer extends AbstractLayer {
|
|
|
54
55
|
get type() {
|
|
55
56
|
return "wmts";
|
|
56
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns the current source associated with this layer as a reactive property.
|
|
60
|
+
*
|
|
61
|
+
* Note that the return type may be expanded in the future with additional source types.
|
|
62
|
+
*/
|
|
63
|
+
get olSource() {
|
|
64
|
+
return this.#olSource.value;
|
|
65
|
+
}
|
|
57
66
|
/** URL of the WMTS service. */
|
|
58
67
|
get legend() {
|
|
59
68
|
return this.#legend.value;
|
|
@@ -121,7 +130,7 @@ class WMTSLayer extends AbstractLayer {
|
|
|
121
130
|
}
|
|
122
131
|
}
|
|
123
132
|
const attributions = explicitAttributions ?? getAttributions(capabilities);
|
|
124
|
-
const source = new WMTS({
|
|
133
|
+
const source = this.#olSource.value = new WMTS({
|
|
125
134
|
...options,
|
|
126
135
|
attributions,
|
|
127
136
|
...sourceOptions,
|
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 { batch, 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 TileSourceType from \"ol/source/Tile\";\nimport WMTS, { optionsFromCapabilities, Options as WMTSSourceOptions } from \"ol/source/WMTS\";\nimport { sourceId } from \"open-pioneer:source-info\";\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 { getAttributions } from \"./wmts/getAttributions\";\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<WMTSSourceOptions>;\n}\n\nconst LOG = createLogger(sourceId);\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 #sourceOptions: Partial<WMTSSourceOptions>;\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 batch(() => {\n this.#initializeWithMetadata(result);\n });\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer '${this.name}' has been destroyed before fetching the data`);\n return;\n }\n LOG.error(`Failed to initialize WMTS layer '${this.name}'`, error);\n //TODO: how to set the load state to 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 #initializeWithMetadata(metadata: string) {\n const parser = new WMTSCapabilities();\n const capabilities = parser.read(metadata);\n const options = optionsFromCapabilities(capabilities, {\n layer: this.#name,\n matrixSet: this.#matrixSet\n });\n if (!options) {\n throw new Error(`Layer '${this.#name}' was not found in capabilities`);\n }\n if (options.matrixSet !== this.#matrixSet) {\n throw new Error(`Tile matrix set '${this.#matrixSet}' was not found in capabilities`);\n }\n\n const { attributions: explicitAttributions, ...sourceOptions } = this.#sourceOptions;\n if (sourceOptions.style && sourceOptions.style !== options.style) {\n const styleToUse = this.#existsStyleInCapabilities(capabilities, sourceOptions.style);\n if (!styleToUse) {\n throw new Error(`Style '${sourceOptions.style}' was not found in capabilities`);\n }\n }\n\n const attributions = explicitAttributions ?? getAttributions(capabilities);\n const source = new WMTS({\n ...options,\n attributions,\n ...sourceOptions,\n tileLoadFunction: (tile, tileUrl) => {\n this.#loadTile(tile, tileUrl);\n }\n });\n this.#layer.setSource(source);\n\n const activeStyleId = source.getStyle();\n const legendUrl = getLegendUrl(capabilities, this.name, activeStyleId);\n this.#legend.value = legendUrl;\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 /* eslint-disable @typescript-eslint/no-explicit-any */\n #existsStyleInCapabilities(capabilities: any, styleToUse: string): boolean {\n // NOTE: we have a style override, check if the style exists in the capabilities\n // the helper optionsFromCapabilities, supports style, too, but uses the Title instead of the Identifier, to find a match in the capabilities\n const layerDesc = capabilities.Contents?.Layer?.find(\n (layer: any) => layer.Identifier === this.#name\n );\n return layerDesc?.Style?.some((style: any) => style.Identifier === styleToUse) ?? false;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\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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"}
|
|
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 { batch, 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 TileSourceType from \"ol/source/Tile\";\nimport WMTS, { optionsFromCapabilities, Options as WMTSSourceOptions } from \"ol/source/WMTS\";\nimport { sourceId } from \"open-pioneer:source-info\";\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 { getAttributions } from \"./wmts/getAttributions\";\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<WMTSSourceOptions>;\n}\n\nconst LOG = createLogger(sourceId);\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 #sourceOptions: Partial<WMTSSourceOptions>;\n #olSource = reactive<WMTS>();\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 /**\n * Returns the current source associated with this layer as a reactive property.\n *\n * Note that the return type may be expanded in the future with additional source types.\n */\n get olSource(): WMTS | undefined {\n return this.#olSource.value;\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 batch(() => {\n this.#initializeWithMetadata(result);\n });\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer '${this.name}' has been destroyed before fetching the data`);\n return;\n }\n LOG.error(`Failed to initialize WMTS layer '${this.name}'`, error);\n //TODO: how to set the load state to 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 #initializeWithMetadata(metadata: string) {\n const parser = new WMTSCapabilities();\n const capabilities = parser.read(metadata);\n const options = optionsFromCapabilities(capabilities, {\n layer: this.#name,\n matrixSet: this.#matrixSet\n });\n if (!options) {\n throw new Error(`Layer '${this.#name}' was not found in capabilities`);\n }\n if (options.matrixSet !== this.#matrixSet) {\n throw new Error(`Tile matrix set '${this.#matrixSet}' was not found in capabilities`);\n }\n\n const { attributions: explicitAttributions, ...sourceOptions } = this.#sourceOptions;\n if (sourceOptions.style && sourceOptions.style !== options.style) {\n const styleToUse = this.#existsStyleInCapabilities(capabilities, sourceOptions.style);\n if (!styleToUse) {\n throw new Error(`Style '${sourceOptions.style}' was not found in capabilities`);\n }\n }\n\n const attributions = explicitAttributions ?? getAttributions(capabilities);\n const source = (this.#olSource.value = new WMTS({\n ...options,\n attributions,\n ...sourceOptions,\n tileLoadFunction: (tile, tileUrl) => {\n this.#loadTile(tile, tileUrl);\n }\n }));\n this.#layer.setSource(source);\n\n const activeStyleId = source.getStyle();\n const legendUrl = getLegendUrl(capabilities, this.name, activeStyleId);\n this.#legend.value = legendUrl;\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 /* eslint-disable @typescript-eslint/no-explicit-any */\n #existsStyleInCapabilities(capabilities: any, styleToUse: string): boolean {\n // NOTE: we have a style override, check if the style exists in the capabilities\n // the helper optionsFromCapabilities, supports style, too, but uses the Title instead of the Identifier, to find a match in the capabilities\n const layerDesc = capabilities.Contents?.Layer?.find(\n (layer: any) => layer.Identifier === this.#name\n );\n return layerDesc?.Style?.some((style: any) => style.Identifier === styleToUse) ?? false;\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\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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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReadonlyReactive } from "@conterra/reactivity-core";
|
|
1
2
|
import { PackageIntl } from "@open-pioneer/runtime";
|
|
2
3
|
import OlMap from "ol/Map";
|
|
3
4
|
import { AttributionItem } from "./MapModel";
|
|
@@ -7,7 +8,7 @@ export declare class MapAttributions {
|
|
|
7
8
|
olMap: OlMap;
|
|
8
9
|
/** false: not rendered */
|
|
9
10
|
showControl: boolean;
|
|
10
|
-
intl: PackageIntl
|
|
11
|
+
intl: ReadonlyReactive<PackageIntl>;
|
|
11
12
|
});
|
|
12
13
|
destroy(): void;
|
|
13
14
|
get attributionItems(): AttributionItem[];
|
package/model/MapAttributions.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { reactive, computed, effect } from '@conterra/reactivity-core';
|
|
2
|
+
import { destroyResources } from '@open-pioneer/core';
|
|
1
3
|
import Attribution from 'ol/control/Attribution.js';
|
|
2
4
|
import { sanitizeHtml } from '../utils/sanitize.js';
|
|
3
|
-
import { reactive, computed } from '@conterra/reactivity-core';
|
|
4
5
|
|
|
5
6
|
class MapAttributions {
|
|
6
7
|
#olMap;
|
|
8
|
+
#intl;
|
|
7
9
|
/**
|
|
8
10
|
* When default rendering of attributions is active, we simply display this control on the map (otherwise: hidden).
|
|
9
11
|
*
|
|
@@ -19,8 +21,10 @@ class MapAttributions {
|
|
|
19
21
|
text: attribution
|
|
20
22
|
}))
|
|
21
23
|
);
|
|
24
|
+
#resources = [];
|
|
22
25
|
constructor(options) {
|
|
23
26
|
this.#olMap = options.olMap;
|
|
27
|
+
this.#intl = options.intl;
|
|
24
28
|
const control = this.#control = new Attribution({
|
|
25
29
|
collapsible: false,
|
|
26
30
|
target: options.showControl ? void 0 : createDummyTargetNode()
|
|
@@ -36,12 +40,17 @@ class MapAttributions {
|
|
|
36
40
|
const element = control.element;
|
|
37
41
|
if (element) {
|
|
38
42
|
element.role = "region";
|
|
39
|
-
|
|
43
|
+
this.#resources.push(
|
|
44
|
+
effect(() => {
|
|
45
|
+
element.ariaLabel = this.#intl.value.formatMessage({ id: "attribution.label" });
|
|
46
|
+
})
|
|
47
|
+
);
|
|
40
48
|
}
|
|
41
49
|
this.#olMap.addControl(control);
|
|
42
50
|
}
|
|
43
51
|
destroy() {
|
|
44
52
|
this.#olMap.removeControl(this.#control);
|
|
53
|
+
destroyResources(this.#resources);
|
|
45
54
|
this.#control.dispose();
|
|
46
55
|
}
|
|
47
56
|
get attributionItems() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapAttributions.js","sources":["MapAttributions.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport OlMap, { FrameState } from \"ol/Map\";\nimport Attribution from \"ol/control/Attribution\";\nimport { sanitizeHtml } from \"../utils/sanitize\";\nimport {
|
|
1
|
+
{"version":3,"file":"MapAttributions.js","sources":["MapAttributions.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { computed, effect, reactive, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { destroyResources, Resource } from \"@open-pioneer/core\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport OlMap, { FrameState } from \"ol/Map\";\nimport Attribution from \"ol/control/Attribution\";\nimport { sanitizeHtml } from \"../utils/sanitize\";\nimport { AttributionItem } from \"./MapModel\";\n\nexport class MapAttributions {\n #olMap: OlMap;\n #intl: ReadonlyReactive<PackageIntl>;\n\n /**\n * When default rendering of attributions is active, we simply display this control on the map (otherwise: hidden).\n *\n * The control is always active (even if invisible) because we re-use its rendering code to extract the attribution items.\n * There is no real API to extract the attributions from OpenLayers, and we don't want to re-implement that logic right now.\n * We will see if that approach remains stable.\n */\n #control: Attribution;\n\n #attributionStrings = reactive<string[]>([], { equal: shallowEqual });\n\n // Attribution strings wrapped in objects, for forward compat.\n #attributionItems = computed<AttributionItem[]>(() =>\n this.#attributionStrings.value.map((attribution) => ({\n text: attribution\n }))\n );\n\n #resources: Resource[] = [];\n\n constructor(options: {\n olMap: OlMap;\n /** false: not rendered */\n showControl: boolean;\n intl: ReadonlyReactive<PackageIntl>;\n }) {\n this.#olMap = options.olMap;\n this.#intl = options.intl;\n\n const control = (this.#control = new Attribution({\n collapsible: false,\n target: options.showControl ? undefined : createDummyTargetNode()\n }));\n interceptAttributions(\n control,\n // Called by the attributions widgets as a side effect.\n // NOTE: this is currently called very often (~ every map render).\n (attributions) => {\n this.#attributionStrings.value = attributions;\n }\n );\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const element = (control as any).element as HTMLElement | undefined;\n if (element) {\n element.role = \"region\";\n this.#resources.push(\n effect(() => {\n element.ariaLabel = this.#intl.value.formatMessage({ id: \"attribution.label\" });\n })\n );\n }\n\n this.#olMap.addControl(control);\n }\n\n destroy() {\n this.#olMap.removeControl(this.#control);\n destroyResources(this.#resources);\n this.#control.dispose();\n }\n\n get attributionItems(): AttributionItem[] {\n return this.#attributionItems.value;\n }\n}\n\n// Overrides the OpenLayers widget to sanitize HTML attributions and to intercept the computed array of strings.\n// Note that this depends on OpenLayers internals that may change between versions.\nfunction interceptAttributions(attr: Attribution, onUpdate: (attributions: string[]) => void) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-function-type\n const originalCollectSourceAttributions = (attr as any).collectSourceAttributions_ as Function;\n if (!originalCollectSourceAttributions) {\n throw new Error(\"Internal error: failed to override attributions widget\");\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (attr as any).collectSourceAttributions_ = (frameState: FrameState) => {\n const rawAttributions = originalCollectSourceAttributions.call(\n attr,\n frameState\n ) as string[];\n if (!Array.isArray(rawAttributions)) {\n throw new Error(\"Internal error: unexpected attributions result (should be an array)\");\n }\n const sanitizedAttributions = rawAttributions.map((a) => sanitizeHtml(a));\n onUpdate(sanitizedAttributions);\n return sanitizedAttributions;\n };\n}\n\nfunction createDummyTargetNode() {\n const node = document.createElement(\"div\");\n node.style.display = \"none\";\n node.className = \"map-attribution-dummy-target\";\n return node;\n}\n\n// TODO: generic shallowEqual, deepEqual helpers @open-pioneer/core\nfunction shallowEqual<T>(a: T[], b: T[]) {\n return a.length === b.length && a.every((v, i) => v == b[i]);\n}\n"],"names":[],"mappings":"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"}
|
package/model/MapModel.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReadonlyReactive } from "@conterra/reactivity-core";
|
|
1
2
|
import { EventSource } from "@conterra/reactivity-events";
|
|
2
3
|
import { HttpService } from "@open-pioneer/http";
|
|
3
4
|
import OlMap from "ol/Map";
|
|
@@ -87,7 +88,7 @@ export declare class MapModel {
|
|
|
87
88
|
olMap: OlMap;
|
|
88
89
|
initialExtent: ExtentConfig | undefined;
|
|
89
90
|
showDefaultAttributions: boolean;
|
|
90
|
-
|
|
91
|
+
currentIntl: ReadonlyReactive<PackageIntl>;
|
|
91
92
|
httpService: HttpService;
|
|
92
93
|
}, tag: InternalConstructorTag);
|
|
93
94
|
/**
|
package/model/MapModel.js
CHANGED
package/model/MapModel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapModel.js","sources":["MapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { computed, reactive, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport { emit, emitter, EventSource } from \"@conterra/reactivity-events\";\nimport {\n createAbortError,\n createLogger,\n createManualPromise,\n deprecated,\n isAbortError,\n ManualPromise\n} from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\nimport OlView from \"ol/View\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { createEmpty, extend, getArea, getCenter } from \"ol/extent\";\nimport { getPointResolution, Projection } from \"ol/proj\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LAYER_DEPS, LayerDependencies } from \"../layers/shared/internals\";\nimport {\n assertInternalConstructor,\n INTERNAL_CONSTRUCTOR_TAG,\n InternalConstructorTag\n} from \"../utils/InternalConstructorTag\";\nimport { calculateBufferedExtent } from \"../utils/geometry-utils\";\nimport {\n DESTROY_HIGHLIGHTS,\n Highlight,\n HighlightOptions,\n Highlights,\n HighlightZoomOptions\n} from \"./Highlights\";\nimport { LayerCollection } from \"./LayerCollection\";\nimport { ExtentConfig } from \"./MapConfig\";\nimport { Overlays } from \"./Overlays\";\nimport { getGeometries } from \"./getGeometries\";\nimport { BaseFeature } from \"../utils/BaseFeature\";\nimport { Geometry } from \"ol/geom\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapAttributions } from \"./MapAttributions\";\n\nconst LOG = createLogger(sourceId);\n\nconst DEFAULT_DPI = 25.4 / 0.28;\nconst INCHES_PER_METRE = 39.37;\n\nconst DEFAULT_OL_POINT_ZOOM_LEVEL = 17;\nconst DEFAULT_OL_MAX_ZOOM_LEVEL = 20;\nconst DEFAULT_VIEW_PADDING = { top: 50, right: 20, bottom: 10, left: 20 };\n\nexport const DISPLAY_STATUS = Symbol(\"DISPLAY_STATUS\");\n\nconst deprecatedHighlights = deprecated({\n name: \"MapModel highlight function called\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.3.0\",\n alternative: \"call methods of myMapModel.highlights instead\"\n});\n\n/**\n * Options supported when calling {@link MapModel.zoom}.\n *\n * @group Map Model\n **/\nexport interface ZoomOptions {\n /**\n * The zoom-level used if there is no valid extend (such as for single points).\n */\n pointZoom?: number;\n\n /**\n * The maximum zoom-level for multiple points, line or polygon results.\n */\n maxZoom?: number;\n\n /**\n * The view padding to make all features visible.\n */\n viewPadding?: MapPadding;\n\n /**\n * The buffer factor around the extent of the zoomed features. E.g. a value of 1.1 will add\n * 10% to specify the size increase of the extent's width and height.\n */\n buffer?: number;\n}\n\n/**\n * Represents an object in the map.\n *\n * @group Map Model\n */\nexport type DisplayTarget = BaseFeature | Geometry;\n\n/**\n * Map padding, all values are pixels.\n *\n * See https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding\n *\n * @group Map Model\n */\nexport interface MapPadding {\n left?: number;\n right?: number;\n top?: number;\n bottom?: number;\n}\n\n/**\n * An item that should be displayed as part of the attributions for the map.\n *\n * @group MapModel\n */\nexport interface AttributionItem {\n /**\n * The attribution's text.\n *\n * Note that this property contains raw HTML tags.\n * The HTML content has been sanitized, so it is safe to display in the user interface.\n */\n text: string;\n}\n\ntype DisplayStatus = \"waiting\" | \"ready\" | \"error\";\n\n/**\n * Represents a map.\n *\n * @group Map Model\n */\nexport class MapModel {\n readonly #id: string;\n readonly #olMap: OlMap;\n readonly #olView: ReadonlyReactive<OlView>;\n readonly #attributions: MapAttributions;\n readonly #layers = new LayerCollection(this, INTERNAL_CONSTRUCTOR_TAG);\n readonly #highlights: Highlights;\n readonly #tooltips: Overlays;\n readonly #layerDeps: LayerDependencies;\n readonly #destroyed = emitter();\n\n #loadStartEventHandler: EventsKey | undefined;\n #loadEndEventHandler: EventsKey | undefined;\n readonly #olLoading = reactive(false);\n\n #isDestroyed = false;\n readonly #container: ReadonlyReactive<HTMLElement | undefined>;\n readonly #initialExtent = reactive<ExtentConfig>();\n readonly #viewBindings: ReadonlyReactive<ViewBindings>;\n readonly #scale: ReadonlyReactive<number | undefined>;\n\n readonly #abortController = new AbortController();\n #displayStatus: DisplayStatus;\n #displayWaiter: ManualPromise<void> | undefined;\n\n /**\n * @internal\n */\n constructor(\n options: {\n id: string;\n olMap: OlMap;\n initialExtent: ExtentConfig | undefined;\n showDefaultAttributions: boolean;\n intl: PackageIntl;\n httpService: HttpService;\n },\n tag: InternalConstructorTag\n ) {\n assertInternalConstructor(tag);\n\n this.#id = options.id;\n this.#olMap = options.olMap;\n this.#attributions = new MapAttributions({\n intl: options.intl,\n olMap: this.#olMap,\n showControl: options.showDefaultAttributions\n });\n\n this.#olView = synchronized(\n () => this.#olMap.getView(),\n (cb) => {\n const key = this.#olMap.on(\"change:view\", cb);\n return () => unByKey(key);\n }\n );\n\n // NOTE: As early as possible (before any async actions) so we don't miss any events.\n this.#watchLoadingState();\n\n this.#initialExtent.value = options.initialExtent;\n this.#layerDeps = {\n httpService: options.httpService\n };\n\n this.#displayStatus = \"waiting\";\n this.#initializeView().then(\n () => {\n this.#displayStatus = \"ready\";\n this.#displayWaiter?.resolve();\n this.#displayWaiter = undefined;\n },\n (error) => {\n if (!isAbortError(error)) {\n LOG.error(`Failed to initialize map`, error);\n }\n\n this.#displayStatus = \"error\";\n this.#displayWaiter?.reject(new Error(`Failed to initialize map.`));\n this.#displayWaiter = undefined;\n }\n );\n\n this.#container = synchronized(\n () => this.#olMap.getTargetElement() ?? undefined,\n (cb) => {\n const key = this.#olMap.on(\"change:target\", cb);\n return () => unByKey(key);\n }\n );\n\n this.#viewBindings = computed(() => createViewBindings(this.#olView.value));\n this.#scale = computed(() => {\n const { projection, resolution, center } = this;\n if (projection == null || resolution == null || center == null) {\n return undefined;\n }\n\n /**\n * Returns the appropriate scale for the given resolution and units, see OpenLayers function getScaleForResolution()\n * https://github.com/openlayers/openlayers/blob/7fa9df03431e9e1bc517e6c414565d9f848a3132/src/ol/control/ScaleLine.js#L454C3-L454C24\n */\n const pointResolution = getPointResolution(projection, resolution, center, \"m\"); //point resolution in meter per pixel\n const scale = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);\n return scale;\n });\n\n // expects fully constructed mapModel\n this.#highlights = new Highlights(this, this.#layerDeps);\n this.#tooltips = new Overlays(this);\n }\n\n /**\n * Destroys this objects, including all layers, highlights and the OL map itself.\n */\n destroy() {\n if (this.#isDestroyed) {\n return;\n }\n\n this.#isDestroyed = true;\n try {\n emit(this.#destroyed);\n } catch (e) {\n LOG.warn(`Unexpected error from event listener during map model destruction:`, e);\n }\n\n this.#loadStartEventHandler && unByKey(this.#loadStartEventHandler);\n this.#loadStartEventHandler = undefined;\n this.#loadEndEventHandler && unByKey(this.#loadEndEventHandler);\n this.#loadEndEventHandler = undefined;\n\n this.#abortController.abort();\n this.#displayWaiter?.reject(new Error(\"Map model was destroyed.\"));\n this.#layers.destroy();\n this.#highlights[DESTROY_HIGHLIGHTS]();\n this.#attributions.destroy();\n this.#olMap.dispose();\n }\n\n /**\n * Emitted when the map model is destroyed.\n */\n get destroyed(): EventSource<void> {\n return this.#destroyed;\n }\n\n /**\n * Returns the map's current display status.\n * This is `waiting` during initialization and `error` or `ready` when done.\n *\n * @internal\n */\n get [DISPLAY_STATUS](): DisplayStatus {\n return this.#displayStatus;\n }\n\n /**\n * The unique id of the map.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * The initial map extent.\n *\n * May be undefined before the map is shown.\n * This is guaranteed to be initialized if the promise returned by {@link whenDisplayed} has resolved.\n */\n get initialExtent(): ExtentConfig | undefined {\n return this.#initialExtent.value;\n }\n\n /**\n * Returns the current projection of the map (reactive).\n */\n get projection(): Projection {\n return this.#viewBindings.value.projection;\n }\n\n /**\n * Returns the current center of the map.\n * Same as `olView.getCenter()`, but reactive.\n */\n get center(): Coordinate | undefined {\n return this.#viewBindings.value.center.value;\n }\n\n /**\n * Returns the current resolution of the map.\n * Same as `olView.getResolution()`, but reactive.\n */\n get resolution(): number | undefined {\n return this.#viewBindings.value.resolution.value;\n }\n\n /**\n * Returns the current zoom level of the map.\n * Same as `olView.getZoom()`, but reactive.\n */\n get zoomLevel(): number | undefined {\n return this.#viewBindings.value.zoom.value;\n }\n\n /**\n * Returns the current scale of the map.\n *\n * The scale is a value derived from the current `center`, `resolution` and `projection` of the map.\n * The scale will change when the map is zoomed in our out, but depending on the projection, it may also\n * change when the map is _panned_.\n *\n * > NOTE: Technically, this is the _denominator_ of the current scale.\n * > In order to display it, use a format like `1:${scale}`.\n */\n get scale(): number | undefined {\n return this.#scale.value;\n }\n\n /**\n * Returns true if the map is currently loading.\n *\n * This is based on the OpenLayers events `loadstart` and `loadend`,\n * see [Documentation](https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:loadstart).\n */\n get loading(): boolean {\n return this.#olLoading.value;\n }\n\n /**\n * Contains all known layers of this map.\n *\n * Note that not all layers in this collection may be active in the OpenLayers map.\n * Also note that not all layers in the OpenLayers map may be contained in this collection.\n */\n get layers(): LayerCollection {\n return this.#layers;\n }\n\n /**\n * The container in which the map is currently being rendered.\n * This is the same as the target element of the underlying OpenLayers map.\n *\n * May be undefined if the map is not being rendered at the moment.\n * May change at runtime.\n */\n get container(): HTMLElement | undefined {\n return this.#container.value;\n }\n\n /**\n * Returns attributions for the current content of the map.\n */\n get attributionItems(): AttributionItem[] {\n return this.#attributions.attributionItems;\n }\n\n /**\n * The raw OpenLayers map.\n */\n get olMap(): OlMap {\n return this.#olMap;\n }\n\n /**\n * Returns the current view of the OpenLayers map.\n */\n get olView(): OlView {\n return this.#olView.value;\n }\n\n /**\n * TODO: Can be removed once the LayerFactory is the only supported way of constructing a layer.\n *\n * @internal\n */\n get [LAYER_DEPS](): LayerDependencies {\n return this.#layerDeps;\n }\n\n /**\n * Create and receive map overlays\n */\n get overlays(): Overlays {\n return this.#tooltips;\n }\n\n /**\n * Create, receive and zoom to map highlights\n */\n get highlights(): Highlights {\n return this.#highlights;\n }\n\n /**\n * Changes the current scale of the map to the given value.\n *\n * Internally, this computes a new zoom level / resolution based on the scale\n * and the current center.\n * The new resolution is then applied to the current `olView`.\n *\n * See also {@link scale}.\n */\n setScale(newScale: number): void {\n const view = this.olView;\n const projection = this.projection;\n const center = this.center;\n if (!center) {\n return;\n }\n\n const mpu = projection.getMetersPerUnit() ?? 1;\n const resolution = INCHES_PER_METRE * DEFAULT_DPI * mpu;\n const pointResolution = newScale / getPointResolution(projection, resolution, center);\n view.setResolution(pointResolution);\n }\n\n /**\n * Zooms to the given targets.\n */\n zoom(displayTargets: DisplayTarget[], options?: ZoomOptions | undefined): void {\n const olView = this.olView;\n const geometries = getGeometries(displayTargets);\n if (geometries.length === 0) {\n return;\n }\n\n let extent = createEmpty();\n for (const geometry of geometries) {\n extent = extend(extent, geometry.getExtent());\n }\n\n const bufferParameter = options?.buffer;\n if (typeof bufferParameter === \"number\") {\n extent = calculateBufferedExtent(extent, bufferParameter);\n }\n\n const center = getCenter(extent);\n const isPoint = getArea(extent) === 0;\n const zoomLevel = isPoint\n ? (options?.pointZoom ?? DEFAULT_OL_POINT_ZOOM_LEVEL)\n : (options?.maxZoom ?? DEFAULT_OL_MAX_ZOOM_LEVEL);\n if (center && center.length) {\n olView.setCenter(center);\n }\n\n const {\n top = 0,\n right = 0,\n bottom = 0,\n left = 0\n } = options?.viewPadding ?? DEFAULT_VIEW_PADDING;\n const padding = [top, right, bottom, left];\n\n if (extent) {\n olView.fit(extent, { maxZoom: zoomLevel, padding });\n } else if (zoomLevel) {\n olView.setZoom(zoomLevel);\n }\n }\n\n /**\n * Creates a highlight at the given targets.\n *\n * A highlight is a temporary graphic on the map that calls attention to a point or an area.\n *\n * Call `destroy()` on the returned highlight object to remove the highlight.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.add} instead.\n */\n highlight(geometries: DisplayTarget[], options?: HighlightOptions | undefined): Highlight {\n deprecatedHighlights();\n return this.#highlights.add(geometries, options);\n }\n\n /**\n * Creates a highlight and zooms to the given targets.\n *\n * See also {@link highlight} and {@link zoom}.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.addAndZoom} instead.\n */\n highlightAndZoom(geometries: DisplayTarget[], options?: HighlightZoomOptions): Highlight {\n deprecatedHighlights();\n return this.#highlights.addAndZoom(geometries, options ?? {});\n }\n\n /**\n * Removes any existing highlights from the map.\n *\n * @deprecated Highlight functions wil be removed in a future major release; call {@link Highlights.clear} instead.\n */\n removeHighlights(): void {\n deprecatedHighlights();\n this.#highlights.clear();\n }\n\n /**\n * Returns a promise that resolves when the map has mounted in the DOM.\n */\n whenDisplayed(): Promise<void> {\n if (this.#isDestroyed) {\n return Promise.reject(new Error(\"Map model was destroyed.\"));\n }\n if (this.#displayStatus === \"error\") {\n return Promise.reject(new Error(`Failed to initialize map.`));\n }\n if (this.#displayStatus === \"ready\") {\n return Promise.resolve();\n }\n return (this.#displayWaiter ??= createManualPromise()).promise;\n }\n\n /**\n * Waits for the map to be displayed and then initializes the view (if necessary).\n *\n * May simply resolve when done, or throw an error when a problem occurs.\n * AbortError is thrown when cancelled via `this.#abortController`, for example\n * when the map model is destroyed before it has ever been displayed.\n */\n async #initializeView(): Promise<void> {\n try {\n await waitForMapSize(this.olMap, this.#abortController.signal); // may throw on cancel\n } catch (e) {\n if (isAbortError(e)) {\n throw e;\n }\n throw new Error(`Failed to wait for the map to be displayed.`, { cause: e });\n }\n\n try {\n const olMap = this.#olMap;\n const view = olMap.getView();\n\n if (this.#initialExtent.value) {\n // Initial extent was set from the outside. We simply ensure that it gets displayed by the map.\n const extent = this.#initialExtent.value;\n const olExtent = [extent.xMin, extent.yMin, extent.xMax, extent.yMax];\n\n const olCenter = getCenter(olExtent);\n const resolution = view.getResolutionForExtent(olExtent);\n LOG.debug(`Applying initial extent`, extent);\n LOG.debug(` Computed center:`, olCenter);\n LOG.debug(` Computed resolution:`, resolution);\n\n view.setCenter(olCenter);\n view.setResolution(resolution);\n } else {\n // Initial extent was NOT set from the outside.\n // We detect whatever the view is displaying and consider it to be the initial extent.\n const olExtent = view.calculateExtent();\n const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = olExtent;\n const extent: ExtentConfig = { xMin, yMin, xMax, yMax };\n LOG.debug(`Detected initial extent`, extent);\n\n this.#initialExtent.value = extent;\n }\n } catch (e) {\n throw new Error(`Failed to apply the initial extent.`, { cause: e });\n }\n }\n\n /**\n * Subscribes to the OpenLayers loading state.\n */\n #watchLoadingState() {\n this.#loadStartEventHandler = this.#olMap.on(\"loadstart\", () => {\n this.#olLoading.value = true;\n });\n this.#loadEndEventHandler = this.#olMap.on(\"loadend\", () => {\n this.#olLoading.value = false;\n });\n }\n}\n\ninterface ViewBindings {\n resolution: ReadonlyReactive<number | undefined>;\n center: ReadonlyReactive<Coordinate | undefined>;\n zoom: ReadonlyReactive<number | undefined>;\n projection: Projection; // not reactive (change view to change projection)\n}\n\nfunction createViewBindings(view: OlView): ViewBindings {\n return {\n resolution: synchronized(\n () => view.getResolution(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n center: synchronized(\n () => view.getCenter(),\n (cb) => {\n const key = view.on(\"change:center\", cb);\n return () => unByKey(key);\n }\n ),\n zoom: synchronized(\n () => view.getZoom(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n projection: view.getProjection()\n };\n}\n\nfunction waitForMapSize(olMap: OlMap, signal: AbortSignal): Promise<void> {\n const promise = new Promise<void>((resolve, reject) => {\n let eventKey: EventsKey | undefined;\n\n function checkSize() {\n const currentSize = olMap.getSize() ?? [];\n const [width = 0, height = 0] = currentSize;\n if (currentSize && width > 0 && height > 0) {\n finish();\n }\n }\n\n function onAbort() {\n finish(createAbortError());\n }\n\n function finish(error?: Error | undefined) {\n if (eventKey) {\n unByKey(eventKey);\n eventKey = undefined;\n }\n signal.removeEventListener(\"abort\", onAbort);\n\n if (error) {\n reject(error);\n } else {\n resolve(wait(25)); // Give the map some time to render\n }\n }\n\n if (signal.aborted) {\n finish(createAbortError());\n return;\n }\n\n signal.addEventListener(\"abort\", onAbort);\n eventKey = olMap.on(\"change:size\", checkSize);\n });\n return promise;\n}\n\nfunction wait(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapModel.js","sources":["MapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { computed, reactive, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport { emit, emitter, EventSource } from \"@conterra/reactivity-events\";\nimport {\n createAbortError,\n createLogger,\n createManualPromise,\n deprecated,\n isAbortError,\n ManualPromise\n} from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\nimport OlView from \"ol/View\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { createEmpty, extend, getArea, getCenter } from \"ol/extent\";\nimport { getPointResolution, Projection } from \"ol/proj\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LAYER_DEPS, LayerDependencies } from \"../layers/shared/internals\";\nimport {\n assertInternalConstructor,\n INTERNAL_CONSTRUCTOR_TAG,\n InternalConstructorTag\n} from \"../utils/InternalConstructorTag\";\nimport { calculateBufferedExtent } from \"../utils/geometry-utils\";\nimport {\n DESTROY_HIGHLIGHTS,\n Highlight,\n HighlightOptions,\n Highlights,\n HighlightZoomOptions\n} from \"./Highlights\";\nimport { LayerCollection } from \"./LayerCollection\";\nimport { ExtentConfig } from \"./MapConfig\";\nimport { Overlays } from \"./Overlays\";\nimport { getGeometries } from \"./getGeometries\";\nimport { BaseFeature } from \"../utils/BaseFeature\";\nimport { Geometry } from \"ol/geom\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapAttributions } from \"./MapAttributions\";\n\nconst LOG = createLogger(sourceId);\n\nconst DEFAULT_DPI = 25.4 / 0.28;\nconst INCHES_PER_METRE = 39.37;\n\nconst DEFAULT_OL_POINT_ZOOM_LEVEL = 17;\nconst DEFAULT_OL_MAX_ZOOM_LEVEL = 20;\nconst DEFAULT_VIEW_PADDING = { top: 50, right: 20, bottom: 10, left: 20 };\n\nexport const DISPLAY_STATUS = Symbol(\"DISPLAY_STATUS\");\n\nconst deprecatedHighlights = deprecated({\n name: \"MapModel highlight function called\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.3.0\",\n alternative: \"call methods of myMapModel.highlights instead\"\n});\n\n/**\n * Options supported when calling {@link MapModel.zoom}.\n *\n * @group Map Model\n **/\nexport interface ZoomOptions {\n /**\n * The zoom-level used if there is no valid extend (such as for single points).\n */\n pointZoom?: number;\n\n /**\n * The maximum zoom-level for multiple points, line or polygon results.\n */\n maxZoom?: number;\n\n /**\n * The view padding to make all features visible.\n */\n viewPadding?: MapPadding;\n\n /**\n * The buffer factor around the extent of the zoomed features. E.g. a value of 1.1 will add\n * 10% to specify the size increase of the extent's width and height.\n */\n buffer?: number;\n}\n\n/**\n * Represents an object in the map.\n *\n * @group Map Model\n */\nexport type DisplayTarget = BaseFeature | Geometry;\n\n/**\n * Map padding, all values are pixels.\n *\n * See https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding\n *\n * @group Map Model\n */\nexport interface MapPadding {\n left?: number;\n right?: number;\n top?: number;\n bottom?: number;\n}\n\n/**\n * An item that should be displayed as part of the attributions for the map.\n *\n * @group MapModel\n */\nexport interface AttributionItem {\n /**\n * The attribution's text.\n *\n * Note that this property contains raw HTML tags.\n * The HTML content has been sanitized, so it is safe to display in the user interface.\n */\n text: string;\n}\n\ntype DisplayStatus = \"waiting\" | \"ready\" | \"error\";\n\n/**\n * Represents a map.\n *\n * @group Map Model\n */\nexport class MapModel {\n readonly #id: string;\n readonly #olMap: OlMap;\n readonly #olView: ReadonlyReactive<OlView>;\n readonly #attributions: MapAttributions;\n readonly #layers = new LayerCollection(this, INTERNAL_CONSTRUCTOR_TAG);\n readonly #highlights: Highlights;\n readonly #tooltips: Overlays;\n readonly #layerDeps: LayerDependencies;\n readonly #destroyed = emitter();\n\n #loadStartEventHandler: EventsKey | undefined;\n #loadEndEventHandler: EventsKey | undefined;\n readonly #olLoading = reactive(false);\n\n #isDestroyed = false;\n readonly #container: ReadonlyReactive<HTMLElement | undefined>;\n readonly #initialExtent = reactive<ExtentConfig>();\n readonly #viewBindings: ReadonlyReactive<ViewBindings>;\n readonly #scale: ReadonlyReactive<number | undefined>;\n\n readonly #abortController = new AbortController();\n #displayStatus: DisplayStatus;\n #displayWaiter: ManualPromise<void> | undefined;\n\n /**\n * @internal\n */\n constructor(\n options: {\n id: string;\n olMap: OlMap;\n initialExtent: ExtentConfig | undefined;\n showDefaultAttributions: boolean;\n currentIntl: ReadonlyReactive<PackageIntl>;\n httpService: HttpService;\n },\n tag: InternalConstructorTag\n ) {\n assertInternalConstructor(tag);\n\n this.#id = options.id;\n this.#olMap = options.olMap;\n this.#attributions = new MapAttributions({\n intl: options.currentIntl,\n olMap: this.#olMap,\n showControl: options.showDefaultAttributions\n });\n\n this.#olView = synchronized(\n () => this.#olMap.getView(),\n (cb) => {\n const key = this.#olMap.on(\"change:view\", cb);\n return () => unByKey(key);\n }\n );\n\n // NOTE: As early as possible (before any async actions) so we don't miss any events.\n this.#watchLoadingState();\n\n this.#initialExtent.value = options.initialExtent;\n this.#layerDeps = {\n httpService: options.httpService\n };\n\n this.#displayStatus = \"waiting\";\n this.#initializeView().then(\n () => {\n this.#displayStatus = \"ready\";\n this.#displayWaiter?.resolve();\n this.#displayWaiter = undefined;\n },\n (error) => {\n if (!isAbortError(error)) {\n LOG.error(`Failed to initialize map`, error);\n }\n\n this.#displayStatus = \"error\";\n this.#displayWaiter?.reject(new Error(`Failed to initialize map.`));\n this.#displayWaiter = undefined;\n }\n );\n\n this.#container = synchronized(\n () => this.#olMap.getTargetElement() ?? undefined,\n (cb) => {\n const key = this.#olMap.on(\"change:target\", cb);\n return () => unByKey(key);\n }\n );\n\n this.#viewBindings = computed(() => createViewBindings(this.#olView.value));\n this.#scale = computed(() => {\n const { projection, resolution, center } = this;\n if (projection == null || resolution == null || center == null) {\n return undefined;\n }\n\n /**\n * Returns the appropriate scale for the given resolution and units, see OpenLayers function getScaleForResolution()\n * https://github.com/openlayers/openlayers/blob/7fa9df03431e9e1bc517e6c414565d9f848a3132/src/ol/control/ScaleLine.js#L454C3-L454C24\n */\n const pointResolution = getPointResolution(projection, resolution, center, \"m\"); //point resolution in meter per pixel\n const scale = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);\n return scale;\n });\n\n // expects fully constructed mapModel\n this.#highlights = new Highlights(this, this.#layerDeps);\n this.#tooltips = new Overlays(this);\n }\n\n /**\n * Destroys this objects, including all layers, highlights and the OL map itself.\n */\n destroy() {\n if (this.#isDestroyed) {\n return;\n }\n\n this.#isDestroyed = true;\n try {\n emit(this.#destroyed);\n } catch (e) {\n LOG.warn(`Unexpected error from event listener during map model destruction:`, e);\n }\n\n this.#loadStartEventHandler && unByKey(this.#loadStartEventHandler);\n this.#loadStartEventHandler = undefined;\n this.#loadEndEventHandler && unByKey(this.#loadEndEventHandler);\n this.#loadEndEventHandler = undefined;\n\n this.#abortController.abort();\n this.#displayWaiter?.reject(new Error(\"Map model was destroyed.\"));\n this.#layers.destroy();\n this.#highlights[DESTROY_HIGHLIGHTS]();\n this.#attributions.destroy();\n this.#olMap.dispose();\n }\n\n /**\n * Emitted when the map model is destroyed.\n */\n get destroyed(): EventSource<void> {\n return this.#destroyed;\n }\n\n /**\n * Returns the map's current display status.\n * This is `waiting` during initialization and `error` or `ready` when done.\n *\n * @internal\n */\n get [DISPLAY_STATUS](): DisplayStatus {\n return this.#displayStatus;\n }\n\n /**\n * The unique id of the map.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * The initial map extent.\n *\n * May be undefined before the map is shown.\n * This is guaranteed to be initialized if the promise returned by {@link whenDisplayed} has resolved.\n */\n get initialExtent(): ExtentConfig | undefined {\n return this.#initialExtent.value;\n }\n\n /**\n * Returns the current projection of the map (reactive).\n */\n get projection(): Projection {\n return this.#viewBindings.value.projection;\n }\n\n /**\n * Returns the current center of the map.\n * Same as `olView.getCenter()`, but reactive.\n */\n get center(): Coordinate | undefined {\n return this.#viewBindings.value.center.value;\n }\n\n /**\n * Returns the current resolution of the map.\n * Same as `olView.getResolution()`, but reactive.\n */\n get resolution(): number | undefined {\n return this.#viewBindings.value.resolution.value;\n }\n\n /**\n * Returns the current zoom level of the map.\n * Same as `olView.getZoom()`, but reactive.\n */\n get zoomLevel(): number | undefined {\n return this.#viewBindings.value.zoom.value;\n }\n\n /**\n * Returns the current scale of the map.\n *\n * The scale is a value derived from the current `center`, `resolution` and `projection` of the map.\n * The scale will change when the map is zoomed in our out, but depending on the projection, it may also\n * change when the map is _panned_.\n *\n * > NOTE: Technically, this is the _denominator_ of the current scale.\n * > In order to display it, use a format like `1:${scale}`.\n */\n get scale(): number | undefined {\n return this.#scale.value;\n }\n\n /**\n * Returns true if the map is currently loading.\n *\n * This is based on the OpenLayers events `loadstart` and `loadend`,\n * see [Documentation](https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:loadstart).\n */\n get loading(): boolean {\n return this.#olLoading.value;\n }\n\n /**\n * Contains all known layers of this map.\n *\n * Note that not all layers in this collection may be active in the OpenLayers map.\n * Also note that not all layers in the OpenLayers map may be contained in this collection.\n */\n get layers(): LayerCollection {\n return this.#layers;\n }\n\n /**\n * The container in which the map is currently being rendered.\n * This is the same as the target element of the underlying OpenLayers map.\n *\n * May be undefined if the map is not being rendered at the moment.\n * May change at runtime.\n */\n get container(): HTMLElement | undefined {\n return this.#container.value;\n }\n\n /**\n * Returns attributions for the current content of the map.\n */\n get attributionItems(): AttributionItem[] {\n return this.#attributions.attributionItems;\n }\n\n /**\n * The raw OpenLayers map.\n */\n get olMap(): OlMap {\n return this.#olMap;\n }\n\n /**\n * Returns the current view of the OpenLayers map.\n */\n get olView(): OlView {\n return this.#olView.value;\n }\n\n /**\n * TODO: Can be removed once the LayerFactory is the only supported way of constructing a layer.\n *\n * @internal\n */\n get [LAYER_DEPS](): LayerDependencies {\n return this.#layerDeps;\n }\n\n /**\n * Create and receive map overlays\n */\n get overlays(): Overlays {\n return this.#tooltips;\n }\n\n /**\n * Create, receive and zoom to map highlights\n */\n get highlights(): Highlights {\n return this.#highlights;\n }\n\n /**\n * Changes the current scale of the map to the given value.\n *\n * Internally, this computes a new zoom level / resolution based on the scale\n * and the current center.\n * The new resolution is then applied to the current `olView`.\n *\n * See also {@link scale}.\n */\n setScale(newScale: number): void {\n const view = this.olView;\n const projection = this.projection;\n const center = this.center;\n if (!center) {\n return;\n }\n\n const mpu = projection.getMetersPerUnit() ?? 1;\n const resolution = INCHES_PER_METRE * DEFAULT_DPI * mpu;\n const pointResolution = newScale / getPointResolution(projection, resolution, center);\n view.setResolution(pointResolution);\n }\n\n /**\n * Zooms to the given targets.\n */\n zoom(displayTargets: DisplayTarget[], options?: ZoomOptions | undefined): void {\n const olView = this.olView;\n const geometries = getGeometries(displayTargets);\n if (geometries.length === 0) {\n return;\n }\n\n let extent = createEmpty();\n for (const geometry of geometries) {\n extent = extend(extent, geometry.getExtent());\n }\n\n const bufferParameter = options?.buffer;\n if (typeof bufferParameter === \"number\") {\n extent = calculateBufferedExtent(extent, bufferParameter);\n }\n\n const center = getCenter(extent);\n const isPoint = getArea(extent) === 0;\n const zoomLevel = isPoint\n ? (options?.pointZoom ?? DEFAULT_OL_POINT_ZOOM_LEVEL)\n : (options?.maxZoom ?? DEFAULT_OL_MAX_ZOOM_LEVEL);\n if (center && center.length) {\n olView.setCenter(center);\n }\n\n const {\n top = 0,\n right = 0,\n bottom = 0,\n left = 0\n } = options?.viewPadding ?? DEFAULT_VIEW_PADDING;\n const padding = [top, right, bottom, left];\n\n if (extent) {\n olView.fit(extent, { maxZoom: zoomLevel, padding });\n } else if (zoomLevel) {\n olView.setZoom(zoomLevel);\n }\n }\n\n /**\n * Creates a highlight at the given targets.\n *\n * A highlight is a temporary graphic on the map that calls attention to a point or an area.\n *\n * Call `destroy()` on the returned highlight object to remove the highlight.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.add} instead.\n */\n highlight(geometries: DisplayTarget[], options?: HighlightOptions | undefined): Highlight {\n deprecatedHighlights();\n return this.#highlights.add(geometries, options);\n }\n\n /**\n * Creates a highlight and zooms to the given targets.\n *\n * See also {@link highlight} and {@link zoom}.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.addAndZoom} instead.\n */\n highlightAndZoom(geometries: DisplayTarget[], options?: HighlightZoomOptions): Highlight {\n deprecatedHighlights();\n return this.#highlights.addAndZoom(geometries, options ?? {});\n }\n\n /**\n * Removes any existing highlights from the map.\n *\n * @deprecated Highlight functions wil be removed in a future major release; call {@link Highlights.clear} instead.\n */\n removeHighlights(): void {\n deprecatedHighlights();\n this.#highlights.clear();\n }\n\n /**\n * Returns a promise that resolves when the map has mounted in the DOM.\n */\n whenDisplayed(): Promise<void> {\n if (this.#isDestroyed) {\n return Promise.reject(new Error(\"Map model was destroyed.\"));\n }\n if (this.#displayStatus === \"error\") {\n return Promise.reject(new Error(`Failed to initialize map.`));\n }\n if (this.#displayStatus === \"ready\") {\n return Promise.resolve();\n }\n return (this.#displayWaiter ??= createManualPromise()).promise;\n }\n\n /**\n * Waits for the map to be displayed and then initializes the view (if necessary).\n *\n * May simply resolve when done, or throw an error when a problem occurs.\n * AbortError is thrown when cancelled via `this.#abortController`, for example\n * when the map model is destroyed before it has ever been displayed.\n */\n async #initializeView(): Promise<void> {\n try {\n await waitForMapSize(this.olMap, this.#abortController.signal); // may throw on cancel\n } catch (e) {\n if (isAbortError(e)) {\n throw e;\n }\n throw new Error(`Failed to wait for the map to be displayed.`, { cause: e });\n }\n\n try {\n const olMap = this.#olMap;\n const view = olMap.getView();\n\n if (this.#initialExtent.value) {\n // Initial extent was set from the outside. We simply ensure that it gets displayed by the map.\n const extent = this.#initialExtent.value;\n const olExtent = [extent.xMin, extent.yMin, extent.xMax, extent.yMax];\n\n const olCenter = getCenter(olExtent);\n const resolution = view.getResolutionForExtent(olExtent);\n LOG.debug(`Applying initial extent`, extent);\n LOG.debug(` Computed center:`, olCenter);\n LOG.debug(` Computed resolution:`, resolution);\n\n view.setCenter(olCenter);\n view.setResolution(resolution);\n } else {\n // Initial extent was NOT set from the outside.\n // We detect whatever the view is displaying and consider it to be the initial extent.\n const olExtent = view.calculateExtent();\n const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = olExtent;\n const extent: ExtentConfig = { xMin, yMin, xMax, yMax };\n LOG.debug(`Detected initial extent`, extent);\n\n this.#initialExtent.value = extent;\n }\n } catch (e) {\n throw new Error(`Failed to apply the initial extent.`, { cause: e });\n }\n }\n\n /**\n * Subscribes to the OpenLayers loading state.\n */\n #watchLoadingState() {\n this.#loadStartEventHandler = this.#olMap.on(\"loadstart\", () => {\n this.#olLoading.value = true;\n });\n this.#loadEndEventHandler = this.#olMap.on(\"loadend\", () => {\n this.#olLoading.value = false;\n });\n }\n}\n\ninterface ViewBindings {\n resolution: ReadonlyReactive<number | undefined>;\n center: ReadonlyReactive<Coordinate | undefined>;\n zoom: ReadonlyReactive<number | undefined>;\n projection: Projection; // not reactive (change view to change projection)\n}\n\nfunction createViewBindings(view: OlView): ViewBindings {\n return {\n resolution: synchronized(\n () => view.getResolution(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n center: synchronized(\n () => view.getCenter(),\n (cb) => {\n const key = view.on(\"change:center\", cb);\n return () => unByKey(key);\n }\n ),\n zoom: synchronized(\n () => view.getZoom(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n projection: view.getProjection()\n };\n}\n\nfunction waitForMapSize(olMap: OlMap, signal: AbortSignal): Promise<void> {\n const promise = new Promise<void>((resolve, reject) => {\n let eventKey: EventsKey | undefined;\n\n function checkSize() {\n const currentSize = olMap.getSize() ?? [];\n const [width = 0, height = 0] = currentSize;\n if (currentSize && width > 0 && height > 0) {\n finish();\n }\n }\n\n function onAbort() {\n finish(createAbortError());\n }\n\n function finish(error?: Error | undefined) {\n if (eventKey) {\n unByKey(eventKey);\n eventKey = undefined;\n }\n signal.removeEventListener(\"abort\", onAbort);\n\n if (error) {\n reject(error);\n } else {\n resolve(wait(25)); // Give the map some time to render\n }\n }\n\n if (signal.aborted) {\n finish(createAbortError());\n return;\n }\n\n signal.addEventListener(\"abort\", onAbort);\n eventKey = olMap.on(\"change:size\", checkSize);\n });\n return promise;\n}\n\nfunction wait(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ReadonlyReactive } from "@conterra/reactivity-core";
|
|
1
2
|
import { HttpService } from "@open-pioneer/http";
|
|
2
3
|
import { PackageIntl } from "@open-pioneer/runtime";
|
|
3
4
|
import { MapConfig } from "./MapConfig";
|
|
4
5
|
import { MapModel } from "./MapModel";
|
|
5
|
-
export declare function createMapModel(mapId: string, mapConfig: MapConfig,
|
|
6
|
+
export declare function createMapModel(mapId: string, mapConfig: MapConfig, currentIntl: ReadonlyReactive<PackageIntl>, httpService: HttpService): Promise<MapModel>;
|
package/model/createMapModel.js
CHANGED
|
@@ -18,18 +18,18 @@ registerProjections({
|
|
|
18
18
|
"EPSG:25833": "+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs"
|
|
19
19
|
});
|
|
20
20
|
const LOG = createLogger(sourceId);
|
|
21
|
-
async function createMapModel(mapId, mapConfig,
|
|
22
|
-
return await new MapModelFactory(mapId, mapConfig,
|
|
21
|
+
async function createMapModel(mapId, mapConfig, currentIntl, httpService) {
|
|
22
|
+
return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();
|
|
23
23
|
}
|
|
24
24
|
class MapModelFactory {
|
|
25
25
|
mapId;
|
|
26
26
|
mapConfig;
|
|
27
|
-
|
|
27
|
+
currentIntl;
|
|
28
28
|
httpService;
|
|
29
|
-
constructor(mapId, mapConfig,
|
|
29
|
+
constructor(mapId, mapConfig, currentIntl, httpService) {
|
|
30
30
|
this.mapId = mapId;
|
|
31
31
|
this.mapConfig = mapConfig;
|
|
32
|
-
this.
|
|
32
|
+
this.currentIntl = currentIntl;
|
|
33
33
|
this.httpService = httpService;
|
|
34
34
|
}
|
|
35
35
|
async createMapModel() {
|
|
@@ -78,7 +78,7 @@ class MapModelFactory {
|
|
|
78
78
|
olMap,
|
|
79
79
|
initialExtent,
|
|
80
80
|
showDefaultAttributions,
|
|
81
|
-
|
|
81
|
+
currentIntl: this.currentIntl,
|
|
82
82
|
httpService: this.httpService
|
|
83
83
|
},
|
|
84
84
|
INTERNAL_CONSTRUCTOR_TAG
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createMapModel.js","sources":["createMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapBrowserEvent } from \"ol\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport View, { ViewOptions } from \"ol/View\";\nimport { getCenter } from \"ol/extent\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport TileLayer from \"ol/layer/Tile\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { INTERNAL_CONSTRUCTOR_TAG } from \"../utils/InternalConstructorTag\";\nimport { patchOpenLayersClassesForTesting } from \"../utils/ol-test-support\";\nimport { registerProjections } from \"../utils/projections\";\nimport { MapConfig } from \"./MapConfig\";\nimport { MapModel } from \"./MapModel\";\n\n/**\n * Register custom projection to the global proj4js definitions. User can select `EPSG:25832`\n * and `EPSG:25833` from the predefined projections without calling `registerProjections`.\n */\nregisterProjections({\n \"EPSG:25832\":\n \"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\",\n \"EPSG:25833\":\n \"+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\"\n});\nconst LOG = createLogger(sourceId);\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n intl: PackageIntl,\n httpService: HttpService\n): Promise<MapModel> {\n return await new MapModelFactory(mapId, mapConfig, intl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n private mapId: string;\n private mapConfig: MapConfig;\n private intl: PackageIntl;\n private httpService: HttpService;\n\n constructor(mapId: string, mapConfig: MapConfig, intl: PackageIntl, httpService: HttpService) {\n this.mapId = mapId;\n this.mapConfig = mapConfig;\n this.intl = intl;\n this.httpService = httpService;\n }\n\n async createMapModel() {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};\n const showDefaultAttributions =\n mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);\n\n const mapOptions: MapOptions = {\n ...rawOlOptions\n };\n if (!mapOptions.controls) {\n mapOptions.controls = [];\n }\n if (!mapOptions.interactions) {\n const shiftCtrlKeysOnly = (\n mapBrowserEvent: MapBrowserEvent<KeyboardEvent | WheelEvent | PointerEvent>\n ) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return (originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n };\n\n // setting altShiftDragRotate to false disables or excludes DragRotate interaction\n mapOptions.interactions = defaultInteractions({\n dragPan: true,\n altShiftDragRotate: false,\n pinchRotate: false,\n mouseWheelZoom: true\n }).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);\n }\n\n const view = (await viewOption) ?? {};\n this.initializeViewOptions(view);\n mapOptions.view = view instanceof View ? view : new View(view);\n\n if (!mapOptions.layers && !mapConfig.layers) {\n mapOptions.layers = [\n new TileLayer({\n source: new OSM()\n })\n ];\n }\n\n const initialView = mapConfig.initialView;\n const initialExtent = initialView?.kind === \"extent\" ? initialView.extent : undefined;\n\n LOG.debug(`Constructing OpenLayers map with options`, mapOptions);\n\n if (import.meta.env.VITEST) {\n patchOpenLayersClassesForTesting();\n }\n\n const olMap = new OlMap(mapOptions);\n const mapModel = new MapModel(\n {\n id: mapId,\n olMap,\n initialExtent,\n showDefaultAttributions,\n intl: this.intl,\n httpService: this.httpService\n },\n INTERNAL_CONSTRUCTOR_TAG\n );\n\n return batch(() => {\n try {\n if (mapConfig.layers) {\n for (const layerConfig of mapConfig.layers) {\n mapModel.layers.addLayer(layerConfig);\n }\n }\n return mapModel;\n } catch (e) {\n mapModel.destroy();\n throw e;\n }\n });\n }\n\n private initializeViewOptions(view: View | ViewOptions) {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n if (view instanceof View) {\n const warn = (prop: string) => {\n LOG.warn(\n `The advanced configuration for map id '${mapId}' has provided a fully constructed view instance: ${prop} cannot be applied.\\n` +\n `Use ViewOptions instead of a View instance.`\n );\n };\n\n if (mapConfig.projection != null) {\n warn(\"projection\");\n }\n if (mapConfig.initialView != null) {\n warn(\"initialView\");\n }\n return;\n }\n\n const projection = (view.projection = this.initializeProjection(mapConfig.projection));\n const initialView = mapConfig.initialView;\n if (initialView) {\n switch (initialView.kind) {\n case \"position\":\n view.zoom = initialView.zoom;\n view.center = [initialView.center.x, initialView.center.y];\n break;\n case \"extent\": {\n /*\n OpenLayers does not support configuration of the initial map extent.\n The only relevant options here are center, zoom (and resolution).\n We must set those values because otherwise OpenLayers will not initialize layer sources.\n\n The actual initial extent is applied once tha map has loaded and its size is known.\n */\n const extent = initialView.extent;\n view.zoom = 0;\n view.center = [\n extent.xMin + (extent.xMax - extent.xMin) / 2,\n extent.yMin + (extent.yMax - extent.yMin) / 2\n ];\n break;\n }\n }\n } else {\n this.setViewDefaults(view, projection);\n }\n }\n\n private setViewDefaults(view: ViewOptions, projection: Projection) {\n if (view.center == null) {\n const extent = projection.getExtent(); // can be null\n if (!extent) {\n LOG.warn(\n `Cannot set default center coordinate because the current projection has no associated extent.\\n` +\n `Try to configure 'initialView' explicity.`\n );\n } else {\n view.center = getCenter(extent);\n }\n }\n\n if (view.zoom == null || view.resolution == null) {\n view.zoom = 0;\n }\n }\n\n private initializeProjection(projectionOption: MapConfig[\"projection\"]) {\n if (projectionOption == null) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return getProjection(\"EPSG:3857\")!; // default OpenLayers projection\n }\n\n const projection = getProjection(projectionOption);\n if (!projection) {\n throw new Error(`Failed to retrieve projection for code '${projectionOption}'.`);\n }\n return projection;\n }\n}\n"],"names":["defaultInteractions","getProjection"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createMapModel.js","sources":["createMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapBrowserEvent } from \"ol\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport View, { ViewOptions } from \"ol/View\";\nimport { getCenter } from \"ol/extent\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport TileLayer from \"ol/layer/Tile\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { INTERNAL_CONSTRUCTOR_TAG } from \"../utils/InternalConstructorTag\";\nimport { patchOpenLayersClassesForTesting } from \"../utils/ol-test-support\";\nimport { registerProjections } from \"../utils/projections\";\nimport { MapConfig } from \"./MapConfig\";\nimport { MapModel } from \"./MapModel\";\n\n/**\n * Register custom projection to the global proj4js definitions. User can select `EPSG:25832`\n * and `EPSG:25833` from the predefined projections without calling `registerProjections`.\n */\nregisterProjections({\n \"EPSG:25832\":\n \"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\",\n \"EPSG:25833\":\n \"+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\"\n});\nconst LOG = createLogger(sourceId);\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n): Promise<MapModel> {\n return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n private mapId: string;\n private mapConfig: MapConfig;\n private currentIntl: ReadonlyReactive<PackageIntl>;\n private httpService: HttpService;\n\n constructor(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n ) {\n this.mapId = mapId;\n this.mapConfig = mapConfig;\n this.currentIntl = currentIntl;\n this.httpService = httpService;\n }\n\n async createMapModel() {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};\n const showDefaultAttributions =\n mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);\n\n const mapOptions: MapOptions = {\n ...rawOlOptions\n };\n if (!mapOptions.controls) {\n mapOptions.controls = [];\n }\n if (!mapOptions.interactions) {\n const shiftCtrlKeysOnly = (\n mapBrowserEvent: MapBrowserEvent<KeyboardEvent | WheelEvent | PointerEvent>\n ) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return (originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n };\n\n // setting altShiftDragRotate to false disables or excludes DragRotate interaction\n mapOptions.interactions = defaultInteractions({\n dragPan: true,\n altShiftDragRotate: false,\n pinchRotate: false,\n mouseWheelZoom: true\n }).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);\n }\n\n const view = (await viewOption) ?? {};\n this.initializeViewOptions(view);\n mapOptions.view = view instanceof View ? view : new View(view);\n\n if (!mapOptions.layers && !mapConfig.layers) {\n mapOptions.layers = [\n new TileLayer({\n source: new OSM()\n })\n ];\n }\n\n const initialView = mapConfig.initialView;\n const initialExtent = initialView?.kind === \"extent\" ? initialView.extent : undefined;\n\n LOG.debug(`Constructing OpenLayers map with options`, mapOptions);\n\n if (import.meta.env.VITEST) {\n patchOpenLayersClassesForTesting();\n }\n\n const olMap = new OlMap(mapOptions);\n const mapModel = new MapModel(\n {\n id: mapId,\n olMap,\n initialExtent,\n showDefaultAttributions,\n currentIntl: this.currentIntl,\n httpService: this.httpService\n },\n INTERNAL_CONSTRUCTOR_TAG\n );\n\n return batch(() => {\n try {\n if (mapConfig.layers) {\n for (const layerConfig of mapConfig.layers) {\n mapModel.layers.addLayer(layerConfig);\n }\n }\n return mapModel;\n } catch (e) {\n mapModel.destroy();\n throw e;\n }\n });\n }\n\n private initializeViewOptions(view: View | ViewOptions) {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n if (view instanceof View) {\n const warn = (prop: string) => {\n LOG.warn(\n `The advanced configuration for map id '${mapId}' has provided a fully constructed view instance: ${prop} cannot be applied.\\n` +\n `Use ViewOptions instead of a View instance.`\n );\n };\n\n if (mapConfig.projection != null) {\n warn(\"projection\");\n }\n if (mapConfig.initialView != null) {\n warn(\"initialView\");\n }\n return;\n }\n\n const projection = (view.projection = this.initializeProjection(mapConfig.projection));\n const initialView = mapConfig.initialView;\n if (initialView) {\n switch (initialView.kind) {\n case \"position\":\n view.zoom = initialView.zoom;\n view.center = [initialView.center.x, initialView.center.y];\n break;\n case \"extent\": {\n /*\n OpenLayers does not support configuration of the initial map extent.\n The only relevant options here are center, zoom (and resolution).\n We must set those values because otherwise OpenLayers will not initialize layer sources.\n\n The actual initial extent is applied once tha map has loaded and its size is known.\n */\n const extent = initialView.extent;\n view.zoom = 0;\n view.center = [\n extent.xMin + (extent.xMax - extent.xMin) / 2,\n extent.yMin + (extent.yMax - extent.yMin) / 2\n ];\n break;\n }\n }\n } else {\n this.setViewDefaults(view, projection);\n }\n }\n\n private setViewDefaults(view: ViewOptions, projection: Projection) {\n if (view.center == null) {\n const extent = projection.getExtent(); // can be null\n if (!extent) {\n LOG.warn(\n `Cannot set default center coordinate because the current projection has no associated extent.\\n` +\n `Try to configure 'initialView' explicity.`\n );\n } else {\n view.center = getCenter(extent);\n }\n }\n\n if (view.zoom == null || view.resolution == null) {\n view.zoom = 0;\n }\n }\n\n private initializeProjection(projectionOption: MapConfig[\"projection\"]) {\n if (projectionOption == null) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return getProjection(\"EPSG:3857\")!; // default OpenLayers projection\n }\n\n const projection = getProjection(projectionOption);\n if (!projection) {\n throw new Error(`Failed to retrieve projection for code '${projectionOption}'.`);\n }\n return projection;\n }\n}\n"],"names":["defaultInteractions","getProjection"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@open-pioneer/map",
|
|
4
|
-
"version": "1.3.0-dev.
|
|
4
|
+
"version": "1.3.0-dev.20260519140411",
|
|
5
5
|
"description": "This package integrates OpenLayers maps into an open pioneer trails application.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"open-pioneer-trails"
|
|
@@ -14,21 +14,21 @@
|
|
|
14
14
|
"directory": "src/packages/map"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@chakra-ui/react": "^3.
|
|
18
|
-
"@conterra/reactivity-core": "^0.8.
|
|
19
|
-
"@conterra/reactivity-events": "^0.8.
|
|
17
|
+
"@chakra-ui/react": "^3.35.0",
|
|
18
|
+
"@conterra/reactivity-core": "^0.8.5",
|
|
19
|
+
"@conterra/reactivity-events": "^0.8.5",
|
|
20
20
|
"@esri/arcgis-html-sanitizer": "^4.1.0",
|
|
21
|
-
"@open-pioneer/core": "4.6.0-dev.
|
|
22
|
-
"@open-pioneer/http": "4.6.0-dev.
|
|
23
|
-
"@open-pioneer/react-utils": "4.6.0-dev.
|
|
24
|
-
"@open-pioneer/reactivity": "4.6.0-dev.
|
|
25
|
-
"@open-pioneer/runtime": "4.6.0-dev.
|
|
21
|
+
"@open-pioneer/core": "4.6.0-dev.20260519125519",
|
|
22
|
+
"@open-pioneer/http": "4.6.0-dev.20260519125519",
|
|
23
|
+
"@open-pioneer/react-utils": "4.6.0-dev.20260519125519",
|
|
24
|
+
"@open-pioneer/reactivity": "4.6.0-dev.20260519125519",
|
|
25
|
+
"@open-pioneer/runtime": "4.6.0-dev.20260519125519",
|
|
26
26
|
"ol": "^10.9.0",
|
|
27
27
|
"proj4": "^2.20.8",
|
|
28
|
-
"react-dom": "^19.2.
|
|
28
|
+
"react-dom": "^19.2.6",
|
|
29
29
|
"react-use": "^17.6.0",
|
|
30
|
-
"react": "^19.2.
|
|
31
|
-
"uuid": "^
|
|
30
|
+
"react": "^19.2.6",
|
|
31
|
+
"uuid": "^14.0.0"
|
|
32
32
|
},
|
|
33
33
|
"exports": {
|
|
34
34
|
"./package.json": "./package.json",
|
|
@@ -106,6 +106,6 @@
|
|
|
106
106
|
]
|
|
107
107
|
},
|
|
108
108
|
"properties": [],
|
|
109
|
-
"packageFormatVersion": "1.0.
|
|
109
|
+
"packageFormatVersion": "1.0.1"
|
|
110
110
|
}
|
|
111
111
|
}
|