@geospatial-sdk/openlayers 0.0.3-alpha.6 → 0.0.5-alpha.2

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.
@@ -0,0 +1,2 @@
1
+ export * from "./map";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AACA,cAAc,OAAO,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ // PUBLIC API
2
+ export * from "./map";
@@ -0,0 +1,9 @@
1
+ import Map from "ol/Map";
2
+ import { MapContextDiff } from "@geospatial-sdk/core";
3
+ /**
4
+ * Apply a context diff to an OpenLayers map
5
+ * @param map
6
+ * @param contextDiff
7
+ */
8
+ export declare function applyContextDiffToMap(map: Map, contextDiff: MapContextDiff): Map;
9
+ //# sourceMappingURL=apply-context-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-context-diff.d.ts","sourceRoot":"","sources":["../../lib/map/apply-context-diff.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,QAAQ,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,cAAc,GAC1B,GAAG,CA6CL"}
@@ -0,0 +1,43 @@
1
+ import { createLayer } from "./create-map";
2
+ /**
3
+ * Apply a context diff to an OpenLayers map
4
+ * @param map
5
+ * @param contextDiff
6
+ */
7
+ export function applyContextDiffToMap(map, contextDiff) {
8
+ const layers = map.getLayers();
9
+ // removed layers (sorted by descending position)
10
+ if (contextDiff.layersRemoved.length > 0) {
11
+ const removed = contextDiff.layersRemoved.sort((a, b) => b.position - a.position);
12
+ for (const layerRemoved of removed) {
13
+ layers.item(layerRemoved.position).dispose();
14
+ layers.removeAt(layerRemoved.position);
15
+ }
16
+ }
17
+ // insert added layers
18
+ for (const layerAdded of contextDiff.layersAdded) {
19
+ const layer = createLayer(layerAdded.layer);
20
+ if (layerAdded.position >= layers.getLength()) {
21
+ layers.push(layer);
22
+ }
23
+ else {
24
+ layers.insertAt(layerAdded.position, layer);
25
+ }
26
+ }
27
+ // move reordered layers (sorted by ascending new position)
28
+ if (contextDiff.layersReordered.length > 0) {
29
+ const reordered = contextDiff.layersReordered.sort((a, b) => a.newPosition - b.newPosition);
30
+ const olLayers = reordered.map((layer) => layers.item(layer.previousPosition));
31
+ const layersArray = layers.getArray();
32
+ for (let i = 0; i < reordered.length; i++) {
33
+ layersArray[reordered[i].newPosition] = olLayers[i];
34
+ }
35
+ map.setLayers([...layersArray]);
36
+ }
37
+ // recreate changed layers
38
+ for (const layerChanged of contextDiff.layersChanged) {
39
+ layers.item(layerChanged.position).dispose();
40
+ layers.setAt(layerChanged.position, createLayer(layerChanged.layer));
41
+ }
42
+ return map;
43
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=apply-context-diff.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-context-diff.test.d.ts","sourceRoot":"","sources":["../../lib/map/apply-context-diff.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,251 @@
1
+ import { SAMPLE_CONTEXT, SAMPLE_LAYER1, SAMPLE_LAYER2, SAMPLE_LAYER3, SAMPLE_LAYER4, SAMPLE_LAYER5, } from "@geospatial-sdk/core/fixtures/map-context.fixtures";
2
+ import { createLayer, createMapFromContext } from "./create-map";
3
+ import { applyContextDiffToMap } from "./apply-context-diff";
4
+ import { beforeEach } from "vitest";
5
+ function assertEqualsToModel(layer, layerModel) {
6
+ var _a;
7
+ const reference = createLayer(layerModel);
8
+ expect(reference).toBeInstanceOf(layer.constructor);
9
+ const refSource = reference.getSource();
10
+ const layerSource = layer.getSource();
11
+ expect(reference.getSource()).toBeInstanceOf((_a = layer.getSource()) === null || _a === void 0 ? void 0 : _a.constructor);
12
+ if (typeof (refSource === null || refSource === void 0 ? void 0 : refSource.getUrl) === "function") {
13
+ expect(layerSource === null || layerSource === void 0 ? void 0 : layerSource.getUrl).toBeTypeOf("function");
14
+ }
15
+ else if (typeof (refSource === null || refSource === void 0 ? void 0 : refSource.getUrls) !== "undefined") {
16
+ expect(refSource === null || refSource === void 0 ? void 0 : refSource.getUrls()).toEqual(layerSource === null || layerSource === void 0 ? void 0 : layerSource.getUrls());
17
+ }
18
+ else if (typeof (refSource === null || refSource === void 0 ? void 0 : refSource.getUrl) !== "undefined") {
19
+ expect(refSource === null || refSource === void 0 ? void 0 : refSource.getUrl()).toEqual(layerSource === null || layerSource === void 0 ? void 0 : layerSource.getUrl());
20
+ }
21
+ }
22
+ describe("applyContextDiffToMap", () => {
23
+ let context;
24
+ let diff;
25
+ let map;
26
+ let layersArray;
27
+ beforeEach(() => {
28
+ context = Object.assign(Object.assign({}, SAMPLE_CONTEXT), { layers: [SAMPLE_LAYER2, SAMPLE_LAYER1] });
29
+ map = createMapFromContext(context);
30
+ });
31
+ describe("no change", () => {
32
+ beforeEach(() => {
33
+ diff = {
34
+ layersAdded: [],
35
+ layersChanged: [],
36
+ layersRemoved: [],
37
+ layersReordered: [],
38
+ viewChanges: {},
39
+ };
40
+ applyContextDiffToMap(map, diff);
41
+ layersArray = map.getLayers().getArray();
42
+ });
43
+ it("does not affect the map", () => {
44
+ expect(layersArray.length).toEqual(2);
45
+ assertEqualsToModel(layersArray[0], SAMPLE_LAYER2);
46
+ assertEqualsToModel(layersArray[1], SAMPLE_LAYER1);
47
+ });
48
+ });
49
+ describe("layers added", () => {
50
+ beforeEach(() => {
51
+ diff = {
52
+ layersAdded: [
53
+ {
54
+ layer: SAMPLE_LAYER3,
55
+ position: 0,
56
+ },
57
+ {
58
+ layer: SAMPLE_LAYER4,
59
+ position: 2,
60
+ },
61
+ ],
62
+ layersChanged: [],
63
+ layersRemoved: [],
64
+ layersReordered: [],
65
+ viewChanges: {},
66
+ };
67
+ applyContextDiffToMap(map, diff);
68
+ layersArray = map.getLayers().getArray();
69
+ });
70
+ it("adds the layers to the map", () => {
71
+ expect(layersArray.length).toEqual(4);
72
+ assertEqualsToModel(layersArray[0], SAMPLE_LAYER3);
73
+ assertEqualsToModel(layersArray[1], SAMPLE_LAYER2);
74
+ assertEqualsToModel(layersArray[2], SAMPLE_LAYER4);
75
+ assertEqualsToModel(layersArray[3], SAMPLE_LAYER1);
76
+ });
77
+ });
78
+ describe("layers removed", () => {
79
+ beforeEach(() => {
80
+ diff = {
81
+ layersAdded: [],
82
+ layersChanged: [],
83
+ layersRemoved: [
84
+ {
85
+ layer: SAMPLE_LAYER2,
86
+ position: 0,
87
+ },
88
+ {
89
+ layer: SAMPLE_LAYER1,
90
+ position: 1,
91
+ },
92
+ ],
93
+ layersReordered: [],
94
+ viewChanges: {},
95
+ };
96
+ applyContextDiffToMap(map, diff);
97
+ });
98
+ it("deletes the layers", () => {
99
+ expect(map.getLayers().getLength()).toEqual(0);
100
+ });
101
+ });
102
+ describe("layers changed", () => {
103
+ beforeEach(() => {
104
+ diff = {
105
+ layersAdded: [],
106
+ layersChanged: [
107
+ {
108
+ layer: Object.assign(Object.assign({}, SAMPLE_LAYER2), { url: "http://changed/" }),
109
+ position: 0,
110
+ },
111
+ {
112
+ layer: Object.assign(Object.assign({}, SAMPLE_LAYER1), { url: "http://changed/", extras: {
113
+ changed: true,
114
+ } }),
115
+ position: 1,
116
+ },
117
+ ],
118
+ layersRemoved: [],
119
+ layersReordered: [],
120
+ viewChanges: {},
121
+ };
122
+ applyContextDiffToMap(map, diff);
123
+ layersArray = map.getLayers().getArray();
124
+ });
125
+ it("modifies the layers accordingly", () => {
126
+ expect(layersArray.length).toEqual(2);
127
+ assertEqualsToModel(layersArray[0], diff.layersChanged[0].layer);
128
+ assertEqualsToModel(layersArray[1], diff.layersChanged[1].layer);
129
+ });
130
+ });
131
+ describe("reordering", () => {
132
+ describe("three layers reordered", () => {
133
+ beforeEach(() => {
134
+ context = Object.assign(Object.assign({}, SAMPLE_CONTEXT), { layers: [SAMPLE_LAYER1, SAMPLE_LAYER2, SAMPLE_LAYER3] });
135
+ map = createMapFromContext(context);
136
+ diff = {
137
+ layersAdded: [],
138
+ layersChanged: [],
139
+ layersRemoved: [],
140
+ layersReordered: [
141
+ {
142
+ layer: SAMPLE_LAYER2,
143
+ newPosition: 0,
144
+ previousPosition: 1,
145
+ },
146
+ {
147
+ layer: SAMPLE_LAYER1,
148
+ newPosition: 1,
149
+ previousPosition: 0,
150
+ },
151
+ ],
152
+ viewChanges: {},
153
+ };
154
+ applyContextDiffToMap(map, diff);
155
+ layersArray = map.getLayers().getArray();
156
+ });
157
+ it("moves the layers accordingly", () => {
158
+ expect(layersArray.length).toEqual(3);
159
+ assertEqualsToModel(layersArray[0], SAMPLE_LAYER2);
160
+ assertEqualsToModel(layersArray[1], SAMPLE_LAYER1);
161
+ assertEqualsToModel(layersArray[2], SAMPLE_LAYER3);
162
+ });
163
+ });
164
+ describe("four layers reordered", () => {
165
+ beforeEach(() => {
166
+ context = Object.assign(Object.assign({}, SAMPLE_CONTEXT), { layers: [SAMPLE_LAYER1, SAMPLE_LAYER3, SAMPLE_LAYER4, SAMPLE_LAYER2] });
167
+ map = createMapFromContext(context);
168
+ diff = {
169
+ layersAdded: [],
170
+ layersChanged: [],
171
+ layersRemoved: [],
172
+ layersReordered: [
173
+ {
174
+ layer: SAMPLE_LAYER4,
175
+ newPosition: 0,
176
+ previousPosition: 2,
177
+ },
178
+ {
179
+ layer: SAMPLE_LAYER1,
180
+ newPosition: 2,
181
+ previousPosition: 0,
182
+ },
183
+ ],
184
+ viewChanges: {},
185
+ };
186
+ applyContextDiffToMap(map, diff);
187
+ layersArray = map.getLayers().getArray();
188
+ });
189
+ it("moves the layers accordingly", () => {
190
+ expect(layersArray.length).toEqual(4);
191
+ assertEqualsToModel(layersArray[0], SAMPLE_LAYER4);
192
+ assertEqualsToModel(layersArray[1], SAMPLE_LAYER3);
193
+ assertEqualsToModel(layersArray[2], SAMPLE_LAYER1);
194
+ assertEqualsToModel(layersArray[3], SAMPLE_LAYER2);
195
+ });
196
+ });
197
+ });
198
+ describe("combined changes", () => {
199
+ let changedLayer;
200
+ beforeEach(() => {
201
+ changedLayer = Object.assign(Object.assign({}, SAMPLE_LAYER3), { extras: { prop: true } });
202
+ context = Object.assign(Object.assign({}, context), { layers: [SAMPLE_LAYER1, SAMPLE_LAYER5, SAMPLE_LAYER3, SAMPLE_LAYER4] });
203
+ map = createMapFromContext(context);
204
+ diff = {
205
+ layersAdded: [
206
+ {
207
+ layer: SAMPLE_LAYER2,
208
+ position: 0,
209
+ },
210
+ ],
211
+ layersChanged: [
212
+ {
213
+ layer: changedLayer,
214
+ position: 1,
215
+ },
216
+ ],
217
+ layersRemoved: [
218
+ {
219
+ layer: SAMPLE_LAYER1,
220
+ position: 0,
221
+ },
222
+ {
223
+ layer: SAMPLE_LAYER4,
224
+ position: 3,
225
+ },
226
+ ],
227
+ layersReordered: [
228
+ {
229
+ layer: changedLayer,
230
+ newPosition: 1,
231
+ previousPosition: 2,
232
+ },
233
+ {
234
+ layer: SAMPLE_LAYER5,
235
+ newPosition: 2,
236
+ previousPosition: 1,
237
+ },
238
+ ],
239
+ viewChanges: {},
240
+ };
241
+ applyContextDiffToMap(map, diff);
242
+ layersArray = map.getLayers().getArray();
243
+ });
244
+ it("applies all changes", () => {
245
+ expect(layersArray.length).toEqual(3);
246
+ assertEqualsToModel(layersArray[0], SAMPLE_LAYER2);
247
+ assertEqualsToModel(layersArray[1], changedLayer);
248
+ assertEqualsToModel(layersArray[2], SAMPLE_LAYER5);
249
+ });
250
+ });
251
+ });
@@ -0,0 +1,19 @@
1
+ import { MapContext, MapContextLayer, MapContextView } from "@geospatial-sdk/core";
2
+ import Map from "ol/Map";
3
+ import View from "ol/View";
4
+ import Layer from "ol/layer/Layer";
5
+ export declare function createLayer(layerModel: MapContextLayer): Layer;
6
+ export declare function createView(viewModel: MapContextView, map: Map): View;
7
+ /**
8
+ * Create an OpenLayers map from a context; optionally specify a target (root element) for the map
9
+ * @param context
10
+ * @param target
11
+ */
12
+ export declare function createMapFromContext(context: MapContext, target?: string | HTMLElement): Map;
13
+ /**
14
+ * Resets an OpenLayers map from a context; existing content will be cleared
15
+ * @param map
16
+ * @param context
17
+ */
18
+ export declare function resetMapFromContext(map: Map, context: MapContext): Map;
19
+ //# sourceMappingURL=create-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-map.d.ts","sourceRoot":"","sources":["../../lib/map/create-map.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,eAAe,EACf,cAAc,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,GAAG,MAAM,QAAQ,CAAC;AACzB,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAgBnC,wBAAgB,WAAW,CAAC,UAAU,EAAE,eAAe,GAAG,KAAK,CAkF9D;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAmBpE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,UAAU,EACnB,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAC5B,GAAG,CAKL;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,GAAG,GAAG,CAKtE"}
@@ -0,0 +1,138 @@
1
+ import Map from "ol/Map";
2
+ import View from "ol/View";
3
+ import TileLayer from "ol/layer/Tile";
4
+ import XYZ from "ol/source/XYZ";
5
+ import TileWMS from "ol/source/TileWMS";
6
+ import VectorLayer from "ol/layer/Vector";
7
+ import VectorSource from "ol/source/Vector";
8
+ import GeoJSON from "ol/format/GeoJSON";
9
+ import { fromLonLat } from "ol/proj";
10
+ import { bbox as bboxStrategy } from "ol/loadingstrategy";
11
+ import { removeSearchParams } from "@geospatial-sdk/core";
12
+ import { defaultStyle } from "./styles";
13
+ const geosjonFormat = new GeoJSON();
14
+ export function createLayer(layerModel) {
15
+ const { type } = layerModel;
16
+ const style = defaultStyle;
17
+ switch (type) {
18
+ case "xyz":
19
+ return new TileLayer({
20
+ source: new XYZ({
21
+ url: layerModel.url,
22
+ }),
23
+ });
24
+ case "wms":
25
+ return new TileLayer({
26
+ source: new TileWMS({
27
+ url: removeSearchParams(layerModel.url, ["request", "service"]),
28
+ params: { LAYERS: layerModel.name },
29
+ gutter: 20,
30
+ }),
31
+ });
32
+ // TODO: implement when ogc-client can handle wmts
33
+ // case 'wmts':
34
+ // return new TileLayer({
35
+ // source: new WMTS(layerModel.options),
36
+ // })
37
+ case "wfs":
38
+ return new VectorLayer({
39
+ source: new VectorSource({
40
+ format: new GeoJSON(),
41
+ url: function (extent) {
42
+ const urlObj = new URL(removeSearchParams(layerModel.url, [
43
+ "service",
44
+ "version",
45
+ "request",
46
+ ]));
47
+ urlObj.searchParams.set("service", "WFS");
48
+ urlObj.searchParams.set("version", "1.1.0");
49
+ urlObj.searchParams.set("request", "GetFeature");
50
+ urlObj.searchParams.set("outputFormat", "application/json");
51
+ urlObj.searchParams.set("typename", layerModel.featureType);
52
+ urlObj.searchParams.set("srsname", "EPSG:3857");
53
+ urlObj.searchParams.set("bbox", `${extent.join(",")},EPSG:3857`);
54
+ return urlObj.toString();
55
+ },
56
+ strategy: bboxStrategy,
57
+ }),
58
+ style,
59
+ });
60
+ case "geojson": {
61
+ if (layerModel.url !== undefined) {
62
+ return new VectorLayer({
63
+ source: new VectorSource({
64
+ format: new GeoJSON(),
65
+ url: layerModel.url,
66
+ }),
67
+ style,
68
+ });
69
+ }
70
+ else {
71
+ let geojson = layerModel.data;
72
+ if (typeof geojson === "string") {
73
+ try {
74
+ geojson = JSON.parse(geojson);
75
+ }
76
+ catch (e) {
77
+ console.warn("A layer could not be created", layerModel, e);
78
+ geojson = { type: "FeatureCollection", features: [] };
79
+ }
80
+ }
81
+ const features = geosjonFormat.readFeatures(geojson, {
82
+ featureProjection: "EPSG:3857",
83
+ dataProjection: "EPSG:4326",
84
+ });
85
+ return new VectorLayer({
86
+ source: new VectorSource({
87
+ features,
88
+ }),
89
+ style,
90
+ });
91
+ }
92
+ }
93
+ default:
94
+ throw new Error(`Unrecognized layer type: ${layerModel.type}`);
95
+ }
96
+ }
97
+ export function createView(viewModel, map) {
98
+ const { center: centerInViewProj, zoom, maxZoom, maxExtent } = viewModel;
99
+ const center = centerInViewProj
100
+ ? fromLonLat(centerInViewProj, "EPSG:3857")
101
+ : [0, 0];
102
+ const view = new View({
103
+ center,
104
+ zoom: zoom !== null && zoom !== void 0 ? zoom : 0,
105
+ maxZoom,
106
+ extent: maxExtent,
107
+ multiWorld: false,
108
+ constrainResolution: true,
109
+ });
110
+ if (viewModel.extent) {
111
+ view.fit(viewModel.extent, {
112
+ size: map.getSize(),
113
+ });
114
+ }
115
+ return view;
116
+ }
117
+ /**
118
+ * Create an OpenLayers map from a context; optionally specify a target (root element) for the map
119
+ * @param context
120
+ * @param target
121
+ */
122
+ export function createMapFromContext(context, target) {
123
+ const map = new Map({
124
+ target,
125
+ });
126
+ return resetMapFromContext(map, context);
127
+ }
128
+ /**
129
+ * Resets an OpenLayers map from a context; existing content will be cleared
130
+ * @param map
131
+ * @param context
132
+ */
133
+ export function resetMapFromContext(map, context) {
134
+ map.setView(createView(context.view, map));
135
+ map.getLayers().clear();
136
+ context.layers.forEach((layer) => map.addLayer(createLayer(layer)));
137
+ return map;
138
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=create-map.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-map.test.d.ts","sourceRoot":"","sources":["../../lib/map/create-map.test.ts"],"names":[],"mappings":""}