solid-map-gl 1.5.3 → 1.6.1
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/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/source/components/Atmosphere/index.jsx +6 -4
- package/dist/source/components/Camera/index.jsx +48 -4
- package/dist/source/components/Control/index.jsx +32 -30
- package/dist/source/components/Image/index.jsx +11 -9
- package/dist/source/components/Layer/index.jsx +48 -43
- package/dist/source/components/Light/index.jsx +12 -0
- package/dist/source/components/MapGL/index.jsx +153 -133
- package/dist/source/components/Marker/index.jsx +29 -22
- package/dist/source/components/Popup/index.jsx +23 -15
- package/dist/source/components/Source/index.jsx +65 -44
- package/dist/source/components/Terrain/index.jsx +21 -26
- package/dist/source/index.jsx +1 -0
- package/dist/source/mapStyles.js +5 -5
- package/dist/types/components/Camera/index.d.ts +10 -1
- package/dist/types/components/Control/index.d.ts +2 -2
- package/dist/types/components/Light/index.d.ts +5 -0
- package/dist/types/components/MapGL/index.d.ts +6 -0
- package/dist/types/components/Terrain/index.d.ts +0 -1
- package/dist/types/index.d.ts +1 -0
- package/package.json +9 -9
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
import { createEffect, onCleanup
|
|
1
|
+
import { createEffect, onCleanup } from 'solid-js';
|
|
2
2
|
import { useMap } from '../MapGL';
|
|
3
|
+
const getControl = (lib, type, options, custom) => {
|
|
4
|
+
if (custom)
|
|
5
|
+
return new custom(options);
|
|
6
|
+
switch (type) {
|
|
7
|
+
case 'navigation':
|
|
8
|
+
return new lib.NavigationControl(options);
|
|
9
|
+
case 'scale':
|
|
10
|
+
return new lib.ScaleControl(options);
|
|
11
|
+
case 'attribution':
|
|
12
|
+
return new lib.AttributionControl(options);
|
|
13
|
+
case 'geolocate':
|
|
14
|
+
return new lib.GeolocateControl(options);
|
|
15
|
+
case 'fullscreen':
|
|
16
|
+
return new lib.FullscreenControl();
|
|
17
|
+
// options || { container: map().container }
|
|
18
|
+
default:
|
|
19
|
+
throw new Error(`Unknown control type: ${type}`);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
3
22
|
export const Control = props => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
case 'navigation':
|
|
14
|
-
return new mapLib.NavigationControl(options);
|
|
15
|
-
case 'scale':
|
|
16
|
-
return new mapLib.ScaleControl(options);
|
|
17
|
-
case 'attribution':
|
|
18
|
-
return new mapLib.AttributionControl(options);
|
|
19
|
-
case 'geolocate':
|
|
20
|
-
return new mapLib.GeolocateControl(options);
|
|
21
|
-
case 'fullscreen':
|
|
22
|
-
return new mapLib.FullscreenControl();
|
|
23
|
-
// options || { container: map().container }
|
|
24
|
-
default:
|
|
25
|
-
throw new Error(`Unknown control type: ${type}`);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
const control = getControl(props.type, props.options);
|
|
29
|
-
control && map()?.addControl(control, props.position);
|
|
30
|
-
setControl(control);
|
|
23
|
+
if (!useMap())
|
|
24
|
+
return;
|
|
25
|
+
const [map] = useMap();
|
|
26
|
+
let control = null;
|
|
27
|
+
// Add or Update Control
|
|
28
|
+
createEffect(() => {
|
|
29
|
+
control && map().hasControl(control) && map().removeControl(control);
|
|
30
|
+
control = getControl(map().mapLib, props.type, props.options, props.custom);
|
|
31
|
+
map().addControl(control, props.position);
|
|
31
32
|
});
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
// Remove Control
|
|
34
|
+
onCleanup(() => map()?.removeControl(control));
|
|
35
|
+
return null;
|
|
34
36
|
};
|
|
@@ -19,10 +19,12 @@ const PATTERN = {
|
|
|
19
19
|
};
|
|
20
20
|
export const patternList = Object.keys(PATTERN);
|
|
21
21
|
export const Image = props => {
|
|
22
|
-
|
|
22
|
+
if (!useMap())
|
|
23
|
+
return;
|
|
24
|
+
const [map] = useMap();
|
|
23
25
|
const [size, setSize] = createSignal({ width: 0, height: 0 });
|
|
24
26
|
// Remove Image
|
|
25
|
-
onCleanup(() => map
|
|
27
|
+
onCleanup(() => map()?.hasImage(props.id) && map()?.removeImage(props.id));
|
|
26
28
|
// Add or Update Image
|
|
27
29
|
createEffect(() => {
|
|
28
30
|
if (!props.id)
|
|
@@ -34,16 +36,16 @@ export const Image = props => {
|
|
|
34
36
|
: props.options;
|
|
35
37
|
_loadImage(props.image || _createPattern(props.pattern), data => {
|
|
36
38
|
const { width, height } = data;
|
|
37
|
-
if (!map.hasImage(props.id))
|
|
38
|
-
map.addImage(props.id, data, ops);
|
|
39
|
+
if (!map().hasImage(props.id))
|
|
40
|
+
map().addImage(props.id, data, ops);
|
|
39
41
|
if (!props.pattern &&
|
|
40
42
|
untrack(() => width === size().width && height === size().height)) {
|
|
41
|
-
map.updateImage(props.id, data);
|
|
42
|
-
map.triggerRepaint();
|
|
43
|
+
map().updateImage(props.id, data);
|
|
44
|
+
map().triggerRepaint();
|
|
43
45
|
}
|
|
44
46
|
else {
|
|
45
|
-
map.removeImage(props.id);
|
|
46
|
-
map.addImage(props.id, data, ops);
|
|
47
|
+
map().removeImage(props.id);
|
|
48
|
+
map().addImage(props.id, data, ops);
|
|
47
49
|
}
|
|
48
50
|
setSize({ width, height });
|
|
49
51
|
});
|
|
@@ -52,7 +54,7 @@ export const Image = props => {
|
|
|
52
54
|
const _loadImage = (image, callback) => {
|
|
53
55
|
if (typeof image !== 'string')
|
|
54
56
|
return callback(image);
|
|
55
|
-
map.loadImage(image, (error, imageData) => {
|
|
57
|
+
map().loadImage(image, (error, imageData) => {
|
|
56
58
|
if (error)
|
|
57
59
|
throw error;
|
|
58
60
|
return callback(imageData);
|
|
@@ -13,46 +13,64 @@ const diff = (newProps = {}, prevProps = {}) => {
|
|
|
13
13
|
}, []);
|
|
14
14
|
};
|
|
15
15
|
export const Layer = props => {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if (!useMap())
|
|
17
|
+
return;
|
|
18
|
+
const [map] = useMap();
|
|
19
|
+
const sourceId = props.style.source || useSourceId();
|
|
18
20
|
props.id = props.id || createUniqueId();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const debug = (text, value) => {
|
|
22
|
+
map().debug &&
|
|
23
|
+
console.debug('%c[MapGL]', 'color: #10b981', text, value || '');
|
|
24
|
+
};
|
|
25
|
+
// Add Layer
|
|
26
|
+
// if (!map().getLayer(props.id)) {
|
|
27
|
+
map().addLayer(props.customLayer || {
|
|
28
|
+
...props.style,
|
|
29
|
+
id: props.id,
|
|
30
|
+
source: sourceId,
|
|
31
|
+
metadata: {
|
|
32
|
+
smg: { beforeType: props.beforeType, beforeId: props.beforeId },
|
|
33
|
+
},
|
|
34
|
+
}, props.beforeType
|
|
35
|
+
? map()
|
|
36
|
+
.getStyle()
|
|
37
|
+
.layers.find(l => l.type === props.beforeType)?.id
|
|
38
|
+
: props.beforeId);
|
|
39
|
+
map().layerIdList.push(props.id);
|
|
40
|
+
debug('Add Layer:', props.id);
|
|
21
41
|
// Hook up events
|
|
22
|
-
|
|
42
|
+
layerEvents.forEach(item => {
|
|
23
43
|
if (props[item]) {
|
|
24
44
|
const event = item.slice(2).toLowerCase();
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
45
|
+
map().on(event, props.id, evt => {
|
|
46
|
+
props[item](evt);
|
|
47
|
+
debug(`Layer '${event}' event on '${props.id}':`, evt);
|
|
48
|
+
});
|
|
28
49
|
}
|
|
29
|
-
})
|
|
50
|
+
});
|
|
51
|
+
// }
|
|
30
52
|
// Update Style
|
|
31
53
|
createEffect((prev) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
!map().getSource(sourceId) ||
|
|
35
|
-
!map().getLayer(props.id))
|
|
54
|
+
const style = props.style;
|
|
55
|
+
if (style === prev || !map().isStyleLoaded())
|
|
36
56
|
return;
|
|
37
|
-
if (
|
|
38
|
-
diff(
|
|
39
|
-
if (
|
|
40
|
-
diff(
|
|
41
|
-
if (
|
|
42
|
-
props.style.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
57
|
+
if (style.layout !== prev?.layout)
|
|
58
|
+
diff(style.layout, prev?.layout).forEach(([key, value]) => map().setLayoutProperty(props.id, key, value, { validate: false }));
|
|
59
|
+
if (style.paint !== prev?.paint)
|
|
60
|
+
diff(style.paint, prev?.paint).forEach(([key, value]) => map().setPaintProperty(props.id, key, value, { validate: false }));
|
|
61
|
+
if (style.minzoom !== prev?.minzoom || style.maxzoom !== prev?.maxzoom)
|
|
62
|
+
map().setLayerZoomRange(props.id, style.minzoom, style.maxzoom);
|
|
63
|
+
if (style.filter !== prev?.filter)
|
|
64
|
+
map().setFilter(props.id, style.filter, { validate: false });
|
|
65
|
+
debug('Update Layer Style:', props.id);
|
|
66
|
+
return style;
|
|
47
67
|
}, props.style);
|
|
48
68
|
// Update Visibility
|
|
49
69
|
createEffect((prev) => {
|
|
50
|
-
if (props.visible ===
|
|
51
|
-
props.visible === prev ||
|
|
52
|
-
!map().getSource(sourceId) ||
|
|
53
|
-
!map().getLayer(props.id))
|
|
70
|
+
if (props.visible === prev)
|
|
54
71
|
return;
|
|
55
72
|
map().setLayoutProperty(props.id, 'visibility', props.visible ? 'visible' : 'none', { validate: false });
|
|
73
|
+
debug(`Update Visibility (${props.id}):`, props.visible);
|
|
56
74
|
return props.visible;
|
|
57
75
|
}, props.visible);
|
|
58
76
|
// Update Filter
|
|
@@ -61,6 +79,7 @@ export const Layer = props => {
|
|
|
61
79
|
return;
|
|
62
80
|
!map().isStyleLoaded() && (await map().once('styledata'));
|
|
63
81
|
map().setFilter(props.id, props.filter);
|
|
82
|
+
debug(`Update Filter (${props.id}):`, props.filter);
|
|
64
83
|
});
|
|
65
84
|
// Update Feature State
|
|
66
85
|
createEffect(async () => {
|
|
@@ -77,21 +96,7 @@ export const Layer = props => {
|
|
|
77
96
|
id: props.featureState.id,
|
|
78
97
|
}, props.featureState.state);
|
|
79
98
|
});
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
!map().getLayer(props.id) &&
|
|
83
|
-
map().addLayer(props.customLayer || {
|
|
84
|
-
...props.style,
|
|
85
|
-
id: props.id,
|
|
86
|
-
source: sourceId,
|
|
87
|
-
metadata: {
|
|
88
|
-
smg: { beforeType: props.beforeType, beforeId: props.beforeId },
|
|
89
|
-
},
|
|
90
|
-
}, props.beforeType
|
|
91
|
-
? map()
|
|
92
|
-
?.getStyle()
|
|
93
|
-
.layers.find(l => l.type === props.beforeType)?.id
|
|
94
|
-
: props.beforeId);
|
|
95
|
-
});
|
|
99
|
+
//Remove Layer
|
|
100
|
+
onCleanup(() => map()?.getLayer(props.id) && map()?.removeLayer(props.id));
|
|
96
101
|
return props.children;
|
|
97
102
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { onCleanup, createEffect } from 'solid-js';
|
|
2
|
+
import { useMap } from '../MapGL';
|
|
3
|
+
export const Light = props => {
|
|
4
|
+
if (!useMap())
|
|
5
|
+
return;
|
|
6
|
+
const [map] = useMap();
|
|
7
|
+
// Add or Update Light Layer
|
|
8
|
+
createEffect(() => map().setLight(props.style || {}));
|
|
9
|
+
// Remove Light Layer
|
|
10
|
+
onCleanup(() => map()?.setLight(null));
|
|
11
|
+
return null;
|
|
12
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createSignal, createEffect, onMount, onCleanup, createContext, useContext, createUniqueId,
|
|
1
|
+
import { createSignal, createEffect, onMount, onCleanup, createContext, useContext, createUniqueId, } from 'solid-js';
|
|
2
2
|
import { mapEvents } from '../../events';
|
|
3
3
|
import { vectorStyleList } from '../../mapStyles';
|
|
4
4
|
const MapContext = createContext();
|
|
@@ -7,12 +7,17 @@ export const useMap = () => useContext(MapContext);
|
|
|
7
7
|
/** Creates a new Map Container */
|
|
8
8
|
export const MapGL = props => {
|
|
9
9
|
props.id = props.id || createUniqueId();
|
|
10
|
+
let map;
|
|
11
|
+
let resizeObserver;
|
|
10
12
|
const [mapRoot, setMapRoot] = createSignal();
|
|
11
|
-
const [
|
|
12
|
-
const [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const debug = (text, value) =>
|
|
13
|
+
const [darkMode, setDarkMode] = createSignal(false);
|
|
14
|
+
const [userInteraction, setUserInteraction] = createSignal(false);
|
|
15
|
+
// debounce user interactions
|
|
16
|
+
createEffect(() => props.onUserInteraction?.(userInteraction()));
|
|
17
|
+
const debug = (text, value) => {
|
|
18
|
+
props.debug &&
|
|
19
|
+
console.debug('%c[MapGL]', 'color: #0ea5e9', text, value || '');
|
|
20
|
+
};
|
|
16
21
|
const mapRef = (<div id={props.id} class={props?.class} classList={props?.classList} style={props?.style || props?.class || props?.classList
|
|
17
22
|
? props.style
|
|
18
23
|
: { position: 'absolute', inset: 0, ...props.style }}/>);
|
|
@@ -31,168 +36,183 @@ export const MapGL = props => {
|
|
|
31
36
|
let mapLib = props.mapLib || (await import('mapbox-gl'));
|
|
32
37
|
if (!mapLib.Map)
|
|
33
38
|
mapLib = window['maplibregl'] || window['mapboxgl'];
|
|
34
|
-
|
|
39
|
+
if (!mapLib.supported())
|
|
40
|
+
throw new Error('Mapbox GL not supported');
|
|
41
|
+
debug(`Map (v${mapLib.version}) loading...`);
|
|
42
|
+
map = new mapLib.Map({
|
|
35
43
|
accessToken:
|
|
36
44
|
//@ts-ignore
|
|
37
|
-
import.meta.env.VITE_MAPBOX_ACCESS_TOKEN,
|
|
38
|
-
interactive: !!props.onViewportChange,
|
|
45
|
+
props.options.accessToken || import.meta.env.VITE_MAPBOX_ACCESS_TOKEN,
|
|
46
|
+
interactive: props.options.interactive || !!props.onViewportChange,
|
|
39
47
|
...props.options,
|
|
40
|
-
|
|
48
|
+
...props.viewport,
|
|
41
49
|
container: mapRef,
|
|
42
|
-
|
|
43
|
-
center: props.viewport?.center,
|
|
44
|
-
zoom: props.viewport?.zoom || null,
|
|
45
|
-
pitch: props.viewport?.pitch || null,
|
|
46
|
-
bearing: props.viewport?.bearing || null,
|
|
50
|
+
style: getStyle(props.options?.style, props.darkStyle),
|
|
47
51
|
fitBoundsOptions: { padding: props.viewport?.padding },
|
|
48
52
|
});
|
|
49
53
|
map.mapLib = mapLib;
|
|
50
54
|
map.debug = props.debug;
|
|
51
|
-
|
|
52
|
-
map.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
map.sourceIdList = [];
|
|
56
|
+
map.layerIdList = [];
|
|
57
|
+
map.once('load', () => {
|
|
58
|
+
setMapRoot(map);
|
|
59
|
+
debug('Map loaded');
|
|
60
|
+
});
|
|
61
|
+
['mousedown', 'touchstart', 'wheel'].forEach(event => map.on(event, () => setUserInteraction(true)));
|
|
62
|
+
map.on('moveend', evt => !evt.rotate && setUserInteraction(false));
|
|
59
63
|
// Listen to dark theme changes
|
|
60
|
-
const darkTheme = window
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
const darkTheme = typeof window !== 'undefined' &&
|
|
65
|
+
window.matchMedia('(prefers-color-scheme: dark)');
|
|
66
|
+
darkTheme?.addEventListener('change', () => {
|
|
67
|
+
setDarkMode(darkTheme.matches);
|
|
68
|
+
debug('Set dark theme to:', darkTheme.matches?.toString());
|
|
69
|
+
});
|
|
70
|
+
new MutationObserver(() => {
|
|
71
|
+
const darkTheme = document.body.classList.contains('dark');
|
|
72
|
+
setDarkMode(darkTheme);
|
|
73
|
+
debug('Set dark theme to:', darkTheme);
|
|
74
|
+
}).observe(document.body, { attributes: true });
|
|
75
|
+
// Listen to map container size changes
|
|
76
|
+
// !props.disableResize &&
|
|
77
|
+
// new ResizeObserver(() => {
|
|
78
|
+
// map?.resize()
|
|
79
|
+
// debug('Map resized')
|
|
80
|
+
// }).observe(mapRef as Element)
|
|
64
81
|
// Hook up events
|
|
65
|
-
|
|
82
|
+
mapEvents.forEach(item => {
|
|
66
83
|
const prop = props[item];
|
|
67
84
|
if (prop) {
|
|
68
85
|
const event = item.slice(2).toLowerCase();
|
|
69
86
|
if (typeof prop === 'function') {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
map.on(event, e => {
|
|
88
|
+
prop(e);
|
|
89
|
+
debug(`Map '${event}' event:`, e);
|
|
90
|
+
});
|
|
73
91
|
}
|
|
74
92
|
else {
|
|
75
93
|
Object.keys(prop).forEach(layerId => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
map.on(event, layerId, e => {
|
|
95
|
+
prop[layerId](e);
|
|
96
|
+
debug(`Map '${event}' event on '${layerId}':`, e);
|
|
97
|
+
});
|
|
79
98
|
});
|
|
80
99
|
}
|
|
81
100
|
}
|
|
82
|
-
}));
|
|
83
|
-
// Update debug features
|
|
84
|
-
createEffect(() => {
|
|
85
|
-
map.showTileBoundaries = props.showTileBoundaries;
|
|
86
|
-
map.showTerrainWireframe = props.showTerrainWireframe;
|
|
87
|
-
map.showPadding = props.showPadding;
|
|
88
|
-
map.showCollisionBoxes = props.showCollisionBoxes;
|
|
89
|
-
map.showOverdrawInspector = props.showOverdrawInspector;
|
|
90
101
|
});
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return props.transitionType;
|
|
102
|
+
// Hook up viewport events
|
|
103
|
+
map.on('move', event => {
|
|
104
|
+
const viewport = {
|
|
105
|
+
...props.viewport,
|
|
106
|
+
id: props.id,
|
|
107
|
+
point: { x: event.originalEvent?.x, y: event.originalEvent?.y },
|
|
108
|
+
center: props.viewport.center.lat
|
|
109
|
+
? map.getCenter()
|
|
110
|
+
: [map.getCenter().lng, map.getCenter().lat],
|
|
111
|
+
zoom: map.getZoom(),
|
|
112
|
+
pitch: map.getPitch(),
|
|
113
|
+
bearing: map.getBearing(),
|
|
114
|
+
};
|
|
115
|
+
props.onViewportChange && props.onViewportChange(viewport);
|
|
106
116
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
117
|
+
});
|
|
118
|
+
// Update Viewport
|
|
119
|
+
createEffect(() => {
|
|
120
|
+
const viewport = {
|
|
121
|
+
...props.viewport,
|
|
122
|
+
padding: props.viewport?.padding || 0,
|
|
123
|
+
};
|
|
124
|
+
if (!map || props.id === props.viewport?.id || userInteraction())
|
|
125
|
+
return;
|
|
126
|
+
map?.stop()[props.transitionType || 'flyTo'](viewport);
|
|
127
|
+
debug(`Update Viewport (${props.transitionType || 'flyTo'}):`, viewport);
|
|
128
|
+
});
|
|
129
|
+
// Update boundaries
|
|
130
|
+
createEffect(prev => {
|
|
131
|
+
const bounds = props.viewport?.bounds;
|
|
132
|
+
if (map && bounds && prev !== bounds && !userInteraction()) {
|
|
133
|
+
props.onViewportChange({
|
|
134
|
+
...props.viewport,
|
|
135
|
+
...map?.cameraForBounds(bounds, {
|
|
136
|
+
padding: props.viewport?.padding,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
debug(`Update Viewport Boundaries:`, bounds);
|
|
140
|
+
}
|
|
141
|
+
return bounds;
|
|
142
|
+
}, props.viewport?.bounds);
|
|
143
|
+
// Update Projection
|
|
144
|
+
createEffect(prev => {
|
|
145
|
+
const proj = props.options?.projection;
|
|
146
|
+
if (prev !== proj) {
|
|
147
|
+
map.setProjection(proj);
|
|
148
|
+
debug('Set Projection to:', proj);
|
|
149
|
+
}
|
|
150
|
+
return proj;
|
|
151
|
+
}, props.options?.projection);
|
|
152
|
+
// Update cursor
|
|
153
|
+
createEffect(() => {
|
|
154
|
+
if (!props.cursorStyle || !map)
|
|
155
|
+
return;
|
|
156
|
+
map.getCanvas().style.cursor = props.cursorStyle;
|
|
157
|
+
debug('Set Cursor to:', props.cursorStyle);
|
|
158
|
+
});
|
|
159
|
+
const insertLayers = (list, layers) => {
|
|
160
|
+
layers.forEach(layer => {
|
|
161
|
+
const index = list.findIndex(i => layer.metadata.smg.beforeType
|
|
162
|
+
? i.type === layer.metadata.smg.beforeType
|
|
163
|
+
: i.id === layer.metadata.smg.beforeId);
|
|
164
|
+
list =
|
|
165
|
+
index === -1
|
|
166
|
+
? [...list, layer]
|
|
167
|
+
: [...list.slice(0, index), layer, ...list.slice(index + 1)];
|
|
114
168
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
oldSources = Object.keys(oldStyle.sources)
|
|
127
|
-
.filter(s => s.startsWith('cl-'))
|
|
128
|
-
.reduce((obj, key) => ({ ...obj, [key]: oldStyle.sources[key] }), {});
|
|
129
|
-
}
|
|
169
|
+
return list;
|
|
170
|
+
};
|
|
171
|
+
// Update map style
|
|
172
|
+
createEffect(prev => {
|
|
173
|
+
const style = getStyle(props.options?.style, props.darkStyle);
|
|
174
|
+
if (map?.isStyleLoaded() && prev !== style) {
|
|
175
|
+
const oldStyle = map.getStyle();
|
|
176
|
+
const oldLayers = oldStyle.layers.filter(l => map.layerIdList.includes(l.id));
|
|
177
|
+
const oldSources = Object.keys(oldStyle.sources)
|
|
178
|
+
.filter(s => map.sourceIdList.includes(s))
|
|
179
|
+
.reduce((obj, key) => ({ ...obj, [key]: oldStyle.sources[key] }), {});
|
|
130
180
|
map.setStyle(style);
|
|
131
181
|
map.once('styledata', () => {
|
|
182
|
+
if (!oldLayers)
|
|
183
|
+
return;
|
|
132
184
|
const newStyle = map.getStyle();
|
|
133
185
|
map.setStyle({
|
|
134
186
|
...newStyle,
|
|
135
187
|
sources: { ...newStyle.sources, ...oldSources },
|
|
136
|
-
layers:
|
|
188
|
+
layers: insertLayers(newStyle.layers, oldLayers),
|
|
137
189
|
});
|
|
138
190
|
});
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
bounds: props.viewport?.bounds,
|
|
151
|
-
};
|
|
152
|
-
const callMove = event => {
|
|
153
|
-
if (event.originalEvent)
|
|
154
|
-
props.onViewportChange &&
|
|
155
|
-
props.onViewportChange({ ...viewport, id: props.id });
|
|
156
|
-
setTransitionType('jumpTo');
|
|
157
|
-
};
|
|
158
|
-
const callEnd = event => {
|
|
159
|
-
if (event.originalEvent)
|
|
160
|
-
props.onViewportChange && props.onViewportChange(viewport);
|
|
161
|
-
setTransitionType(props.transitionType);
|
|
162
|
-
};
|
|
163
|
-
map.on('move', callMove).on('moveend', callEnd);
|
|
164
|
-
onCleanup(() => map?.off('move', callMove).off('moveend', callEnd));
|
|
165
|
-
});
|
|
166
|
-
// Update boundaries
|
|
167
|
-
createEffect(prev => {
|
|
168
|
-
if (props.viewport?.bounds != prev)
|
|
169
|
-
props.onViewportChange({
|
|
170
|
-
...props.viewport,
|
|
171
|
-
...map.cameraForBounds(props.viewport?.bounds, {
|
|
172
|
-
padding: props.viewport?.padding,
|
|
173
|
-
}),
|
|
174
|
-
});
|
|
175
|
-
return props.viewport?.bounds;
|
|
176
|
-
}, props.viewport?.bounds);
|
|
177
|
-
// Update Viewport
|
|
191
|
+
debug('Set Mapstyle to:', style);
|
|
192
|
+
}
|
|
193
|
+
return style;
|
|
194
|
+
}, props.options?.style);
|
|
195
|
+
[
|
|
196
|
+
'showTileBoundaries',
|
|
197
|
+
'showTerrainWireframe',
|
|
198
|
+
'showCollisionBoxes',
|
|
199
|
+
'showPadding',
|
|
200
|
+
'showOverdrawInspector',
|
|
201
|
+
].forEach(item => {
|
|
178
202
|
createEffect(() => {
|
|
179
|
-
|
|
203
|
+
const prop = props[item];
|
|
204
|
+
if (!map)
|
|
180
205
|
return;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
padding: props.viewport?.padding || 0,
|
|
184
|
-
};
|
|
185
|
-
switch (untrack(transitionType)) {
|
|
186
|
-
case 'easeTo':
|
|
187
|
-
map.stop().easeTo(viewport);
|
|
188
|
-
case 'jumpTo':
|
|
189
|
-
map.stop().jumpTo(viewport);
|
|
190
|
-
default:
|
|
191
|
-
map.stop().flyTo(viewport);
|
|
192
|
-
}
|
|
206
|
+
map[item] = prop;
|
|
207
|
+
debug(`Set ${item} to:`, prop);
|
|
193
208
|
});
|
|
194
209
|
});
|
|
195
|
-
|
|
210
|
+
onCleanup(() => {
|
|
211
|
+
resizeObserver?.disconnect();
|
|
212
|
+
map?.remove();
|
|
213
|
+
debug('Map removed');
|
|
214
|
+
});
|
|
215
|
+
return (<MapContext.Provider value={[mapRoot, userInteraction, debug]}>
|
|
196
216
|
{mapRoot() && props.children}
|
|
197
217
|
{mapRef}
|
|
198
218
|
</MapContext.Provider>);
|