@mapcomponents/react-maplibre 0.1.9 → 0.1.13
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/.github/ISSUE_TEMPLATE/bug_report.md +2 -2
- package/.github/ISSUE_TEMPLATE/feature_request.md +3 -3
- package/.github/workflows/node_version_test.yml +25 -0
- package/.github/workflows/storybook.yml +6 -3
- package/CONTRIBUTING.md +2 -2
- package/README.md +3 -7
- package/coverage/clover.xml +748 -625
- package/coverage/coverage-final.json +19 -14
- package/coverage/lcov-report/block-navigation.js +8 -0
- package/coverage/lcov-report/index.html +170 -104
- package/coverage/lcov-report/sorter.js +26 -0
- package/coverage/lcov-report/{components → src/components}/MapLibreMap/MapLibreMap.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MapLibreMap/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlCreatePdfButton/MlCreatePdfButton.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlCreatePdfButton/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlFeatureEditor/MlFeatureEditor.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlFeatureEditor/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlFillExtrusionLayer/MlFillExtrusionLayer.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlFillExtrusionLayer/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlFollowGps/MlFollowGps.js.html +99 -48
- package/coverage/lcov-report/{components → src/components}/MlFollowGps/index.html +27 -21
- package/coverage/lcov-report/{components → src/components}/MlGPXViewer/MlGPXViewer.js.html +73 -61
- package/coverage/lcov-report/{components → src/components}/MlGPXViewer/gpxConverter.js.html +56 -71
- package/coverage/lcov-report/{components → src/components}/MlGPXViewer/index.html +32 -26
- package/coverage/lcov-report/{components → src/components}/MlGeoJsonLayer/MlGeoJsonLayer.js.html +91 -31
- package/coverage/lcov-report/{components → src/components}/MlGeoJsonLayer/index.html +35 -29
- package/coverage/lcov-report/{components → src/components}/MlImageMarkerLayer/MlImageMarkerLayer.js.html +26 -23
- package/coverage/lcov-report/{components → src/components}/MlImageMarkerLayer/index.html +26 -20
- package/coverage/lcov-report/{components → src/components}/MlLayer/MlLayer.js.html +37 -31
- package/coverage/lcov-report/{components → src/components}/MlLayer/index.html +33 -27
- package/coverage/lcov-report/{components → src/components}/MlLayerMagnify/MlLayerMagnify.js.html +48 -42
- package/coverage/lcov-report/{components → src/components}/MlLayerMagnify/index.html +31 -25
- package/coverage/lcov-report/{components → src/components}/MlLayerSwipe/MlLayerSwipe.js.html +45 -42
- package/coverage/lcov-report/{components → src/components}/MlLayerSwipe/index.html +31 -25
- package/coverage/lcov-report/src/components/MlLayerSwitcher/MlLayerSwitcher.js.html +755 -0
- package/coverage/lcov-report/src/components/MlLayerSwitcher/components/LayerBox.js.html +380 -0
- package/coverage/lcov-report/src/components/MlLayerSwitcher/components/index.html +117 -0
- package/coverage/lcov-report/src/components/MlLayerSwitcher/index.html +117 -0
- package/coverage/lcov-report/{components → src/components}/MlMarker/MlMarker.js.html +18 -12
- package/coverage/lcov-report/{components → src/components}/MlMarker/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlNavigationCompass/MlNavigationCompass.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlNavigationCompass/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlNavigationTools/MlNavigationTools.js.html +55 -37
- package/coverage/lcov-report/{components → src/components}/MlNavigationTools/index.html +23 -17
- package/coverage/lcov-report/{components → src/components}/MlOsmLayer/MlOsmLayer.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlOsmLayer/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlScaleReference/MlScaleReference.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlScaleReference/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlShareMapState/MlShareMapState.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlShareMapState/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlSpatialElevationProfile/MlSpatialElevationProfile.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlSpatialElevationProfile/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlThreeJsLayer/MlThreeJsLayer.js.html +37 -55
- package/coverage/lcov-report/{components → src/components}/MlThreeJsLayer/index.html +31 -25
- package/coverage/lcov-report/{components → src/components}/MlUseMapDebugger/MlUseMapDebugger.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlUseMapDebugger/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlVectorTileLayer/MlVectorTileLayer.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlVectorTileLayer/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlWmsFeatureInfoPopup/MlWmsFeatureInfoPopup.js.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlWmsFeatureInfoPopup/index.html +17 -11
- package/coverage/lcov-report/{components → src/components}/MlWmsLayer/MlWmsLayer.js.html +20 -14
- package/coverage/lcov-report/{components → src/components}/MlWmsLayer/index.html +21 -15
- package/coverage/lcov-report/{components → src/components}/MlWmsLoader/MlWmsLoader.js.html +38 -20
- package/coverage/lcov-report/{components → src/components}/MlWmsLoader/index.html +23 -17
- package/coverage/lcov-report/{hooks → src/hooks}/index.html +17 -11
- package/coverage/lcov-report/{hooks → src/hooks}/useMap.js.html +17 -11
- package/coverage/lcov-report/{hooks → src/hooks}/useMapState.js.html +17 -11
- package/coverage/lcov-report/{hooks → src/hooks}/useWms.js.html +25 -19
- package/coverage/lcov-report/src/i18n.js.html +167 -0
- package/coverage/lcov-report/src/index.html +117 -0
- package/coverage/lcov-report/src/translations/english.js.html +95 -0
- package/coverage/lcov-report/src/translations/german.js.html +95 -0
- package/coverage/lcov-report/src/translations/index.html +132 -0
- package/coverage/lcov.info +1278 -1010
- package/dist/b556faa3bc6829d2.png +0 -0
- package/dist/index.esm.js +170 -109
- package/dist/index.esm.js.map +1 -1
- package/package.json +3 -1
- package/public/assets/dop.png +0 -0
- package/public/assets/historic.png +0 -0
- package/public/assets/osm.png +0 -0
- package/public/thumbnails/MlFollowGps.png +0 -0
- package/public/thumbnails/MlThreeJsLayer.png +0 -0
- package/rollup.config.js +10 -2
- package/src/components/MapLibreMap/lib/MapLibreGlWrapper.js +58 -73
- package/src/components/MlCreatePdfButton/MlCreatePdfButton.meta.json +1 -1
- package/src/components/MlFeatureEditor/MlFeatureEditor.meta.json +2 -2
- package/src/components/MlFollowGps/MlFollowGps.js +46 -31
- package/src/components/MlFollowGps/MlFollowGps.meta.json +2 -2
- package/src/components/MlFollowGps/assets/marker.png +0 -0
- package/src/components/MlGPXViewer/MlGPXViewer.js +45 -43
- package/src/components/MlGPXViewer/gpxConverter.js +22 -29
- package/src/components/MlGeoJsonLayer/MlGeoJsonLayer.js +27 -9
- package/src/components/MlGeoJsonLayer/MlGeoJsonLayer.meta.json +1 -1
- package/src/components/MlGeoJsonLayer/util/transitionFunctions.js +19 -12
- package/src/components/MlImageMarkerLayer/MlImageMarkerLayer.js +3 -4
- package/src/components/MlImageMarkerLayer/MlImageMarkerLayer.test.js +6 -7
- package/src/components/MlLayer/MlLayer.js +2 -2
- package/src/components/MlLayer/MlLayer.test.js +12 -10
- package/src/components/MlLayerMagnify/MlLayerMagnify.js +3 -3
- package/src/components/MlLayerSwipe/MlLayerSwipe.js +4 -5
- package/src/components/MlLayerSwitcher/MlLayerSwitcher.css +17 -0
- package/src/components/MlLayerSwitcher/MlLayerSwitcher.doc.de.md +3 -0
- package/src/components/MlLayerSwitcher/MlLayerSwitcher.js +223 -0
- package/src/components/MlLayerSwitcher/MlLayerSwitcher.meta_.json +15 -0
- package/src/components/MlLayerSwitcher/MlLayerSwitcher.stories.js +106 -0
- package/src/components/MlLayerSwitcher/assets/sample_1.json +26 -0
- package/src/components/MlLayerSwitcher/assets/sample_2.json +22 -0
- package/src/components/MlLayerSwitcher/components/LayerBox.js +98 -0
- package/src/components/MlMarker/MlMarker.js +1 -1
- package/src/components/MlNavigationTools/MlNavigationTools.js +26 -22
- package/src/components/MlScaleReference/MlScaleReference.meta.json +1 -1
- package/src/components/MlScaleReference/MlScaleReference.stories.js +25 -21
- package/src/components/MlSpatialElevationProfile/MlSpatialElevationProfile.stories.js +12 -6
- package/src/components/MlThreeJsLayer/MlThreeJsLayer.js +8 -15
- package/src/components/MlVectorTileLayer/MlVectorTileLayer.meta.json +3 -3
- package/src/components/MlWmsLayer/MlWmsLayer.js +1 -1
- package/src/components/MlWmsLoader/MlWmsLoader.js +8 -4
- package/src/components/MlWmsLoader/MlWmsLoader.meta.json +1 -1
- package/src/components/MlWmsLoader/MlWmsLoader.stories.js +5 -4
- package/src/decorators/EmptyMapContextDecorator.js +11 -6
- package/src/decorators/MapContext3DDecorator.js +25 -20
- package/src/decorators/MapContextDashboardDecorator.js +7 -7
- package/src/decorators/MapContextDecorator.js +7 -8
- package/src/decorators/MapContextKlokantechBasicDecorator.js +8 -9
- package/src/decorators/MultiMapContextDecorator.js +2 -6
- package/src/hooks/useMapState.stories.js +7 -2
- package/src/hooks/useWms.js +7 -6
- package/src/i18n.js +28 -0
- package/src/translations/english.js +4 -0
- package/src/translations/german.js +4 -0
- package/src/ui_components/ImageLoader.js +73 -0
- package/src/ui_components/Sidebar.js +76 -22
- package/src/ui_components/TopToolbar.js +18 -18
|
@@ -21,6 +21,7 @@ const MlGeoJsonLayer = (props) => {
|
|
|
21
21
|
const mapRef = useRef(null);
|
|
22
22
|
const initializedRef = useRef(false);
|
|
23
23
|
const transitionInProgressRef = useRef(false);
|
|
24
|
+
const transitionTimeoutRef = useRef(undefined);
|
|
24
25
|
const currentTransitionStepRef = useRef(false);
|
|
25
26
|
const transitionGeojsonDataRef = useRef([]);
|
|
26
27
|
const transitionGeojsonCommonDataRef = useRef([]);
|
|
@@ -33,6 +34,9 @@ const MlGeoJsonLayer = (props) => {
|
|
|
33
34
|
let _componentId = componentId.current;
|
|
34
35
|
return () => {
|
|
35
36
|
// This is the cleanup function, it is called when this react component is removed from react-dom
|
|
37
|
+
if (transitionTimeoutRef.current) {
|
|
38
|
+
clearTimeout(transitionTimeoutRef.current);
|
|
39
|
+
}
|
|
36
40
|
if (mapRef.current) {
|
|
37
41
|
mapRef.current.cleanup(_componentId);
|
|
38
42
|
|
|
@@ -43,11 +47,17 @@ const MlGeoJsonLayer = (props) => {
|
|
|
43
47
|
|
|
44
48
|
useEffect(() => {
|
|
45
49
|
if (!mapRef.current || !initializedRef.current) return;
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
|
|
51
|
+
for (var key in props.layout) {
|
|
52
|
+
mapContext.getMap(props.mapId).setLayoutProperty(layerId.current, key, props.layout[key]);
|
|
53
|
+
}
|
|
54
|
+
}, [props.layout, mapContext, props.mapId]);
|
|
55
|
+
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (!mapRef.current || !initializedRef.current) return;
|
|
48
58
|
|
|
49
59
|
for (var key in props.paint) {
|
|
50
|
-
mapContext.getMap(props.mapId).setPaintProperty(
|
|
60
|
+
mapContext.getMap(props.mapId).setPaintProperty(layerId.current, key, props.paint[key]);
|
|
51
61
|
}
|
|
52
62
|
}, [props.paint, mapContext, props.mapId]);
|
|
53
63
|
|
|
@@ -63,7 +73,8 @@ const MlGeoJsonLayer = (props) => {
|
|
|
63
73
|
msPerStep,
|
|
64
74
|
currentTransitionStepRef,
|
|
65
75
|
mapRef.current,
|
|
66
|
-
componentId.current
|
|
76
|
+
componentId.current,
|
|
77
|
+
transitionTimeoutRef
|
|
67
78
|
);
|
|
68
79
|
},
|
|
69
80
|
[props]
|
|
@@ -130,6 +141,7 @@ const MlGeoJsonLayer = (props) => {
|
|
|
130
141
|
"line-color": "rgb(100,200,100)",
|
|
131
142
|
"line-width": 10,
|
|
132
143
|
},
|
|
144
|
+
layout: props.layout || {},
|
|
133
145
|
},
|
|
134
146
|
props.insertBeforeLayer,
|
|
135
147
|
componentId.current
|
|
@@ -153,9 +165,7 @@ const MlGeoJsonLayer = (props) => {
|
|
|
153
165
|
typeof props.geojson.geometry !== "undefined"
|
|
154
166
|
) {
|
|
155
167
|
transitionToGeojson(props.geojson);
|
|
156
|
-
|
|
157
|
-
oldGeojsonRef.current = props.geojson;
|
|
158
|
-
}, props.transitionTime / 2);
|
|
168
|
+
oldGeojsonRef.current = props.geojson;
|
|
159
169
|
}
|
|
160
170
|
}
|
|
161
171
|
}, [mapContext.mapIds, mapContext, props, transitionToGeojson]);
|
|
@@ -174,8 +184,16 @@ MlGeoJsonLayer.propTypes = {
|
|
|
174
184
|
*/
|
|
175
185
|
type: PropTypes.string,
|
|
176
186
|
/**
|
|
177
|
-
*
|
|
178
|
-
* Possible
|
|
187
|
+
* Layout property object, that is passed to the addLayer call.
|
|
188
|
+
* Possible props depend on the layer type.
|
|
189
|
+
* https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#line
|
|
190
|
+
* https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#circle
|
|
191
|
+
* https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#fill
|
|
192
|
+
*/
|
|
193
|
+
layout: PropTypes.object,
|
|
194
|
+
/**
|
|
195
|
+
* Paint property object, that is passed to the addLayer call.
|
|
196
|
+
* Possible props depend on the layer type.
|
|
179
197
|
* https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#line
|
|
180
198
|
* https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#circle
|
|
181
199
|
* https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#fill
|
|
@@ -8,13 +8,14 @@ const _showNextTransitionSegment = function (
|
|
|
8
8
|
transitionGeojsonDataRef,
|
|
9
9
|
transitionGeojsonCommonDataRef,
|
|
10
10
|
currentTransitionStepRef,
|
|
11
|
-
msPerStep
|
|
11
|
+
msPerStep,
|
|
12
|
+
transitionTimeoutRef
|
|
12
13
|
) {
|
|
13
14
|
if (
|
|
14
15
|
typeof map.getSource(layerId) === "undefined" ||
|
|
15
16
|
!transitionInProgressRef.current
|
|
16
17
|
) {
|
|
17
|
-
setTimeout(() => _showNextTransitionSegment(...arguments), msPerStep);
|
|
18
|
+
transitionTimeoutRef.current = setTimeout(() => _showNextTransitionSegment(...arguments), msPerStep);
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
20
21
|
if (
|
|
@@ -31,6 +32,10 @@ const _showNextTransitionSegment = function (
|
|
|
31
32
|
.geometry.coordinates,
|
|
32
33
|
]);
|
|
33
34
|
|
|
35
|
+
if (!map?.getSource?.(layerId)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
34
39
|
map.getSource(layerId).setData(newData);
|
|
35
40
|
|
|
36
41
|
if (typeof props.onTransitionFrame === "function") {
|
|
@@ -42,7 +47,7 @@ const _showNextTransitionSegment = function (
|
|
|
42
47
|
transitionInProgressRef.current &&
|
|
43
48
|
currentTransitionStepRef.current < transitionGeojsonDataRef.current.length
|
|
44
49
|
) {
|
|
45
|
-
setTimeout(() => _showNextTransitionSegment(...arguments), msPerStep);
|
|
50
|
+
transitionTimeoutRef.current = setTimeout(() => _showNextTransitionSegment(...arguments), msPerStep);
|
|
46
51
|
} else {
|
|
47
52
|
if (typeof props.onTransitionEnd === "function") {
|
|
48
53
|
props.onTransitionEnd(props.geojson);
|
|
@@ -62,7 +67,8 @@ const _transitionToGeojson = (
|
|
|
62
67
|
msPerStep,
|
|
63
68
|
currentTransitionStepRef,
|
|
64
69
|
map,
|
|
65
|
-
layerId
|
|
70
|
+
layerId,
|
|
71
|
+
transitionTimeoutRef
|
|
66
72
|
) => {
|
|
67
73
|
// create the transition geojson between oldGeojsonRef.current and props.geojson
|
|
68
74
|
|
|
@@ -189,12 +195,12 @@ const _transitionToGeojson = (
|
|
|
189
195
|
);
|
|
190
196
|
// for some reason turf.lineChunk returns the full lineString as element 0, chunks start at 1
|
|
191
197
|
tmpLinestring = tmpChunks.features[1];
|
|
192
|
-
for (i =
|
|
198
|
+
for (i = 0; i < srcTransitionSteps; i++) {
|
|
193
199
|
transitionGeojsonDataRef.current.push(tmpLinestring);
|
|
194
|
-
if (typeof tmpChunks.features[i
|
|
200
|
+
if (typeof tmpChunks.features[i] !== "undefined") {
|
|
195
201
|
tmpLinestring = turf.lineString([
|
|
196
202
|
...tmpLinestring.geometry.coordinates,
|
|
197
|
-
...tmpChunks.features[i
|
|
203
|
+
...tmpChunks.features[i].geometry.coordinates,
|
|
198
204
|
]);
|
|
199
205
|
} else {
|
|
200
206
|
transitionGeojsonDataRef.current.push(tmpLinestring);
|
|
@@ -212,12 +218,12 @@ const _transitionToGeojson = (
|
|
|
212
218
|
);
|
|
213
219
|
// for some reason turf.lineChunk returns the full lineString as element 0, chunks start at 1
|
|
214
220
|
tmpLinestring = tmpChunks.features[1];
|
|
215
|
-
for (i =
|
|
221
|
+
for (i = 0; i < targetTransitionSteps; i++) {
|
|
216
222
|
transitionGeojsonDataRef.current.push(tmpLinestring);
|
|
217
|
-
if (typeof tmpChunks.features[i
|
|
223
|
+
if (typeof tmpChunks.features[i] !== "undefined") {
|
|
218
224
|
tmpLinestring = turf.lineString([
|
|
219
225
|
...tmpLinestring.geometry.coordinates,
|
|
220
|
-
...tmpChunks.features[i
|
|
226
|
+
...tmpChunks.features[i].geometry.coordinates,
|
|
221
227
|
]);
|
|
222
228
|
} else {
|
|
223
229
|
transitionGeojsonDataRef.current.push(tmpLinestring);
|
|
@@ -229,7 +235,7 @@ const _transitionToGeojson = (
|
|
|
229
235
|
|
|
230
236
|
currentTransitionStepRef.current = 1;
|
|
231
237
|
transitionInProgressRef.current = true;
|
|
232
|
-
setTimeout(
|
|
238
|
+
transitionTimeoutRef.current = setTimeout(
|
|
233
239
|
() =>
|
|
234
240
|
_showNextTransitionSegment(
|
|
235
241
|
props,
|
|
@@ -239,7 +245,8 @@ const _transitionToGeojson = (
|
|
|
239
245
|
transitionGeojsonDataRef,
|
|
240
246
|
transitionGeojsonCommonDataRef,
|
|
241
247
|
currentTransitionStepRef,
|
|
242
|
-
msPerStep
|
|
248
|
+
msPerStep,
|
|
249
|
+
transitionTimeoutRef
|
|
243
250
|
),
|
|
244
251
|
msPerStep
|
|
245
252
|
);
|
|
@@ -6,14 +6,12 @@ import { MapContext } from "@mapcomponents/react-core";
|
|
|
6
6
|
const MlImageMarkerLayer = (props) => {
|
|
7
7
|
// Use a useRef hook to reference the layer object to be able to access it later inside useEffect hooks
|
|
8
8
|
const mapRef = useRef(null);
|
|
9
|
-
const componentId = useRef(
|
|
10
|
-
(props.idPrefix ? props.idPrefix : "MlOsmLayer-") + uuidv4()
|
|
11
|
-
);
|
|
9
|
+
const componentId = useRef((props.idPrefix ? props.idPrefix : "MlImageMarkerLayer-") + uuidv4());
|
|
12
10
|
const mapContext = useContext(MapContext);
|
|
13
11
|
const layerInitializedRef = useRef(false);
|
|
14
12
|
const idSuffixRef = useRef(props.idSuffix || new Date().getTime());
|
|
15
13
|
const imageIdRef = useRef(props.imageId || "img_" + new Date().getTime());
|
|
16
|
-
const layerId = useRef(
|
|
14
|
+
const layerId = useRef(props.layerId || componentId.current);
|
|
17
15
|
|
|
18
16
|
useEffect(() => {
|
|
19
17
|
let _componentId = componentId.current;
|
|
@@ -82,6 +80,7 @@ const MlImageMarkerLayer = (props) => {
|
|
|
82
80
|
|
|
83
81
|
layerInitializedRef.current = true;
|
|
84
82
|
|
|
83
|
+
console.log(props.imgSrc);
|
|
85
84
|
if (props.imgSrc) {
|
|
86
85
|
mapRef.current.loadImage(props.imgSrc, function (error, image) {
|
|
87
86
|
if (error) throw error;
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { layerRemovalTest, sourceRemovalTest } from "../../util";
|
|
2
|
+
import { uuid_regex } from "../../setupTests";
|
|
2
3
|
|
|
3
4
|
import MlImageMarkerLayer from "./MlImageMarkerLayer";
|
|
4
5
|
|
|
5
|
-
const testComponent =
|
|
6
|
-
<MlImageMarkerLayer options={{ source: {} }} imgSrc="testImage" />
|
|
7
|
-
);
|
|
6
|
+
const testComponent = <MlImageMarkerLayer options={{ source: {} }} imgSrc="testImage" />;
|
|
8
7
|
|
|
9
8
|
layerRemovalTest(
|
|
10
9
|
"<MlImageMarkerLayer />",
|
|
11
10
|
testComponent,
|
|
12
|
-
|
|
13
|
-
"MlImageMarkerLayer-{
|
|
11
|
+
new RegExp('^.*"MlImageMarkerLayer-' + uuid_regex + '".*$'),
|
|
12
|
+
"MlImageMarkerLayer-{uuid}"
|
|
14
13
|
);
|
|
15
14
|
sourceRemovalTest(
|
|
16
15
|
"<MlImageMarkerLayer />",
|
|
17
16
|
testComponent,
|
|
18
|
-
|
|
19
|
-
"MlImageMarkerLayer-{
|
|
17
|
+
new RegExp('^.*"MlImageMarkerLayer-' + uuid_regex + '".*$'),
|
|
18
|
+
"MlImageMarkerLayer-{uuid}"
|
|
20
19
|
);
|
|
@@ -12,7 +12,7 @@ const MlLayer = (props) => {
|
|
|
12
12
|
(props.layerId ? props.layerId : "MlLayer-") + uuidv4()
|
|
13
13
|
);
|
|
14
14
|
const idSuffixRef = useRef(props.idSuffix || new Date().getTime());
|
|
15
|
-
const layerId = (props.layerId ||
|
|
15
|
+
const layerId = useRef(props.layerId || componentId.current);
|
|
16
16
|
const layerPaintConfRef = useRef(undefined);
|
|
17
17
|
const layerLayoutConfRef = useRef(undefined);
|
|
18
18
|
|
|
@@ -65,7 +65,7 @@ const MlLayer = (props) => {
|
|
|
65
65
|
layerInitializedRef.current = true;
|
|
66
66
|
mapRef.current.addLayer(
|
|
67
67
|
{
|
|
68
|
-
id: layerId,
|
|
68
|
+
id: layerId.current,
|
|
69
69
|
type: "background",
|
|
70
70
|
paint: {
|
|
71
71
|
"background-color": "rgba(0,0,0,0)",
|
|
@@ -5,6 +5,8 @@ import { MapContext, MapComponentsProvider } from "@mapcomponents/react-core";
|
|
|
5
5
|
import MapLibreMap from "./../MapLibreMap/MapLibreMap";
|
|
6
6
|
import MlLayer from "./MlLayer";
|
|
7
7
|
|
|
8
|
+
import { uuid_regex } from "../../setupTests";
|
|
9
|
+
|
|
8
10
|
const MlLayerTestComponent = (props) => {
|
|
9
11
|
const [layerVisible, setLayerVisible] = useState(true);
|
|
10
12
|
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
|
@@ -59,57 +61,57 @@ const createWrapper = () =>
|
|
|
59
61
|
);
|
|
60
62
|
|
|
61
63
|
describe("<MlLayer>", () => {
|
|
62
|
-
it("should add a Layer with the id 'MlLayer-{
|
|
64
|
+
it("should add a Layer with the id 'MlLayer-{uuid}' to the MapLibre instance", async () => {
|
|
63
65
|
const wrapper = createWrapper();
|
|
64
66
|
|
|
65
67
|
wrapper.find(".trigger_refresh").simulate("click");
|
|
66
68
|
|
|
67
69
|
expect(
|
|
68
|
-
|
|
70
|
+
new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".layers_json").text())
|
|
69
71
|
).toEqual(true);
|
|
70
72
|
});
|
|
71
73
|
|
|
72
|
-
it("should remove a Layer with the id 'MlLayer-{
|
|
74
|
+
it("should remove a Layer with the id 'MlLayer-{uuid}' from the MapLibre instance", async () => {
|
|
73
75
|
const wrapper = createWrapper();
|
|
74
76
|
|
|
75
77
|
wrapper.find(".trigger_refresh").simulate("click");
|
|
76
78
|
|
|
77
79
|
expect(
|
|
78
|
-
|
|
80
|
+
new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".layers_json").text())
|
|
79
81
|
).toEqual(true);
|
|
80
82
|
|
|
81
83
|
wrapper.find(".toggle_layer_visible").simulate("click");
|
|
82
84
|
wrapper.find(".trigger_refresh").simulate("click");
|
|
83
85
|
|
|
84
86
|
expect(
|
|
85
|
-
|
|
87
|
+
new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".layers_json").text())
|
|
86
88
|
).toEqual(false);
|
|
87
89
|
});
|
|
88
90
|
|
|
89
|
-
it("should add a Source with the id 'MlLayer-{
|
|
91
|
+
it("should add a Source with the id 'MlLayer-{uuid}' to the MapLibre instance", async () => {
|
|
90
92
|
const wrapper = createWrapper();
|
|
91
93
|
|
|
92
94
|
wrapper.find(".trigger_refresh").simulate("click");
|
|
93
95
|
|
|
94
96
|
expect(
|
|
95
|
-
|
|
97
|
+
new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".sources_json").text())
|
|
96
98
|
).toEqual(true);
|
|
97
99
|
});
|
|
98
100
|
|
|
99
|
-
it("should remove a Source with the id 'MlLayer-{
|
|
101
|
+
it("should remove a Source with the id 'MlLayer-{uuid}' from the MapLibre instance", async () => {
|
|
100
102
|
const wrapper = createWrapper();
|
|
101
103
|
|
|
102
104
|
wrapper.find(".trigger_refresh").simulate("click");
|
|
103
105
|
|
|
104
106
|
expect(
|
|
105
|
-
|
|
107
|
+
new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".sources_json").text())
|
|
106
108
|
).toEqual(true);
|
|
107
109
|
|
|
108
110
|
wrapper.find(".toggle_layer_visible").simulate("click");
|
|
109
111
|
wrapper.find(".trigger_refresh").simulate("click");
|
|
110
112
|
|
|
111
113
|
expect(
|
|
112
|
-
|
|
114
|
+
new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".sources_json").text())
|
|
113
115
|
).toEqual(false);
|
|
114
116
|
});
|
|
115
117
|
});
|
|
@@ -29,7 +29,7 @@ const MlLayerMagnify = (props) => {
|
|
|
29
29
|
if (!props.map1Id || !props.map2Id) {
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
32
|
-
if (!mapContext.
|
|
32
|
+
if (!mapContext.getMap(props.map1Id) || !mapContext.getMap(props.map2Id)) {
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -100,8 +100,8 @@ const MlLayerMagnify = (props) => {
|
|
|
100
100
|
|
|
101
101
|
syncMoveInitializedRef.current = true;
|
|
102
102
|
syncCleanupFunctionRef.current = syncMove(
|
|
103
|
-
mapContext.getMap(props.map1Id),
|
|
104
|
-
mapContext.getMap(props.map2Id)
|
|
103
|
+
mapContext.getMap(props.map1Id).map,
|
|
104
|
+
mapContext.getMap(props.map2Id).map
|
|
105
105
|
);
|
|
106
106
|
|
|
107
107
|
if (
|
|
@@ -22,7 +22,7 @@ const MlLayerSwipe = (props) => {
|
|
|
22
22
|
if (!props.map1Id || !props.map2Id) {
|
|
23
23
|
return false;
|
|
24
24
|
}
|
|
25
|
-
if (!mapContext.
|
|
25
|
+
if (!mapContext.getMap(props.map1Id) || !mapContext.getMap(props.map2Id)) {
|
|
26
26
|
return false;
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -53,8 +53,7 @@ const MlLayerSwipe = (props) => {
|
|
|
53
53
|
setSwipeX(swipeX_tmp);
|
|
54
54
|
swipeXRef.current = swipeX_tmp;
|
|
55
55
|
|
|
56
|
-
var clipA =
|
|
57
|
-
"rect(0, " + (swipeXRef.current * bounds.width) / 100 + "px, 999em, 0)";
|
|
56
|
+
var clipA = "rect(0, " + (swipeXRef.current * bounds.width) / 100 + "px, 999em, 0)";
|
|
58
57
|
|
|
59
58
|
mapContext.maps[props.map2Id].getContainer().style.clip = clipA;
|
|
60
59
|
}
|
|
@@ -71,8 +70,8 @@ const MlLayerSwipe = (props) => {
|
|
|
71
70
|
|
|
72
71
|
initializedRef.current = true;
|
|
73
72
|
syncCleanupFunctionRef.current = syncMove(
|
|
74
|
-
mapContext.getMap(props.map1Id),
|
|
75
|
-
mapContext.getMap(props.map2Id)
|
|
73
|
+
mapContext.getMap(props.map1Id).map,
|
|
74
|
+
mapContext.getMap(props.map2Id).map
|
|
76
75
|
);
|
|
77
76
|
onMove({ clientX: mapContext.maps[props.map1Id].getCanvas().clientWidth / 2 });
|
|
78
77
|
}, [mapContext.mapIds, mapContext, props, onMove, mapExists]);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.mllayerswitcher-layer-box.activeHighlight > .mllayerswitcher-layer-image {
|
|
2
|
+
border-color: rgb(181, 215, 238);
|
|
3
|
+
border-radius: 8px;
|
|
4
|
+
}
|
|
5
|
+
.mllayerswitcher-layer-box.activeHighlight > .mllayerswitcher-layer-text {
|
|
6
|
+
color: rgb(181, 215, 238) !important;
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.mllayerswitcher-layer-box.active > .mllayerswitcher-layer-image {
|
|
11
|
+
border-color: rgb(196, 240, 0);
|
|
12
|
+
border-radius: 8px;
|
|
13
|
+
}
|
|
14
|
+
.mllayerswitcher-layer-box.active > .mllayerswitcher-layer-text {
|
|
15
|
+
color: rgb(252, 0, 0) !important;
|
|
16
|
+
|
|
17
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
//CSS
|
|
2
|
+
import "@fontsource/roboto/300.css";
|
|
3
|
+
import "@fontsource/roboto/400.css";
|
|
4
|
+
import "@fontsource/roboto/500.css";
|
|
5
|
+
import { css, cx } from '@emotion/css'
|
|
6
|
+
import "./MlLayerSwitcher.css";
|
|
7
|
+
//External
|
|
8
|
+
import { useEffect, useContext, useState } from "react";
|
|
9
|
+
import PropTypes from "prop-types";
|
|
10
|
+
import { useTranslation } from "react-i18next";
|
|
11
|
+
import { Card, CardContent, Typography, Box } from "@mui/material";
|
|
12
|
+
//Internal
|
|
13
|
+
import { MapContext } from "@mapcomponents/react-core";
|
|
14
|
+
import LayerBox from "./components/LayerBox";
|
|
15
|
+
import Divider from "@mui/material/Divider";
|
|
16
|
+
import useMapState from "../../hooks/useMapState";
|
|
17
|
+
import LoadingOverlay from "../../ui_components/LoadingOverlay";
|
|
18
|
+
/**
|
|
19
|
+
* @component
|
|
20
|
+
*
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
const MlLayerSwitcher = (props) => {
|
|
24
|
+
const mapContext = useContext(MapContext);
|
|
25
|
+
const showBaseSources = !!props.baseSourceConfig?.layers?.length;
|
|
26
|
+
const showDetailLayer = !!props.detailLayerConfig?.layers?.length;
|
|
27
|
+
const { layers } = useMapState({
|
|
28
|
+
mapId: props.mapId,
|
|
29
|
+
watch: {
|
|
30
|
+
viewport: false,
|
|
31
|
+
layers: true,
|
|
32
|
+
sources: false,
|
|
33
|
+
},
|
|
34
|
+
filter: {},
|
|
35
|
+
});
|
|
36
|
+
const [activeLayers, setActiveLayers] = useState([]);
|
|
37
|
+
const [activeDetailLayers, setActiveDetailLayers] = useState([]);
|
|
38
|
+
const { t } = useTranslation();
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
//Set base state to activate only the first layer
|
|
42
|
+
if (mapContext.map) {
|
|
43
|
+
const disableAllButFirst = (config, i) => {
|
|
44
|
+
const layers = getLayerListFromId(config.layerId);
|
|
45
|
+
const visible = i === 0 ? "visible" : "none";
|
|
46
|
+
|
|
47
|
+
layers.forEach((layer) => {
|
|
48
|
+
if (layer) {
|
|
49
|
+
changeLayerState(layer, visible);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
props.baseSourceConfig.layers.forEach((config, i) => disableAllButFirst(config, i));
|
|
55
|
+
props.detailLayerConfig.layers.forEach((config, i) => disableAllButFirst(config, i));
|
|
56
|
+
}
|
|
57
|
+
return () => {
|
|
58
|
+
// This is the cleanup function, it is called when this react component is removed from react-dom
|
|
59
|
+
// try to remove anything this component has added to the MapLibre-gl instance
|
|
60
|
+
// e.g.: remove the layer
|
|
61
|
+
// mapContext.getMap(props.mapId).removeLayer(layerRef.current);
|
|
62
|
+
// check for the existence of map.style before calling getLayer or getSource
|
|
63
|
+
};
|
|
64
|
+
}, [mapContext.map]);
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (mapContext.map?.style?._layers) {
|
|
68
|
+
let newactiveLayers = [];
|
|
69
|
+
let newactiveDetailLayers = [];
|
|
70
|
+
props.baseSourceConfig.layers.forEach((layerConfig) => {
|
|
71
|
+
const layers = getLayerListFromId(layerConfig.layerId);
|
|
72
|
+
|
|
73
|
+
layers.forEach((layer) => {
|
|
74
|
+
const visibilty = mapContext.map?.getLayoutProperty(layer, "visibility");
|
|
75
|
+
if (mapContext.map.baseLayers.indexOf(layer) !== -1) {
|
|
76
|
+
layer = "styleBase";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (newactiveLayers.indexOf(layer) === -1 && visibilty === "visible") {
|
|
80
|
+
newactiveLayers.push(layer);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
props.detailLayerConfig.layers.forEach(({ layerId }) => {
|
|
85
|
+
const visibilty = mapContext.map?.getLayoutProperty(layerId, "visibility");
|
|
86
|
+
if (newactiveDetailLayers.indexOf(layerId) === -1 && visibilty === "visible") {
|
|
87
|
+
newactiveDetailLayers.push(layerId);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
setActiveLayers(newactiveLayers);
|
|
91
|
+
|
|
92
|
+
setActiveDetailLayers(newactiveDetailLayers);
|
|
93
|
+
}
|
|
94
|
+
}, [layers]);
|
|
95
|
+
|
|
96
|
+
const getLayerListFromId = (id) => {
|
|
97
|
+
return id === "styleBase" ? mapContext?.map.baseLayers : [id];
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const handleDetailLayerBoxClick = (layerId) => {
|
|
101
|
+
const cfg = props.detailLayerConfig.layers.find((e) => e.layerId === layerId);
|
|
102
|
+
if (cfg.linkedTo) {
|
|
103
|
+
handleLayerBoxClick(cfg.linkedTo);
|
|
104
|
+
}
|
|
105
|
+
const nextVisiblityClickedLayer =
|
|
106
|
+
mapContext?.map.getLayer(layerId)?.getLayoutProperty("visibility") === "visible"
|
|
107
|
+
? "none"
|
|
108
|
+
: "visible";
|
|
109
|
+
changeLayerState(layerId, nextVisiblityClickedLayer);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const handleLayerBoxClick = (id) => {
|
|
113
|
+
let layers = getLayerListFromId(id);
|
|
114
|
+
const nextVisiblityClickedLayer =
|
|
115
|
+
mapContext?.map.getLayer(layers[0])?.getLayoutProperty("visibility") === "visible"
|
|
116
|
+
? "none"
|
|
117
|
+
: "visible";
|
|
118
|
+
|
|
119
|
+
props.baseSourceConfig.layers.forEach((config, i) => {
|
|
120
|
+
let layers = getLayerListFromId(config.layerId);
|
|
121
|
+
let visible = "none";
|
|
122
|
+
if (config.layerId === id) {
|
|
123
|
+
visible = nextVisiblityClickedLayer;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//To avoid disabling all base layers we activate the first one
|
|
127
|
+
if (nextVisiblityClickedLayer === "none" && i === 0) {
|
|
128
|
+
visible = "visible";
|
|
129
|
+
}
|
|
130
|
+
layers.forEach((layer) => {
|
|
131
|
+
if (layer) {
|
|
132
|
+
changeLayerState(layer, visible);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const changeLayerState = (layer, visible = "none") => {
|
|
139
|
+
mapContext.map?.setLayoutProperty(layer, "visibility", visible);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<>
|
|
144
|
+
<Card sx={{ zIndex: 101, position: "absolute", minWidth: "200px" }}>
|
|
145
|
+
<CardContent>
|
|
146
|
+
{showBaseSources && (
|
|
147
|
+
<Box sx={{ minHeight: "150px" }}>
|
|
148
|
+
<Typography variant="h6">{t(props.baseSourceConfig.label || "Map type")}</Typography>
|
|
149
|
+
<Divider />
|
|
150
|
+
<Box sx={{ display: "flex", paddingTop: "1rem" }}>
|
|
151
|
+
{props.baseSourceConfig.layers.map(({ src, label, layerId }) => {
|
|
152
|
+
return (
|
|
153
|
+
<LayerBox
|
|
154
|
+
mapId={props.mapId}
|
|
155
|
+
key={layerId}
|
|
156
|
+
activeLayers={activeLayers}
|
|
157
|
+
label={t(label)}
|
|
158
|
+
layerId={layerId}
|
|
159
|
+
thumbnail={src}
|
|
160
|
+
handleLayerBoxClick={() => {
|
|
161
|
+
handleLayerBoxClick(layerId);
|
|
162
|
+
}}
|
|
163
|
+
/>
|
|
164
|
+
);
|
|
165
|
+
})}
|
|
166
|
+
</Box>
|
|
167
|
+
</Box>
|
|
168
|
+
)}
|
|
169
|
+
{showDetailLayer && (
|
|
170
|
+
<Box sx={{ minHeight: "150px" }}>
|
|
171
|
+
<Typography variant="h6">{t("Map details")}</Typography>
|
|
172
|
+
<Divider />
|
|
173
|
+
<Box sx={{ display: "flex", paddingTop: "1rem" }}>
|
|
174
|
+
{props.detailLayerConfig.layers.map(({ src, label, layerId }) => {
|
|
175
|
+
return (
|
|
176
|
+
<LayerBox
|
|
177
|
+
mapId={props.mapId}
|
|
178
|
+
activeLayers={activeDetailLayers}
|
|
179
|
+
label={t(label)}
|
|
180
|
+
layerId={layerId}
|
|
181
|
+
key={layerId}
|
|
182
|
+
thumbnail={src}
|
|
183
|
+
handleLayerBoxClick={() => {
|
|
184
|
+
handleDetailLayerBoxClick(layerId);
|
|
185
|
+
}}
|
|
186
|
+
/>
|
|
187
|
+
);
|
|
188
|
+
})}
|
|
189
|
+
</Box>
|
|
190
|
+
</Box>
|
|
191
|
+
)}
|
|
192
|
+
</CardContent>{" "}
|
|
193
|
+
</Card>
|
|
194
|
+
</>
|
|
195
|
+
);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
MlLayerSwitcher.propTypes = {
|
|
199
|
+
baseSourceConfig: PropTypes.shape({
|
|
200
|
+
label: PropTypes.string,
|
|
201
|
+
layers: PropTypes.arrayOf(
|
|
202
|
+
PropTypes.shape({
|
|
203
|
+
layerId: PropTypes.string.isRequired,
|
|
204
|
+
src: PropTypes.string,
|
|
205
|
+
label: PropTypes.string.isRequired,
|
|
206
|
+
})
|
|
207
|
+
),
|
|
208
|
+
}),
|
|
209
|
+
detailLayerConfig: PropTypes.shape({
|
|
210
|
+
label: PropTypes.string,
|
|
211
|
+
layers: PropTypes.arrayOf(
|
|
212
|
+
PropTypes.shape({
|
|
213
|
+
layerId: PropTypes.string.isRequired,
|
|
214
|
+
src: PropTypes.string,
|
|
215
|
+
label: PropTypes.string.isRequired,
|
|
216
|
+
linkedTo: PropTypes.string,
|
|
217
|
+
})
|
|
218
|
+
),
|
|
219
|
+
}),
|
|
220
|
+
mapId: PropTypes.string,
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export default MlLayerSwitcher;
|