@geospatial-sdk/maplibre 0.0.5-dev.41
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/LICENSE +28 -0
- package/README.md +11 -0
- package/dist/helpers/map.helpers.d.ts +21 -0
- package/dist/helpers/map.helpers.d.ts.map +1 -0
- package/dist/helpers/map.helpers.js +65 -0
- package/dist/helpers/style.helpers.d.ts +4 -0
- package/dist/helpers/style.helpers.d.ts.map +1 -0
- package/dist/helpers/style.helpers.js +54 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/map/apply-context-diff.d.ts +9 -0
- package/dist/map/apply-context-diff.d.ts.map +1 -0
- package/dist/map/apply-context-diff.js +71 -0
- package/dist/map/create-map.d.ts +17 -0
- package/dist/map/create-map.d.ts.map +1 -0
- package/dist/map/create-map.js +144 -0
- package/dist/map/index.d.ts +3 -0
- package/dist/map/index.d.ts.map +1 -0
- package/dist/map/index.js +2 -0
- package/dist/maplibre.models.d.ts +13 -0
- package/dist/maplibre.models.d.ts.map +1 -0
- package/dist/maplibre.models.js +1 -0
- package/lib/helpers/map.helpers.ts +101 -0
- package/lib/helpers/style.helpers.test.ts +160 -0
- package/lib/helpers/style.helpers.ts +68 -0
- package/lib/index.ts +2 -0
- package/lib/map/apply-context-diff.test.ts +152 -0
- package/lib/map/apply-context-diff.ts +89 -0
- package/lib/map/create-map.test.ts +287 -0
- package/lib/map/create-map.ts +173 -0
- package/lib/map/index.ts +2 -0
- package/lib/maplibre.models.ts +31 -0
- package/package.json +39 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { contextStyleToMaplibreLayers } from "./style.helpers";
|
|
3
|
+
|
|
4
|
+
const defautlMaplibreFill = {
|
|
5
|
+
type: "fill",
|
|
6
|
+
paint: {
|
|
7
|
+
"fill-color": "rgba(255,255,255,0.4)",
|
|
8
|
+
},
|
|
9
|
+
filter: ["==", "$type", "Polygon"],
|
|
10
|
+
};
|
|
11
|
+
const defaultMaplibreLine = {
|
|
12
|
+
type: "line",
|
|
13
|
+
paint: {
|
|
14
|
+
"line-color": "#3399CC",
|
|
15
|
+
"line-width": 1.25,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
const defaultMaplibreCircle = {
|
|
19
|
+
type: "circle",
|
|
20
|
+
filter: ["==", "$type", "Point"],
|
|
21
|
+
paint: {
|
|
22
|
+
"circle-color": "rgba(255,255,255,0.4)",
|
|
23
|
+
"circle-radius": 5,
|
|
24
|
+
"circle-stroke-color": "#3399CC",
|
|
25
|
+
"circle-stroke-width": 1.25,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const defaultMaplibreStyle = [
|
|
29
|
+
defautlMaplibreFill,
|
|
30
|
+
defaultMaplibreLine,
|
|
31
|
+
defaultMaplibreCircle,
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
describe("createPaint", () => {
|
|
35
|
+
it("return default layers when empty", () => {
|
|
36
|
+
expect(contextStyleToMaplibreLayers({} as any)).toEqual(
|
|
37
|
+
defaultMaplibreStyle,
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
describe("Fill layer", () => {
|
|
41
|
+
it("generates a fill layer", () => {
|
|
42
|
+
const result = contextStyleToMaplibreLayers({
|
|
43
|
+
"fill-color": "red",
|
|
44
|
+
} as any);
|
|
45
|
+
expect(result).toEqual([
|
|
46
|
+
{
|
|
47
|
+
filter: ["==", "$type", "Polygon"],
|
|
48
|
+
type: "fill",
|
|
49
|
+
paint: {
|
|
50
|
+
"fill-color": "red",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
defaultMaplibreLine,
|
|
54
|
+
defaultMaplibreCircle,
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("Line layer", () => {
|
|
60
|
+
it("generates a line layer if stroke-color is defined", () => {
|
|
61
|
+
const result = contextStyleToMaplibreLayers({
|
|
62
|
+
"stroke-color": "rgba(30, 67, 246, 0.5)",
|
|
63
|
+
"stroke-width": 3,
|
|
64
|
+
} as any);
|
|
65
|
+
expect(result).toEqual([
|
|
66
|
+
defautlMaplibreFill,
|
|
67
|
+
{
|
|
68
|
+
type: "line",
|
|
69
|
+
paint: {
|
|
70
|
+
"line-color": "rgba(30, 67, 246, 0.5)",
|
|
71
|
+
"line-width": 3,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
defaultMaplibreCircle,
|
|
75
|
+
]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("Line stroke width", () => {
|
|
79
|
+
const result = contextStyleToMaplibreLayers({ "stroke-width": 3 } as any);
|
|
80
|
+
expect(result[1]).toEqual({
|
|
81
|
+
type: "line",
|
|
82
|
+
paint: {
|
|
83
|
+
"line-color": "#3399CC",
|
|
84
|
+
"line-width": 3,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("Line dash array", () => {
|
|
90
|
+
const result = contextStyleToMaplibreLayers({
|
|
91
|
+
"stroke-color": "red",
|
|
92
|
+
"stroke-line-dash": [2, 4],
|
|
93
|
+
} as any);
|
|
94
|
+
expect(result[1]).toEqual({
|
|
95
|
+
type: "line",
|
|
96
|
+
paint: {
|
|
97
|
+
"line-color": "red",
|
|
98
|
+
"line-dasharray": [2, 4],
|
|
99
|
+
"line-width": 1.25,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe("Circle layer", () => {
|
|
106
|
+
it("generates a circle layer with fill and stroke colors and stroke width", () => {
|
|
107
|
+
const style = {
|
|
108
|
+
"circle-radius": 10,
|
|
109
|
+
"circle-fill-color": "red",
|
|
110
|
+
"circle-stroke-color": "blue",
|
|
111
|
+
"circle-stroke-width": 2,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const result = contextStyleToMaplibreLayers(style as any);
|
|
115
|
+
|
|
116
|
+
expect(result).toEqual([
|
|
117
|
+
defautlMaplibreFill,
|
|
118
|
+
defaultMaplibreLine,
|
|
119
|
+
{
|
|
120
|
+
type: "circle",
|
|
121
|
+
filter: ["==", "$type", "Point"],
|
|
122
|
+
paint: {
|
|
123
|
+
"circle-radius": 10,
|
|
124
|
+
"circle-color": "red",
|
|
125
|
+
"circle-stroke-color": "blue",
|
|
126
|
+
"circle-stroke-width": 2,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("generates a circle layer with only radius if no colors are provided", () => {
|
|
133
|
+
const style = {
|
|
134
|
+
"circle-radius": 5,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const result = contextStyleToMaplibreLayers(style as any);
|
|
138
|
+
|
|
139
|
+
expect(result[2].paint).toEqual({
|
|
140
|
+
"circle-color": "rgba(255,255,255,0.4)",
|
|
141
|
+
"circle-radius": 5,
|
|
142
|
+
"circle-stroke-color": "#3399CC",
|
|
143
|
+
"circle-stroke-width": 1.25,
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("respects colors and opacity", () => {
|
|
148
|
+
const style = {
|
|
149
|
+
"circle-radius": 8,
|
|
150
|
+
"circle-fill-color": "rgba(255,0,0,0.3)",
|
|
151
|
+
"circle-stroke-color": "rgba(0,0,255,0.6)",
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const result = contextStyleToMaplibreLayers(style as any);
|
|
155
|
+
|
|
156
|
+
expect(result[2].paint["circle-color"]).toBe("rgba(255,0,0,0.3)"); // mocked
|
|
157
|
+
expect(result[2].paint["circle-stroke-color"]).toBe("rgba(0,0,255,0.6)"); // mocked
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { VectorStyle } from "@geospatial-sdk/core/dist/model/style";
|
|
2
|
+
import { LayerSpecification } from "maplibre-gl";
|
|
3
|
+
import { FlatFill, FlatStyle, Rule } from "ol/style/flat";
|
|
4
|
+
|
|
5
|
+
const defaultOltStyle: FlatStyle = {
|
|
6
|
+
"fill-color": "rgba(255,255,255,0.4)",
|
|
7
|
+
"stroke-color": "#3399CC",
|
|
8
|
+
"stroke-width": 1.25,
|
|
9
|
+
"circle-radius": 5,
|
|
10
|
+
"circle-fill-color": "rgba(255,255,255,0.4)",
|
|
11
|
+
"circle-stroke-width": 1.25,
|
|
12
|
+
"circle-stroke-color": "#3399CC",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function contextStyleToMaplibreLayers(
|
|
16
|
+
style: VectorStyle = {},
|
|
17
|
+
): Partial<LayerSpecification>[] {
|
|
18
|
+
const layers: Partial<LayerSpecification>[] = [];
|
|
19
|
+
|
|
20
|
+
if (Array.isArray(style)) {
|
|
21
|
+
return style.flatMap((style_) => {
|
|
22
|
+
if (style_.hasOwnProperty("style")) {
|
|
23
|
+
console.warn("Rules in styles are not supported yet.");
|
|
24
|
+
return contextStyleToMaplibreLayers((style_ as Rule).style);
|
|
25
|
+
}
|
|
26
|
+
return contextStyleToMaplibreLayers(style_ as any);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
style = { ...defaultOltStyle, ...style };
|
|
31
|
+
|
|
32
|
+
if (style["fill-color"]) {
|
|
33
|
+
layers.push({
|
|
34
|
+
type: "fill",
|
|
35
|
+
paint: {
|
|
36
|
+
"fill-color": (style as FlatFill)["fill-color"] as string,
|
|
37
|
+
},
|
|
38
|
+
filter: ["==", "$type", "Polygon"],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (style["stroke-color"] || style["stroke-width"]) {
|
|
42
|
+
layers.push({
|
|
43
|
+
type: "line",
|
|
44
|
+
paint: {
|
|
45
|
+
"line-color": style["stroke-color"] as string,
|
|
46
|
+
...(style["stroke-width"] !== undefined && {
|
|
47
|
+
"line-width": style["stroke-width"] as number,
|
|
48
|
+
}),
|
|
49
|
+
...(style["stroke-line-dash"] !== undefined && {
|
|
50
|
+
"line-dasharray": style["stroke-line-dash"],
|
|
51
|
+
}),
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (style["circle-radius"]) {
|
|
56
|
+
layers.push({
|
|
57
|
+
type: "circle",
|
|
58
|
+
paint: {
|
|
59
|
+
"circle-radius": style["circle-radius"],
|
|
60
|
+
"circle-stroke-color": style["circle-stroke-color"] as string,
|
|
61
|
+
"circle-color": style["circle-fill-color"] as string,
|
|
62
|
+
"circle-stroke-width": style["circle-stroke-width"] as number,
|
|
63
|
+
},
|
|
64
|
+
filter: ["==", "$type", "Point"],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return layers;
|
|
68
|
+
}
|
package/lib/index.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { MapContext, MapContextDiff } from "@geospatial-sdk/core";
|
|
3
|
+
import {
|
|
4
|
+
SAMPLE_CONTEXT,
|
|
5
|
+
SAMPLE_LAYER1,
|
|
6
|
+
SAMPLE_LAYER2,
|
|
7
|
+
SAMPLE_LAYER3,
|
|
8
|
+
SAMPLE_LAYER4,
|
|
9
|
+
} from "@geospatial-sdk/core/fixtures/map-context.fixtures";
|
|
10
|
+
import { applyContextDiffToMap } from "./apply-context-diff";
|
|
11
|
+
import * as mapHelpers from "../helpers/map.helpers";
|
|
12
|
+
import { getBeforeId } from "../helpers/map.helpers";
|
|
13
|
+
|
|
14
|
+
// Helper to create a fresh mock Map instance for each test
|
|
15
|
+
function createMockMap() {
|
|
16
|
+
return {
|
|
17
|
+
addLayer: vi.fn(),
|
|
18
|
+
addSource: vi.fn(),
|
|
19
|
+
removeLayer: vi.fn(),
|
|
20
|
+
removeSource: vi.fn(),
|
|
21
|
+
setZoom: vi.fn(),
|
|
22
|
+
setCenter: vi.fn(),
|
|
23
|
+
fitBounds: vi.fn(),
|
|
24
|
+
getStyle: vi.fn(() => ({ layers: [], sources: {} })),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe("applyContextDiffToMap (mocked Map)", () => {
|
|
29
|
+
let context: MapContext;
|
|
30
|
+
let diff: MapContextDiff;
|
|
31
|
+
let map: ReturnType<typeof createMockMap>;
|
|
32
|
+
|
|
33
|
+
beforeEach(async () => {
|
|
34
|
+
context = {
|
|
35
|
+
...SAMPLE_CONTEXT,
|
|
36
|
+
layers: [SAMPLE_LAYER2, SAMPLE_LAYER1],
|
|
37
|
+
};
|
|
38
|
+
map = createMockMap();
|
|
39
|
+
map.getStyle.mockReturnValue({ layers: [], sources: {} });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("does not call any mutating methods for no change", async () => {
|
|
43
|
+
diff = {
|
|
44
|
+
layersAdded: [],
|
|
45
|
+
layersChanged: [],
|
|
46
|
+
layersRemoved: [],
|
|
47
|
+
layersReordered: [],
|
|
48
|
+
};
|
|
49
|
+
await applyContextDiffToMap(map as any, diff);
|
|
50
|
+
expect(map.addLayer).not.toHaveBeenCalled();
|
|
51
|
+
expect(map.addSource).not.toHaveBeenCalled();
|
|
52
|
+
expect(map.removeLayer).not.toHaveBeenCalled();
|
|
53
|
+
expect(map.removeSource).not.toHaveBeenCalled();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("calls addLayer and addSource for layers added", async () => {
|
|
57
|
+
diff = {
|
|
58
|
+
layersAdded: [
|
|
59
|
+
{ layer: SAMPLE_LAYER3, position: 0 },
|
|
60
|
+
{ layer: SAMPLE_LAYER4, position: 2 },
|
|
61
|
+
],
|
|
62
|
+
layersChanged: [],
|
|
63
|
+
layersRemoved: [],
|
|
64
|
+
layersReordered: [],
|
|
65
|
+
};
|
|
66
|
+
await applyContextDiffToMap(map as any, diff);
|
|
67
|
+
expect(map.addSource).toHaveBeenCalled();
|
|
68
|
+
expect(map.addLayer).toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("calls removeLayer and removeSource for layers removed", async () => {
|
|
72
|
+
// Simulate getLayersAtPosition returning a mock layer with id/source
|
|
73
|
+
const mockLayer = { id: "layerid", source: "sourceid" };
|
|
74
|
+
vi.spyOn(mapHelpers, "getLayersAtPosition").mockReturnValue([mockLayer]);
|
|
75
|
+
diff = {
|
|
76
|
+
layersAdded: [],
|
|
77
|
+
layersChanged: [],
|
|
78
|
+
layersRemoved: [
|
|
79
|
+
{ layer: SAMPLE_LAYER2, position: 0 },
|
|
80
|
+
{ layer: SAMPLE_LAYER1, position: 1 },
|
|
81
|
+
],
|
|
82
|
+
layersReordered: [],
|
|
83
|
+
};
|
|
84
|
+
await applyContextDiffToMap(map as any, diff);
|
|
85
|
+
expect(map.removeLayer).toHaveBeenCalledWith("layerid");
|
|
86
|
+
expect(map.removeSource).toHaveBeenCalledWith("sourceid");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("calls addLayer for changed layers", async () => {
|
|
90
|
+
const generateLayerIdSpy = vi
|
|
91
|
+
.spyOn(mapHelpers, "generateLayerId")
|
|
92
|
+
.mockReturnValue("azreza");
|
|
93
|
+
const getBeforeId = vi
|
|
94
|
+
.spyOn(mapHelpers, "getBeforeId")
|
|
95
|
+
.mockReturnValue("azreza");
|
|
96
|
+
const removeLayersFromSourceSpy = vi.spyOn(
|
|
97
|
+
mapHelpers,
|
|
98
|
+
"removeLayersFromSource",
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
diff = {
|
|
102
|
+
layersAdded: [],
|
|
103
|
+
layersChanged: [
|
|
104
|
+
{ layer: { ...SAMPLE_LAYER3, url: "http://changed/" }, position: 0 },
|
|
105
|
+
{
|
|
106
|
+
layer: {
|
|
107
|
+
...SAMPLE_LAYER1,
|
|
108
|
+
url: "http://changed/",
|
|
109
|
+
extras: { changed: true },
|
|
110
|
+
},
|
|
111
|
+
position: 1,
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
layersRemoved: [],
|
|
115
|
+
layersReordered: [],
|
|
116
|
+
};
|
|
117
|
+
await applyContextDiffToMap(map as any, diff);
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
expect(generateLayerIdSpy).toHaveBeenCalledWith(
|
|
121
|
+
diff.layersChanged[1].layer,
|
|
122
|
+
);
|
|
123
|
+
expect(generateLayerIdSpy).toHaveBeenCalledWith(
|
|
124
|
+
diff.layersChanged[0].layer,
|
|
125
|
+
);
|
|
126
|
+
expect(map.addLayer).toHaveBeenCalled();
|
|
127
|
+
expect(removeLayersFromSourceSpy).toHaveBeenCalled();
|
|
128
|
+
expect(removeLayersFromSourceSpy).toHaveBeenCalledTimes(2);
|
|
129
|
+
} finally {
|
|
130
|
+
generateLayerIdSpy.mockRestore();
|
|
131
|
+
removeLayersFromSourceSpy.mockRestore();
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("calls fitBounds for viewChanges with extent", async () => {
|
|
136
|
+
diff = {
|
|
137
|
+
layersAdded: [],
|
|
138
|
+
layersChanged: [],
|
|
139
|
+
layersRemoved: [],
|
|
140
|
+
layersReordered: [],
|
|
141
|
+
viewChanges: { extent: [-10, -10, 20, 20] },
|
|
142
|
+
};
|
|
143
|
+
await applyContextDiffToMap(map as any, diff);
|
|
144
|
+
expect(map.fitBounds).toHaveBeenCalledWith(
|
|
145
|
+
[
|
|
146
|
+
[-10, -10],
|
|
147
|
+
[20, 20],
|
|
148
|
+
],
|
|
149
|
+
expect.objectContaining({ padding: 20, duration: 1000 }),
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { MapContextDiff } from "@geospatial-sdk/core";
|
|
2
|
+
import { Map } from "maplibre-gl";
|
|
3
|
+
import { createLayer } from "./create-map";
|
|
4
|
+
import {
|
|
5
|
+
generateLayerId,
|
|
6
|
+
getBeforeId,
|
|
7
|
+
getLayersAtPosition,
|
|
8
|
+
removeLayersFromSource,
|
|
9
|
+
} from "../helpers/map.helpers";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Apply a context diff to an MapLibre map
|
|
13
|
+
* @param map
|
|
14
|
+
* @param contextDiff
|
|
15
|
+
*/
|
|
16
|
+
export async function applyContextDiffToMap(
|
|
17
|
+
map: Map,
|
|
18
|
+
contextDiff: MapContextDiff,
|
|
19
|
+
): Promise<void> {
|
|
20
|
+
// removed layers (sorted by descending position)
|
|
21
|
+
if (contextDiff.layersRemoved.length > 0) {
|
|
22
|
+
const removed = contextDiff.layersRemoved.sort(
|
|
23
|
+
(a, b) => b.position - a.position,
|
|
24
|
+
);
|
|
25
|
+
for (const layerRemoved of removed) {
|
|
26
|
+
const mlLayers = getLayersAtPosition(map, layerRemoved.position);
|
|
27
|
+
if (mlLayers.length === 0) {
|
|
28
|
+
console.warn(
|
|
29
|
+
`[Warning] applyContextDiffToMap: no layer found at position ${layerRemoved.position} to remove.`,
|
|
30
|
+
);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const sourceId = mlLayers[0].source;
|
|
34
|
+
mlLayers.forEach((layer) => {
|
|
35
|
+
map.removeLayer(layer.id);
|
|
36
|
+
});
|
|
37
|
+
map.removeSource(sourceId);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// insert added layers
|
|
42
|
+
const newLayers = await Promise.all(
|
|
43
|
+
contextDiff.layersAdded.map((layerAdded) =>
|
|
44
|
+
createLayer(layerAdded.layer, layerAdded.position),
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
newLayers.forEach((style, index) => {
|
|
48
|
+
const position = contextDiff.layersAdded[index].position;
|
|
49
|
+
const beforeId = getBeforeId(map, position);
|
|
50
|
+
Object.keys(style.sources).forEach((sourceId) =>
|
|
51
|
+
map.addSource(sourceId, style.sources[sourceId]),
|
|
52
|
+
);
|
|
53
|
+
style.layers.map((layer) => {
|
|
54
|
+
map.addLayer(layer, beforeId);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// recreate changed layers
|
|
59
|
+
for (const layerChanged of contextDiff.layersChanged) {
|
|
60
|
+
const { layer, position } = layerChanged;
|
|
61
|
+
const sourceId = generateLayerId(layer);
|
|
62
|
+
removeLayersFromSource(map, sourceId);
|
|
63
|
+
const beforeId = getBeforeId(map, position);
|
|
64
|
+
createLayer(layer, position).then((styleDiff) => {
|
|
65
|
+
styleDiff.layers.map((layer) => {
|
|
66
|
+
map.addLayer(layer, beforeId);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (typeof contextDiff.viewChanges !== "undefined") {
|
|
72
|
+
const { viewChanges } = contextDiff;
|
|
73
|
+
|
|
74
|
+
if (viewChanges && "extent" in viewChanges) {
|
|
75
|
+
const { extent } = viewChanges;
|
|
76
|
+
|
|
77
|
+
map.fitBounds(
|
|
78
|
+
[
|
|
79
|
+
[extent[0], extent[1]],
|
|
80
|
+
[extent[2], extent[3]],
|
|
81
|
+
],
|
|
82
|
+
{
|
|
83
|
+
padding: 20,
|
|
84
|
+
duration: 1000,
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|