@geospatial-sdk/openlayers 0.0.5-dev.50 → 0.0.5-dev.52

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.
Files changed (37) hide show
  1. package/dist/map/constants.d.ts +2 -0
  2. package/dist/map/constants.d.ts.map +1 -0
  3. package/dist/map/constants.js +1 -0
  4. package/dist/map/create-map.d.ts.map +1 -1
  5. package/dist/map/create-map.js +3 -2
  6. package/dist/map/feature-hover.d.ts +7 -0
  7. package/dist/map/feature-hover.d.ts.map +1 -0
  8. package/dist/map/feature-hover.js +82 -0
  9. package/dist/map/get-features.d.ts +13 -0
  10. package/dist/map/get-features.d.ts.map +1 -0
  11. package/dist/map/get-features.js +77 -0
  12. package/dist/map/index.d.ts +0 -1
  13. package/dist/map/index.d.ts.map +1 -1
  14. package/dist/map/index.js +0 -1
  15. package/dist/map/layer-update.d.ts.map +1 -1
  16. package/dist/map/layer-update.js +10 -0
  17. package/dist/map/register-events.d.ts +0 -8
  18. package/dist/map/register-events.d.ts.map +1 -1
  19. package/dist/map/register-events.js +4 -58
  20. package/lib/map/constants.ts +1 -0
  21. package/lib/map/create-map.test.ts +16 -13
  22. package/lib/map/create-map.ts +3 -1
  23. package/lib/map/feature-hover.ts +113 -0
  24. package/lib/map/get-features.test.ts +120 -0
  25. package/lib/map/get-features.ts +122 -0
  26. package/lib/map/handle-errors.test.ts +4 -5
  27. package/lib/map/index.ts +0 -1
  28. package/lib/map/layer-update.test.ts +27 -1
  29. package/lib/map/layer-update.ts +27 -3
  30. package/lib/map/register-events.test.ts +74 -122
  31. package/lib/map/register-events.ts +5 -98
  32. package/package.json +5 -5
  33. package/dist/map/styles.d.ts +0 -16
  34. package/dist/map/styles.d.ts.map +0 -1
  35. package/dist/map/styles.js +0 -77
  36. package/lib/map/styles.test.ts +0 -217
  37. package/lib/map/styles.ts +0 -103
@@ -3,111 +3,27 @@ import {
3
3
  FeaturesClickEventType,
4
4
  FeaturesHoverEventType,
5
5
  MapClickEventType,
6
- MapExtentChangeEventType,
7
6
  MapEventsByType,
7
+ MapExtentChangeEventType,
8
8
  SourceLoadErrorType,
9
9
  } from "@geospatial-sdk/core";
10
10
  import { toLonLat, transformExtent } from "ol/proj.js";
11
- import GeoJSON from "ol/format/GeoJSON.js";
12
- import OlFeature from "ol/Feature.js";
13
11
  import BaseEvent from "ol/events/Event.js";
14
- import { MapBrowserEvent } from "ol";
15
- import { Coordinate } from "ol/coordinate.js";
16
- import TileWMS from "ol/source/TileWMS.js";
17
- import ImageWMS from "ol/source/ImageWMS.js";
18
12
  import Layer from "ol/layer/Layer.js";
19
- import { Pixel } from "ol/pixel.js";
20
- import type { Feature, FeatureCollection } from "geojson";
21
- import throttle from "lodash.throttle";
22
13
  import { BaseLayerObjectEventTypes } from "ol/layer/Base.js";
23
14
  import { equals } from "ol/extent.js";
24
-
25
- const GEOJSON = new GeoJSON();
26
-
27
- export function getFeaturesFromVectorSources(
28
- olMap: Map,
29
- pixel: Pixel,
30
- ): Feature[] {
31
- const olFeatures = olMap.getFeaturesAtPixel(pixel);
32
- const { features } = GEOJSON.writeFeaturesObject(olFeatures as OlFeature[]);
33
- if (!features) {
34
- return [];
35
- }
36
- return features;
37
- }
38
-
39
- export function getGFIUrl(
40
- source: TileWMS | ImageWMS,
41
- map: Map,
42
- coordinate: Coordinate,
43
- ): string | null {
44
- const view = map.getView();
45
- const projection = view.getProjection();
46
- const resolution = view.getResolution() as number;
47
- const params = {
48
- ...source.getParams(),
49
- INFO_FORMAT: "application/json",
50
- };
51
- return (
52
- source.getFeatureInfoUrl(coordinate, resolution, projection, params) ?? null
53
- );
54
- }
55
-
56
- export function getFeaturesFromWmsSources(
57
- olMap: Map,
58
- coordinate: Coordinate,
59
- ): Promise<Feature[]> {
60
- const wmsSources: (ImageWMS | TileWMS)[] = olMap
61
- .getLayers()
62
- .getArray()
63
- .filter(
64
- (layer): layer is Layer<ImageWMS | TileWMS> =>
65
- layer instanceof Layer &&
66
- (layer.getSource() instanceof TileWMS ||
67
- layer.getSource() instanceof ImageWMS),
68
- )
69
- .map((layer) => layer.getSource()!);
70
-
71
- if (!wmsSources.length) {
72
- return Promise.resolve([]);
73
- }
74
-
75
- const gfiUrls = wmsSources.reduce((urls, source) => {
76
- const gfiUrl = getGFIUrl(source, olMap, coordinate);
77
- return gfiUrl ? [...urls, gfiUrl] : urls;
78
- }, [] as string[]);
79
- return Promise.all(
80
- gfiUrls.map((url) =>
81
- fetch(url)
82
- .then((response) => response.json())
83
- .then((collection: FeatureCollection) => collection.features),
84
- ),
85
- ).then((features) => features.flat());
86
- }
87
-
88
- const getFeaturesFromWmsSourcesThrottled = throttle(
89
- getFeaturesFromWmsSources,
90
- 250,
91
- );
92
-
93
- async function readFeaturesAtPixel(
94
- map: Map,
95
- event: MapBrowserEvent<PointerEvent>,
96
- ) {
97
- return [
98
- ...getFeaturesFromVectorSources(map, event.pixel),
99
- ...(await getFeaturesFromWmsSourcesThrottled(map, event.coordinate)),
100
- ];
101
- }
15
+ import { readFeaturesAtPixel } from "./get-features.js";
102
16
 
103
17
  function registerFeatureClickEvent(map: Map) {
104
18
  if (map.get(FeaturesClickEventType)) return;
105
19
 
106
20
  map.on("click", async (event: any) => {
107
- const features = await readFeaturesAtPixel(map, event);
21
+ const featuresByLayer = await readFeaturesAtPixel(map, event);
22
+ const features = Array.from(featuresByLayer.values()).flat();
108
23
  map.dispatchEvent({
109
24
  type: FeaturesClickEventType,
110
25
  features,
26
+ featuresByLayer,
111
27
  } as unknown as BaseEvent);
112
28
  });
113
29
 
@@ -116,15 +32,6 @@ function registerFeatureClickEvent(map: Map) {
116
32
 
117
33
  function registerFeatureHoverEvent(map: Map) {
118
34
  if (map.get(FeaturesHoverEventType)) return;
119
-
120
- map.on("pointermove", async (event: any) => {
121
- const features = await readFeaturesAtPixel(map, event);
122
- map.dispatchEvent({
123
- type: FeaturesHoverEventType,
124
- features,
125
- } as unknown as BaseEvent);
126
- });
127
-
128
35
  map.set(FeaturesHoverEventType, true);
129
36
  }
130
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geospatial-sdk/openlayers",
3
- "version": "0.0.5-dev.50+c8ee5e3",
3
+ "version": "0.0.5-dev.52+73ea489",
4
4
  "description": "OpenLayers-related utilities",
5
5
  "keywords": [
6
6
  "ol",
@@ -30,17 +30,17 @@
30
30
  "devDependencies": {
31
31
  "@types/chroma-js": "^2.4.3",
32
32
  "@types/lodash.throttle": "^4.1.9",
33
- "ol": "^8.2.0",
33
+ "ol": "^10.7.0",
34
34
  "ol-mapbox-style": "12.4.0"
35
35
  },
36
36
  "peerDependencies": {
37
- "ol": ">6.x"
37
+ "ol": ">9.x"
38
38
  },
39
39
  "dependencies": {
40
- "@geospatial-sdk/core": "^0.0.5-dev.50+c8ee5e3",
40
+ "@geospatial-sdk/core": "^0.0.5-dev.52+73ea489",
41
41
  "chroma-js": "^2.4.2",
42
42
  "lodash.throttle": "^4.1.1",
43
43
  "ol-mapbox-style": "12.4.0"
44
44
  },
45
- "gitHead": "c8ee5e32059a06e056a5723987baf5e2574bf784"
45
+ "gitHead": "73ea4890e493aae5379e23af6b7679bab253db92"
46
46
  }
@@ -1,16 +0,0 @@
1
- import { Style } from "ol/style.js";
2
- import { StyleFunction } from "ol/style/Style.js";
3
- export interface CreateStyleOptions {
4
- color: string;
5
- isFocused?: boolean;
6
- }
7
- export interface StyleByGeometryType {
8
- line: Style | Style[];
9
- polygon: Style | Style[];
10
- point: Style | Style[];
11
- }
12
- export declare function createGeometryStyles(options: CreateStyleOptions): StyleByGeometryType;
13
- export declare function createStyleFunction(styleByGeometryType: StyleByGeometryType): StyleFunction;
14
- export declare const defaultStyle: StyleFunction;
15
- export declare const defaultHighlightStyle: StyleFunction;
16
- //# sourceMappingURL=styles.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../lib/map/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIlD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,KAAK,GAAG,KAAK,EAAE,CAAC;IACtB,OAAO,EAAE,KAAK,GAAG,KAAK,EAAE,CAAC;IACzB,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,GAC1B,mBAAmB,CA4CrB;AAED,wBAAgB,mBAAmB,CACjC,mBAAmB,EAAE,mBAAmB,GACvC,aAAa,CAmBf;AAMD,eAAO,MAAM,YAAY,eAIxB,CAAC;AAEF,eAAO,MAAM,qBAAqB,eAKjC,CAAC"}
@@ -1,77 +0,0 @@
1
- import { Circle, Fill, Stroke, Style } from "ol/style.js";
2
- import chroma from "chroma-js";
3
- export function createGeometryStyles(options) {
4
- const { color, isFocused } = options;
5
- const zIndex = isFocused ? 10 : undefined;
6
- return {
7
- polygon: new Style({
8
- fill: new Fill({
9
- color: computeTransparentFillColor(color),
10
- }),
11
- stroke: new Stroke({
12
- color: "white",
13
- width: 2,
14
- }),
15
- zIndex,
16
- }),
17
- point: new Style({
18
- image: new Circle({
19
- fill: new Fill({
20
- color,
21
- }),
22
- stroke: new Stroke({
23
- color: "white",
24
- width: isFocused ? 3 : 2,
25
- }),
26
- radius: isFocused ? 8 : 7,
27
- }),
28
- zIndex,
29
- }),
30
- line: [
31
- new Style({
32
- stroke: new Stroke({
33
- color: "white",
34
- width: isFocused ? 8 : 6,
35
- }),
36
- zIndex,
37
- }),
38
- new Style({
39
- stroke: new Stroke({
40
- color,
41
- width: isFocused ? 3 : 2,
42
- }),
43
- zIndex,
44
- }),
45
- ],
46
- };
47
- }
48
- export function createStyleFunction(styleByGeometryType) {
49
- return (feature) => {
50
- const geometryType = feature?.getGeometry()?.getType();
51
- switch (geometryType) {
52
- case "LinearRing":
53
- case "LineString":
54
- case "MultiLineString":
55
- return styleByGeometryType.line;
56
- case "Point":
57
- case "MultiPoint":
58
- return styleByGeometryType.point;
59
- case "Circle":
60
- case "Polygon":
61
- case "MultiPolygon":
62
- return styleByGeometryType.polygon;
63
- default:
64
- return styleByGeometryType.point;
65
- }
66
- };
67
- }
68
- function computeTransparentFillColor(color, alpha = 0.25) {
69
- return chroma(color).alpha(alpha).css();
70
- }
71
- export const defaultStyle = createStyleFunction(createGeometryStyles({
72
- color: "blue",
73
- }));
74
- export const defaultHighlightStyle = createStyleFunction(createGeometryStyles({
75
- color: "red",
76
- isFocused: true,
77
- }));
@@ -1,217 +0,0 @@
1
- import chroma from "chroma-js";
2
- import Style, { StyleFunction } from "ol/style/Style.js";
3
- import Feature from "ol/Feature.js";
4
- import { LineString, Point, Polygon } from "ol/geom.js";
5
- import {
6
- createGeometryStyles,
7
- createStyleFunction,
8
- defaultHighlightStyle,
9
- defaultStyle,
10
- StyleByGeometryType,
11
- } from "./styles.js";
12
- import CircleStyle from "ol/style/Circle.js";
13
-
14
- describe("MapStyleService", () => {
15
- describe("#createGeometryStyles", () => {
16
- let styles: StyleByGeometryType;
17
- let pointStyle: Style;
18
- let lineStyle: Style[];
19
- let polygonStyle: Style;
20
-
21
- describe("unfocused style", () => {
22
- beforeEach(() => {
23
- const options = {
24
- color: "orange",
25
- };
26
- styles = createGeometryStyles(options);
27
- pointStyle = styles.point as Style;
28
- lineStyle = styles.line as Style[];
29
- polygonStyle = styles.polygon as Style;
30
- });
31
- describe("point style", () => {
32
- it("has 1 style", () => {
33
- expect(pointStyle).toBeInstanceOf(Style);
34
- });
35
- it("has correct radius", () => {
36
- expect((pointStyle.getImage() as CircleStyle)?.getRadius()).toBe(7);
37
- });
38
- it("has correct fill color", () => {
39
- expect(
40
- (pointStyle.getImage() as CircleStyle)?.getFill()?.getColor(),
41
- ).toBe("orange");
42
- });
43
- it("has correct stroke color and width", () => {
44
- expect(
45
- (pointStyle.getImage() as CircleStyle)?.getStroke()?.getColor(),
46
- ).toBe("white");
47
- expect(
48
- (pointStyle.getImage() as CircleStyle)?.getStroke()?.getWidth(),
49
- ).toBe(2);
50
- });
51
- });
52
- describe("polygon style", () => {
53
- it("has 1 style", () => {
54
- expect(polygonStyle).toBeInstanceOf(Style);
55
- });
56
- it("has correct fill color", () => {
57
- expect(polygonStyle.getFill()?.getColor()).toBe(
58
- chroma("orange").alpha(0.25).css(),
59
- );
60
- });
61
- it("has correct stroke color and width", () => {
62
- expect(polygonStyle.getStroke()?.getColor()).toBe("white");
63
- expect(polygonStyle.getStroke()?.getWidth()).toBe(2);
64
- });
65
- });
66
- describe("line style", () => {
67
- it("has 2 styles", () => {
68
- expect(lineStyle).toEqual([expect.any(Style), expect.any(Style)]);
69
- });
70
- it("has correct color (back stroke)", () => {
71
- expect(lineStyle[0].getStroke()?.getColor()).toBe("white");
72
- });
73
- it("has correct width (back stroke)", () => {
74
- expect(lineStyle[0].getStroke()?.getWidth()).toBe(6);
75
- });
76
- it("has correct color (front stroke)", () => {
77
- expect(lineStyle[1].getStroke()?.getColor()).toBe("orange");
78
- });
79
- it("has correct width (front stroke)", () => {
80
- expect(lineStyle[1].getStroke()?.getWidth()).toBe(2);
81
- });
82
- });
83
- });
84
- describe("focused style", () => {
85
- beforeEach(() => {
86
- const options = {
87
- color: "pink",
88
- isFocused: true,
89
- };
90
- styles = createGeometryStyles(options);
91
- pointStyle = styles.point as Style;
92
- lineStyle = styles.line as Style[];
93
- polygonStyle = styles.polygon as Style;
94
- });
95
- describe("point style", () => {
96
- it("has correct radius", () => {
97
- expect((pointStyle.getImage() as CircleStyle)?.getRadius()).toBe(8);
98
- });
99
- it("has correct fill color", () => {
100
- expect(
101
- (pointStyle.getImage() as CircleStyle)?.getFill()?.getColor(),
102
- ).toBe("pink");
103
- });
104
- it("has correct stroke color and width", () => {
105
- expect(
106
- (pointStyle.getImage() as CircleStyle)?.getStroke()?.getColor(),
107
- ).toBe("white");
108
- expect(
109
- (pointStyle.getImage() as CircleStyle)?.getStroke()?.getWidth(),
110
- ).toBe(3);
111
- });
112
- });
113
- describe("polygon style", () => {
114
- it("has correct fill color", () => {
115
- expect(polygonStyle.getFill()?.getColor()).toBe(
116
- chroma("pink").alpha(0.25).css(),
117
- );
118
- });
119
- it("has correct stroke color and width", () => {
120
- expect(polygonStyle.getStroke()?.getColor()).toBe("white");
121
- expect(polygonStyle.getStroke()?.getWidth()).toBe(2);
122
- });
123
- });
124
- describe("line style", () => {
125
- it("has correct color (back stroke)", () => {
126
- expect(lineStyle[0].getStroke()?.getColor()).toBe("white");
127
- });
128
- it("has correct width (back stroke)", () => {
129
- expect(lineStyle[0].getStroke()?.getWidth()).toBe(8);
130
- });
131
- it("has correct color (front stroke)", () => {
132
- expect(lineStyle[1].getStroke()?.getColor()).toBe("pink");
133
- });
134
- it("has correct width (front stroke)", () => {
135
- expect(lineStyle[1].getStroke()?.getWidth()).toBe(3);
136
- });
137
- });
138
- });
139
- });
140
-
141
- describe("#createStyleFunction", () => {
142
- let styleFn: StyleFunction;
143
- let feature: Feature;
144
- it("returns a function", () => {
145
- styleFn = createStyleFunction(
146
- createGeometryStyles({
147
- color: "blue",
148
- }),
149
- );
150
- feature = new Feature();
151
- });
152
- describe("with linestring geometry", () => {
153
- beforeEach(() => {
154
- feature.setGeometry(new LineString([]));
155
- });
156
- it("resolves to a double style with stroke", () => {
157
- const style = styleFn(feature, 1) as Style[];
158
- expect(style).toEqual([expect.any(Style), expect.any(Style)]);
159
- expect(style[0].getStroke()).toBeTruthy();
160
- expect(style[0].getFill()).toBeFalsy();
161
- expect(style[0].getImage()).toBeFalsy();
162
- });
163
- });
164
- describe("with point geometry", () => {
165
- beforeEach(() => {
166
- feature.setGeometry(new Point([]));
167
- });
168
- it("resolves to a style with image", () => {
169
- const style = styleFn(feature, 1) as Style;
170
- expect(style.getImage()).toBeTruthy();
171
- expect(style.getFill()).toBeFalsy();
172
- expect(style.getStroke()).toBeFalsy();
173
- });
174
- });
175
- describe("with polygon geometry", () => {
176
- beforeEach(() => {
177
- feature.setGeometry(new Polygon([]));
178
- });
179
- it("resolves to a style with fill and stroke", () => {
180
- const style = styleFn(feature, 1) as Style;
181
- expect(style.getFill()).toBeTruthy();
182
- expect(style.getStroke()).toBeTruthy();
183
- expect(style.getImage()).toBeFalsy();
184
- });
185
- });
186
- });
187
-
188
- describe("built-in styles", () => {
189
- let pointFeature: Feature;
190
- let pointStyle: Style;
191
- beforeEach(() => {
192
- pointFeature = new Feature(new Point([]));
193
- });
194
- describe("default style", () => {
195
- beforeEach(() => {
196
- const styleFn = defaultStyle;
197
- pointStyle = styleFn(pointFeature, 1) as Style;
198
- });
199
- it("uses the primary theme color", () => {
200
- expect(
201
- (pointStyle.getImage() as CircleStyle)?.getFill()?.getColor(),
202
- ).toEqual("blue");
203
- });
204
- });
205
- describe("default highlight style", () => {
206
- beforeEach(() => {
207
- const styleFn = defaultHighlightStyle;
208
- pointStyle = styleFn(pointFeature, 1) as Style;
209
- });
210
- it("uses the secondary theme color", () => {
211
- expect(
212
- (pointStyle.getImage() as CircleStyle)?.getFill()?.getColor(),
213
- ).toEqual("red");
214
- });
215
- });
216
- });
217
- });
package/lib/map/styles.ts DELETED
@@ -1,103 +0,0 @@
1
- import { Circle, Fill, Stroke, Style } from "ol/style.js";
2
- import { StyleFunction } from "ol/style/Style.js";
3
- import { FeatureLike } from "ol/Feature.js";
4
- import chroma from "chroma-js";
5
-
6
- export interface CreateStyleOptions {
7
- color: string;
8
- isFocused?: boolean;
9
- }
10
-
11
- export interface StyleByGeometryType {
12
- line: Style | Style[];
13
- polygon: Style | Style[];
14
- point: Style | Style[];
15
- }
16
-
17
- export function createGeometryStyles(
18
- options: CreateStyleOptions,
19
- ): StyleByGeometryType {
20
- const { color, isFocused } = options;
21
- const zIndex = isFocused ? 10 : undefined;
22
- return {
23
- polygon: new Style({
24
- fill: new Fill({
25
- color: computeTransparentFillColor(color),
26
- }),
27
- stroke: new Stroke({
28
- color: "white",
29
- width: 2,
30
- }),
31
- zIndex,
32
- }),
33
- point: new Style({
34
- image: new Circle({
35
- fill: new Fill({
36
- color,
37
- }),
38
- stroke: new Stroke({
39
- color: "white",
40
- width: isFocused ? 3 : 2,
41
- }),
42
- radius: isFocused ? 8 : 7,
43
- }),
44
- zIndex,
45
- }),
46
- line: [
47
- new Style({
48
- stroke: new Stroke({
49
- color: "white",
50
- width: isFocused ? 8 : 6,
51
- }),
52
- zIndex,
53
- }),
54
- new Style({
55
- stroke: new Stroke({
56
- color,
57
- width: isFocused ? 3 : 2,
58
- }),
59
- zIndex,
60
- }),
61
- ],
62
- };
63
- }
64
-
65
- export function createStyleFunction(
66
- styleByGeometryType: StyleByGeometryType,
67
- ): StyleFunction {
68
- return (feature: FeatureLike): Style | Style[] => {
69
- const geometryType = feature?.getGeometry()?.getType();
70
- switch (geometryType) {
71
- case "LinearRing":
72
- case "LineString":
73
- case "MultiLineString":
74
- return styleByGeometryType.line;
75
- case "Point":
76
- case "MultiPoint":
77
- return styleByGeometryType.point;
78
- case "Circle":
79
- case "Polygon":
80
- case "MultiPolygon":
81
- return styleByGeometryType.polygon;
82
- default:
83
- return styleByGeometryType.point;
84
- }
85
- };
86
- }
87
-
88
- function computeTransparentFillColor(color: string, alpha = 0.25): string {
89
- return chroma(color).alpha(alpha).css();
90
- }
91
-
92
- export const defaultStyle = createStyleFunction(
93
- createGeometryStyles({
94
- color: "blue",
95
- }),
96
- );
97
-
98
- export const defaultHighlightStyle = createStyleFunction(
99
- createGeometryStyles({
100
- color: "red",
101
- isFocused: true,
102
- }),
103
- );