@mapcomponents/react-maplibre 0.1.59 → 0.1.61
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/.eslintignore +2 -1
- package/CHANGELOG.md +15 -0
- package/coverage/clover.xml +142 -47
- package/coverage/coverage-final.json +5 -4
- package/coverage/lcov-report/index.html +36 -21
- package/coverage/lcov-report/src/components/MapLibreMap/MapLibreMap.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MapLibreMap/index.html +1 -1
- package/coverage/lcov-report/src/components/MlCenterPosition/MlCenterPosition.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlCenterPosition/index.html +1 -1
- package/coverage/lcov-report/src/components/MlCreatePdfButton/MlCreatePdfButton.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlCreatePdfButton/index.html +1 -1
- package/coverage/lcov-report/src/components/MlCreatePdfForm/MlCreatePdfForm.tsx.html +2 -2
- package/coverage/lcov-report/src/components/MlCreatePdfForm/index.html +1 -1
- package/coverage/lcov-report/src/components/MlFeatureEditor/MlFeatureEditor.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlFeatureEditor/index.html +1 -1
- package/coverage/lcov-report/src/components/MlFillExtrusionLayer/MlFillExtrusionLayer.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlFillExtrusionLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlFollowGps/MlFollowGps.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlFollowGps/index.html +1 -1
- package/coverage/lcov-report/src/components/MlGPXViewer/MlGPXViewer.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlGPXViewer/gpxConverter.js.html +1 -1
- package/coverage/lcov-report/src/components/MlGPXViewer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlGeoJsonLayer/MlGeoJsonLayer.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlGeoJsonLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlGeojsonLayerWithSource/MlGeojsonLayerWithSource.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlGeojsonLayerWithSource/index.html +1 -1
- package/coverage/lcov-report/src/components/MlImageMarkerLayer/MlImageMarkerLayer.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlImageMarkerLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayer/MlLayer.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerMagnify/MlLayerMagnify.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerMagnify/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerSwipe/MlLayerSwipe.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerSwipe/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerSwitcher/MlLayerSwitcher.js.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerSwitcher/components/LayerBox.js.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerSwitcher/components/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerSwitcher/index.html +1 -1
- package/coverage/lcov-report/src/components/MlMarker/MlMarker.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlMarker/index.html +1 -1
- package/coverage/lcov-report/src/components/MlMeasureTool/MlMeasureTool.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlMeasureTool/index.html +1 -1
- package/coverage/lcov-report/src/components/MlNavigationCompass/MlNavigationCompass.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlNavigationCompass/index.html +1 -1
- package/coverage/lcov-report/src/components/MlNavigationTools/MlNavigationTools.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlNavigationTools/index.html +1 -1
- package/coverage/lcov-report/src/components/MlOsmLayer/MlOsmLayer.js.html +1 -1
- package/coverage/lcov-report/src/components/MlOsmLayer/MlOsmLayer.stories_.js.html +1 -1
- package/coverage/lcov-report/src/components/MlOsmLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlScaleReference/MlScaleReference.js.html +1 -1
- package/coverage/lcov-report/src/components/MlScaleReference/index.html +1 -1
- package/coverage/lcov-report/src/components/MlShareMapState/MlShareMapState.js.html +1 -1
- package/coverage/lcov-report/src/components/MlShareMapState/index.html +1 -1
- package/coverage/lcov-report/src/components/MlSpatialElevationProfile/MlSpatialElevationProfile.js.html +1 -1
- package/coverage/lcov-report/src/components/MlSpatialElevationProfile/index.html +1 -1
- package/coverage/lcov-report/src/components/MlThreeJsLayer/MlThreeJsLayer.js.html +1 -1
- package/coverage/lcov-report/src/components/MlThreeJsLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlTransitionGeoJsonLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlUseMapDebugger/MlUseMapDebugger.js.html +1 -1
- package/coverage/lcov-report/src/components/MlUseMapDebugger/index.html +1 -1
- package/coverage/lcov-report/src/components/MlVectorTileLayer/MlVectorTileLayer.tsx.html +92 -146
- package/coverage/lcov-report/src/components/MlVectorTileLayer/index.html +21 -21
- package/coverage/lcov-report/src/components/MlWmsFeatureInfoPopup/MlWmsFeatureInfoPopup.js.html +1 -1
- package/coverage/lcov-report/src/components/MlWmsFeatureInfoPopup/index.html +1 -1
- package/coverage/lcov-report/src/components/MlWmsLayer/MlWmsLayer.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlWmsLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlWmsLoader/MlWmsLoader.tsx.html +1 -1
- package/coverage/lcov-report/src/components/MlWmsLoader/index.html +1 -1
- package/coverage/lcov-report/src/contexts/MapContext.tsx.html +1 -1
- package/coverage/lcov-report/src/contexts/SimpleDataContext.js.html +1 -1
- package/coverage/lcov-report/src/contexts/SimpleDataProvider.js.html +1 -1
- package/coverage/lcov-report/src/contexts/index.html +1 -1
- package/coverage/lcov-report/src/hooks/index.html +1 -1
- package/coverage/lcov-report/src/hooks/useCameraFollowPath/index.html +116 -0
- package/coverage/lcov-report/src/hooks/useCameraFollowPath/useCameraFollowPath.tsx.html +661 -0
- package/coverage/lcov-report/src/hooks/{exportMap → useExportMap}/index.html +3 -3
- package/coverage/lcov-report/src/hooks/{exportMap → useExportMap}/index.ts.html +4 -4
- package/coverage/lcov-report/src/hooks/{exportMap → useExportMap}/lib.ts.html +4 -4
- package/coverage/lcov-report/src/hooks/useLayer.ts.html +1 -1
- package/coverage/lcov-report/src/hooks/useLayerEvent.js.html +1 -1
- package/coverage/lcov-report/src/hooks/useMap.ts.html +4 -4
- package/coverage/lcov-report/src/hooks/useMapState.ts.html +1 -1
- package/coverage/lcov-report/src/hooks/useSource.ts.html +1 -1
- package/coverage/lcov-report/src/hooks/useWms.js.html +1 -1
- package/coverage/lcov-report/src/index.html +1 -1
- package/coverage/lcov-report/src/index.ts.html +6 -3
- package/coverage/lcov.info +270 -76
- package/dist/components/MlCreatePdfForm/MlCreatePdfForm.d.ts +1 -1
- package/dist/components/MlCreatePdfForm/lib/PdfForm.d.ts +1 -1
- package/dist/components/MlVectorTileLayer/MlVectorTileLayer.d.ts +5 -24
- package/dist/hooks/useCameraFollowPath/useCameraFollowPath.d.ts +35 -0
- package/dist/hooks/useCameraFollowPath/useCameraFollowPath.stories.d.ts +17 -0
- package/dist/hooks/useExportMap/index.d.ts +11 -0
- package/dist/hooks/useExportMap/lib.d.ts +36 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +209 -63
- package/dist/index.esm.js.map +1 -1
- package/package.json +2 -1
- package/scripts/build-catalogue-meta.js +1 -1
- package/src/components/MlCreatePdfForm/MlCreatePdfForm.tsx +1 -1
- package/src/components/MlCreatePdfForm/lib/PdfForm.tsx +5 -5
- package/src/components/MlVectorTileLayer/MlVectorTileLayer.stories.js +15 -9
- package/src/components/MlVectorTileLayer/MlVectorTileLayer.test.js +7 -6
- package/src/components/MlVectorTileLayer/MlVectorTileLayer.tsx +59 -77
- package/src/hooks/useCameraFollowPath/useCameraFollowPath.doc.de.md +4 -0
- package/src/hooks/useCameraFollowPath/useCameraFollowPath.doc.en.md +1 -0
- package/src/hooks/useCameraFollowPath/useCameraFollowPath.meta.json +15 -0
- package/src/hooks/useCameraFollowPath/useCameraFollowPath.stories.tsx +198 -0
- package/src/hooks/useCameraFollowPath/useCameraFollowPath.tsx +192 -0
- package/src/hooks/{exportMap → useExportMap}/index.ts +1 -1
- package/src/hooks/{exportMap → useExportMap}/lib.ts +1 -1
- package/src/index.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mapcomponents/react-maplibre",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.61",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"@mui/styles": "^5.5.3",
|
|
30
30
|
"@turf/turf": "^6.5.0",
|
|
31
31
|
"d3": "^7.4.4",
|
|
32
|
+
"deck.gl": "^8.8.13",
|
|
32
33
|
"jspdf": "^2.5.1",
|
|
33
34
|
"maplibre-gl": "^2.1.7",
|
|
34
35
|
"react-i18next": "^11.14.3",
|
|
@@ -4,7 +4,7 @@ const fs = require("fs");
|
|
|
4
4
|
let options = {};
|
|
5
5
|
let mc_meta = {};
|
|
6
6
|
|
|
7
|
-
glob("src
|
|
7
|
+
glob("src/**/**/*.meta.json", options, function (er, files) {
|
|
8
8
|
console.log(files);
|
|
9
9
|
|
|
10
10
|
for (var i = 0, len = files.length; i < len; i++) {
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import PdfPreview from './lib/PdfPreview';
|
|
3
3
|
import PdfForm from './lib/PdfForm';
|
|
4
4
|
import { PdfContextProvider } from './lib/PdfContext';
|
|
5
|
-
import { createPdfResolverParams } from '../../hooks/
|
|
5
|
+
import { createPdfResolverParams } from '../../hooks/useExportMap/lib';
|
|
6
6
|
import { SxProps } from '@mui/material';
|
|
7
7
|
|
|
8
8
|
interface MlCreatePdfFormProps {
|
|
@@ -13,8 +13,8 @@ import {
|
|
|
13
13
|
} from '@mui/material';
|
|
14
14
|
|
|
15
15
|
import useMap from '../../../hooks/useMap';
|
|
16
|
-
import
|
|
17
|
-
import { createPdfResolverParams } from '../../../hooks/
|
|
16
|
+
import useExportMap from '../../../hooks/useExportMap';
|
|
17
|
+
import { createPdfResolverParams } from '../../../hooks/useExportMap/lib';
|
|
18
18
|
|
|
19
19
|
import * as turf from '@turf/turf';
|
|
20
20
|
|
|
@@ -40,16 +40,16 @@ interface PdfFormProps {
|
|
|
40
40
|
* Id of the target MapLibre instance in mapContext
|
|
41
41
|
*/
|
|
42
42
|
mapId?: string;
|
|
43
|
-
onCreatePdf?: (options:createPdfResolverParams) => createPdfResolverParams;
|
|
43
|
+
onCreatePdf?: (options: createPdfResolverParams) => createPdfResolverParams;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export default function PdfForm(props:PdfFormProps) {
|
|
46
|
+
export default function PdfForm(props: PdfFormProps) {
|
|
47
47
|
const pdfContext = useContext(PdfContext);
|
|
48
48
|
const mapHook = useMap({
|
|
49
49
|
// eslint-disable-next-line react/prop-types
|
|
50
50
|
mapId: props.mapId,
|
|
51
51
|
});
|
|
52
|
-
const mapExporter =
|
|
52
|
+
const mapExporter = useExportMap({ mapId: props.mapId });
|
|
53
53
|
|
|
54
54
|
const createPdfHandler = useCallback(() => {
|
|
55
55
|
if (
|
|
@@ -28,16 +28,22 @@ ExampleConfig.args = {
|
|
|
28
28
|
mapId: "map_1",
|
|
29
29
|
url:
|
|
30
30
|
"https://wms.wheregroup.com/tileserver/tile/tileserver.php?/europe-0-14/index.json?/europe-0-14/{z}/{x}/{y}.pbf",
|
|
31
|
-
layers:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
},
|
|
38
|
-
paint: { "line-width": 2, "line-color": "#ff0000" },
|
|
31
|
+
layers: [
|
|
32
|
+
{
|
|
33
|
+
id: "water",
|
|
34
|
+
type: "fill",
|
|
35
|
+
"source-layer": "water",
|
|
36
|
+
layout: {},
|
|
37
|
+
paint: { "fill-color": "#0905f5", "fill-opacity": 0.5 },
|
|
39
38
|
},
|
|
40
|
-
|
|
39
|
+
{
|
|
40
|
+
id: "buildings",
|
|
41
|
+
type: "fill",
|
|
42
|
+
"source-layer": "building",
|
|
43
|
+
layout: {},
|
|
44
|
+
paint: { "fill-color": "#717875" },
|
|
45
|
+
},
|
|
46
|
+
],
|
|
41
47
|
sourceOptions: {
|
|
42
48
|
minzoom: 0,
|
|
43
49
|
maxzoom: 20,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { layerRemovalTest, sourceRemovalTest } from "../../util";
|
|
2
|
-
|
|
2
|
+
import React from 'react'
|
|
3
3
|
import MlVectorTileLayer from "./MlVectorTileLayer";
|
|
4
4
|
import { uuid_regex } from "../../setupTests";
|
|
5
5
|
|
|
@@ -7,8 +7,9 @@ const testComponent = (
|
|
|
7
7
|
<MlVectorTileLayer
|
|
8
8
|
{...{
|
|
9
9
|
url: "https://wms.wheregroup.com/tileserver/tile/tileserver.php?/europe-0-14/index.json?/europe-0-14/{z}/{x}/{y}.pbf",
|
|
10
|
-
layers:
|
|
11
|
-
|
|
10
|
+
layers: [
|
|
11
|
+
{
|
|
12
|
+
id: "landuseLine",
|
|
12
13
|
"source-layer": "landuse",
|
|
13
14
|
layout: {
|
|
14
15
|
"line-cap": "round",
|
|
@@ -16,7 +17,7 @@ const testComponent = (
|
|
|
16
17
|
},
|
|
17
18
|
paint: { "line-width": 1, "line-color": "#ff0000" },
|
|
18
19
|
},
|
|
19
|
-
|
|
20
|
+
],
|
|
20
21
|
sourceOptions: {
|
|
21
22
|
minzoom: 0,
|
|
22
23
|
maxzoom: 20,
|
|
@@ -28,8 +29,8 @@ const testComponent = (
|
|
|
28
29
|
layerRemovalTest(
|
|
29
30
|
"<MlVectorTileLayer />",
|
|
30
31
|
testComponent,
|
|
31
|
-
new RegExp('^.*"
|
|
32
|
-
|
|
32
|
+
new RegExp('^.*"landuseLine".*$'),
|
|
33
|
+
'landuseLine'
|
|
33
34
|
);
|
|
34
35
|
sourceRemovalTest(
|
|
35
36
|
"<MlVectorTileLayer />",
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import React, { useRef, useEffect, useCallback } from "react";
|
|
2
|
-
import useMap from
|
|
3
|
-
import
|
|
2
|
+
import useMap from '../../hooks/useMap';
|
|
3
|
+
import { LayerSpecification } from 'maplibre-gl';
|
|
4
|
+
import { VectorSourceSpecification } from 'maplibre-gl';
|
|
4
5
|
|
|
5
6
|
interface MlVectorTileLayerProps {
|
|
6
7
|
mapId?: string;
|
|
7
8
|
insertBeforeLayer?: string;
|
|
8
9
|
layerId?: string;
|
|
9
|
-
sourceOptions?:
|
|
10
|
+
sourceOptions?: VectorSourceSpecification;
|
|
10
11
|
url?: string;
|
|
11
|
-
layers
|
|
12
|
+
layers: LayerSpecification[];
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -23,135 +24,116 @@ const MlVectorTileLayer = (props: MlVectorTileLayerProps) => {
|
|
|
23
24
|
waitForLayer: props.insertBeforeLayer,
|
|
24
25
|
});
|
|
25
26
|
|
|
26
|
-
const
|
|
27
|
-
const layerId = useRef(props.layerId || "MlVectorTileLayer-" + mapHook.componentId);
|
|
27
|
+
const layerId = useRef(props.layerId || 'MlVectorTileLayer-' + mapHook.componentId);
|
|
28
28
|
const layerPaintConfsRef = useRef({});
|
|
29
29
|
const layerLayoutConfsRef = useRef({});
|
|
30
30
|
const initializedRef = useRef(false);
|
|
31
31
|
|
|
32
|
-
const
|
|
32
|
+
const createLayers = useCallback(() => {
|
|
33
33
|
if (!mapHook.map) return;
|
|
34
34
|
|
|
35
35
|
initializedRef.current = true;
|
|
36
36
|
|
|
37
|
-
if (mapHook.map.map.
|
|
37
|
+
if (mapHook.map.map.getSource(layerId.current)) {
|
|
38
38
|
mapHook.cleanup();
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
// Add the new layer to the
|
|
41
|
+
// Add the new layer to the maplibre instance once it is available
|
|
42
42
|
mapHook.map.addSource(
|
|
43
43
|
layerId.current,
|
|
44
44
|
{
|
|
45
|
-
type:
|
|
45
|
+
type: 'vector',
|
|
46
46
|
tiles: [props.url],
|
|
47
47
|
tileSize: 512,
|
|
48
|
-
attribution:
|
|
48
|
+
attribution: '',
|
|
49
49
|
...props.sourceOptions,
|
|
50
50
|
},
|
|
51
51
|
mapHook.componentId
|
|
52
52
|
);
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
layerIdsRef.current[key] = _layerId;
|
|
57
|
-
|
|
54
|
+
props.layers.forEach((layer) => {
|
|
55
|
+
if (!mapHook.map) return;
|
|
58
56
|
mapHook.map.addLayer(
|
|
59
57
|
{
|
|
60
|
-
id: _layerId,
|
|
61
58
|
source: layerId.current,
|
|
62
|
-
type: "line",
|
|
63
59
|
minzoom: 0,
|
|
64
60
|
maxzoom: 22,
|
|
65
61
|
layout: {},
|
|
66
62
|
paint: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
'line-opacity': 0.5,
|
|
64
|
+
'line-color': 'rgb(80, 80, 80)',
|
|
65
|
+
'line-width': 2,
|
|
70
66
|
},
|
|
71
|
-
...
|
|
67
|
+
...layer,
|
|
72
68
|
},
|
|
73
69
|
props.insertBeforeLayer,
|
|
74
70
|
mapHook.componentId
|
|
75
71
|
);
|
|
76
|
-
layerPaintConfsRef.current[
|
|
77
|
-
layerLayoutConfsRef.current[
|
|
72
|
+
layerPaintConfsRef.current[layer.id] = JSON.stringify(layer.paint);
|
|
73
|
+
layerLayoutConfsRef.current[layer.id] = JSON.stringify(layer.layout);
|
|
78
74
|
|
|
79
75
|
// recreate layer if style has changed
|
|
80
76
|
mapHook.map.on(
|
|
81
|
-
|
|
77
|
+
'styledata',
|
|
82
78
|
() => {
|
|
83
79
|
if (initializedRef.current && !mapHook.map?.map.getSource(layerId.current)) {
|
|
84
|
-
console.log(
|
|
85
|
-
|
|
80
|
+
console.log('Recreate Layer ' + layerId.current);
|
|
81
|
+
createLayers();
|
|
86
82
|
}
|
|
87
83
|
},
|
|
88
84
|
mapHook.componentId
|
|
89
85
|
);
|
|
90
|
-
}
|
|
86
|
+
});
|
|
91
87
|
}, [mapHook.map, props]);
|
|
92
88
|
|
|
93
|
-
|
|
94
|
-
if (initializedRef.current) return;
|
|
95
|
-
|
|
96
|
-
createLayer();
|
|
97
|
-
}, [createLayer]);
|
|
89
|
+
const updateLayers = useCallback(() => {
|
|
90
|
+
if (!initializedRef.current) return;
|
|
98
91
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
for (var key in props.layers) {
|
|
103
|
-
if (mapHook.map.map.getLayer(layerIdsRef.current[key])) {
|
|
92
|
+
props.layers.forEach((layer) => {
|
|
93
|
+
if (!mapHook.map) return;
|
|
94
|
+
if (mapHook.map.map.getLayer(layer.id)) {
|
|
104
95
|
// update changed paint property
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (layerPaintConfString !== layerPaintConfsRef.current[
|
|
108
|
-
for (
|
|
109
|
-
mapHook.map.map.setPaintProperty(
|
|
110
|
-
layerIdsRef.current[key],
|
|
111
|
-
paintKey,
|
|
112
|
-
props.layers[key].paint[paintKey]
|
|
113
|
-
);
|
|
96
|
+
const layerPaintConfString = JSON.stringify(layer.paint);
|
|
97
|
+
|
|
98
|
+
if (layerPaintConfString !== layerPaintConfsRef.current[layer.id]) {
|
|
99
|
+
for (const paintKey in layer.paint) {
|
|
100
|
+
mapHook.map.map.setPaintProperty(layer.id, paintKey, layer.paint[paintKey]);
|
|
114
101
|
}
|
|
115
102
|
}
|
|
116
|
-
layerPaintConfsRef.current[
|
|
103
|
+
layerPaintConfsRef.current[layer.id] = layerPaintConfString;
|
|
117
104
|
|
|
118
105
|
// update changed layout property
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (layerLayoutConfString !== layerLayoutConfsRef.current[
|
|
122
|
-
for (
|
|
123
|
-
mapHook.map.map.setLayoutProperty(
|
|
124
|
-
layerIdsRef.current[key],
|
|
125
|
-
layoutKey,
|
|
126
|
-
props.layers[key].layout[layoutKey]
|
|
127
|
-
);
|
|
106
|
+
const layerLayoutConfString = JSON.stringify(layer.layout);
|
|
107
|
+
|
|
108
|
+
if (layerLayoutConfString !== layerLayoutConfsRef.current[layer.id]) {
|
|
109
|
+
for (const layoutKey in layer.layout) {
|
|
110
|
+
mapHook.map.map.setLayoutProperty(layer.id, layoutKey, layer.layout[layoutKey]);
|
|
128
111
|
}
|
|
129
112
|
}
|
|
130
|
-
layerLayoutConfsRef.current[
|
|
113
|
+
layerLayoutConfsRef.current[layer.id] = layerLayoutConfString;
|
|
131
114
|
}
|
|
132
|
-
}
|
|
115
|
+
});
|
|
116
|
+
}, [mapHook.map, props.layers]);
|
|
117
|
+
|
|
118
|
+
// initial layer creation
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (initializedRef.current) return;
|
|
121
|
+
createLayers();
|
|
122
|
+
}, [createLayers]);
|
|
123
|
+
|
|
124
|
+
// if layers get removed or added
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (!mapHook.map || !initializedRef.current) return;
|
|
127
|
+
createLayers();
|
|
128
|
+
}, [props.layers.length, mapHook.map]);
|
|
129
|
+
|
|
130
|
+
// on layout/paint update
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
if (!mapHook.map || !initializedRef.current) return;
|
|
133
|
+
updateLayers();
|
|
133
134
|
}, [props.layers, mapHook.map]);
|
|
134
135
|
|
|
135
136
|
return <></>;
|
|
136
137
|
};
|
|
137
138
|
|
|
138
|
-
MlVectorTileLayer.propTypes = {
|
|
139
|
-
/**
|
|
140
|
-
* Id of the target MapLibre instance in mapContext
|
|
141
|
-
*/
|
|
142
|
-
mapId: PropTypes.string,
|
|
143
|
-
/**
|
|
144
|
-
* Options object that will be used as first parameter on the MapLibreGl.addSource call see MapLibre source options documentation.
|
|
145
|
-
*/
|
|
146
|
-
sourceOptions: PropTypes.object,
|
|
147
|
-
/**
|
|
148
|
-
* Object that hold layers
|
|
149
|
-
*/
|
|
150
|
-
layers: PropTypes.object,
|
|
151
|
-
/**
|
|
152
|
-
* String of the URL of a wms layer
|
|
153
|
-
*/
|
|
154
|
-
url: PropTypes.string,
|
|
155
|
-
};
|
|
156
|
-
|
|
157
139
|
export default MlVectorTileLayer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This Component accepts an array consisting of coordinates and travels this route with the camera. Options for speed, initial zoom level and final zoom level are also available.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "useCameraFollowPath",
|
|
3
|
+
"title": "Move camera along linestring",
|
|
4
|
+
"description": "",
|
|
5
|
+
"i18n": {
|
|
6
|
+
"de": {
|
|
7
|
+
"title": "Kamerafahrt entlang eines Linestrings",
|
|
8
|
+
"description": ""
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"tags": [],
|
|
12
|
+
"category": "",
|
|
13
|
+
"type": "component",
|
|
14
|
+
"price": 1000
|
|
15
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import useCameraFollowPath from './useCameraFollowPath';
|
|
3
|
+
import TopToolbar from '../../ui_components/TopToolbar';
|
|
4
|
+
import mapContextDecorator from '../../decorators/MapContextDecorator';
|
|
5
|
+
import { Button, Slider, Typography } from '@mui/material';
|
|
6
|
+
import MlGeoJsonLayer from '../../components/MlGeoJsonLayer/MlGeoJsonLayer';
|
|
7
|
+
import { Feature } from '@turf/turf';
|
|
8
|
+
|
|
9
|
+
const storyoptions = {
|
|
10
|
+
title: 'Hooks/useCameraFollowPath',
|
|
11
|
+
component: useCameraFollowPath,
|
|
12
|
+
argTypes: {},
|
|
13
|
+
decorators: mapContextDecorator,
|
|
14
|
+
};
|
|
15
|
+
export default storyoptions;
|
|
16
|
+
|
|
17
|
+
const routeJson: Feature = {
|
|
18
|
+
type: 'Feature',
|
|
19
|
+
properties: {},
|
|
20
|
+
geometry: {
|
|
21
|
+
type: 'LineString',
|
|
22
|
+
coordinates: [
|
|
23
|
+
[7.10942788610961, 50.708209240168],
|
|
24
|
+
[7.10966149846967, 50.7088867160122],
|
|
25
|
+
[7.10910082880551, 50.7108256986007],
|
|
26
|
+
[7.10856352037736, 50.7126945974813],
|
|
27
|
+
[7.1083532692533, 50.7142598002937],
|
|
28
|
+
[7.10814301812924, 50.7160118929942],
|
|
29
|
+
[7.10793276700518, 50.7169463424345],
|
|
30
|
+
[7.10776923835314, 50.7176004570426],
|
|
31
|
+
[7.10713848498096, 50.718838602551],
|
|
32
|
+
[7.10699831756492, 50.7199599418793],
|
|
33
|
+
[7.106900786313568, 50.72118132611057],
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const marks = [
|
|
39
|
+
{
|
|
40
|
+
value: 15,
|
|
41
|
+
label: '15',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
value: 16,
|
|
45
|
+
label: '16',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
value: 17,
|
|
49
|
+
label: '17',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
value: 18,
|
|
53
|
+
label: '18',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
value: 19,
|
|
57
|
+
label: '19',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
value: 20,
|
|
61
|
+
label: '20',
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const Template = () => {
|
|
66
|
+
const [state, setState] = useState({ pause: true, zoom: 18, speed: 1, pitch: 60 });
|
|
67
|
+
|
|
68
|
+
const CameraFollowPath = useCameraFollowPath({
|
|
69
|
+
route: routeJson,
|
|
70
|
+
pause: state.pause,
|
|
71
|
+
pitch: state.pitch,
|
|
72
|
+
zoom: state.zoom,
|
|
73
|
+
speed: state.speed,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const [showComponent, setShowComponent] = useState(true);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<>
|
|
80
|
+
<TopToolbar>
|
|
81
|
+
<Button onClick={() => setShowComponent(!showComponent)}>
|
|
82
|
+
{showComponent ? 'Route ausblenden' : 'Route einblenden'}
|
|
83
|
+
</Button>
|
|
84
|
+
{showComponent ? (
|
|
85
|
+
<MlGeoJsonLayer
|
|
86
|
+
geojson={routeJson}
|
|
87
|
+
type="line"
|
|
88
|
+
paint={{
|
|
89
|
+
'line-width': 2,
|
|
90
|
+
'line-color': 'blue',
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
) : null}
|
|
94
|
+
<Button
|
|
95
|
+
disabled={!state.pause}
|
|
96
|
+
onClick={() =>
|
|
97
|
+
setState((current) => {
|
|
98
|
+
return { ...current, pause: false };
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
>
|
|
102
|
+
Start
|
|
103
|
+
</Button>
|
|
104
|
+
<Button
|
|
105
|
+
disabled={state.pause}
|
|
106
|
+
onClick={() =>
|
|
107
|
+
setState((current) => {
|
|
108
|
+
return { ...current, pause: true };
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
>
|
|
112
|
+
Pause
|
|
113
|
+
</Button>
|
|
114
|
+
<Button
|
|
115
|
+
onClick={() => {
|
|
116
|
+
CameraFollowPath.reset();
|
|
117
|
+
setState((current) => {
|
|
118
|
+
return { ...current, pause: true, pitch: 60, zoom: 18, speed: 1 };
|
|
119
|
+
});
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
Reset
|
|
123
|
+
</Button>
|
|
124
|
+
<Typography
|
|
125
|
+
id="discrete-slider"
|
|
126
|
+
style={{ color: '#121212', marginLeft: '10px', marginRight: '10px' }}
|
|
127
|
+
>
|
|
128
|
+
Zoom:
|
|
129
|
+
</Typography>
|
|
130
|
+
<Slider
|
|
131
|
+
value={state.zoom}
|
|
132
|
+
onChange={(ev, value) => {
|
|
133
|
+
setState((current) => {
|
|
134
|
+
return { ...current, zoom: Number(value) };
|
|
135
|
+
});
|
|
136
|
+
}}
|
|
137
|
+
getAriaValueText={(value) => value.toString()}
|
|
138
|
+
aria-labelledby="discrete-slider"
|
|
139
|
+
//valueLabelDisplay="auto"
|
|
140
|
+
step={1}
|
|
141
|
+
marks={marks}
|
|
142
|
+
min={15}
|
|
143
|
+
max={20}
|
|
144
|
+
sx={{
|
|
145
|
+
marginTop: '20px',
|
|
146
|
+
paddingBottom: '20px',
|
|
147
|
+
marginRight: '10px',
|
|
148
|
+
maxWidth: '200px',
|
|
149
|
+
}}
|
|
150
|
+
/>
|
|
151
|
+
<Typography
|
|
152
|
+
id="discrete-slider2"
|
|
153
|
+
style={{ color: '#121212', marginLeft: '10px', marginRight: '10px' }}
|
|
154
|
+
>
|
|
155
|
+
Speed:
|
|
156
|
+
</Typography>
|
|
157
|
+
<Slider
|
|
158
|
+
value={state.speed}
|
|
159
|
+
onChange={(ev, value) => {
|
|
160
|
+
setState((current) => {
|
|
161
|
+
return { ...current, speed: Number(value) };
|
|
162
|
+
});
|
|
163
|
+
}}
|
|
164
|
+
getAriaValueText={(value) => value.toString()}
|
|
165
|
+
aria-labelledby="discrete-slider2"
|
|
166
|
+
//valueLabelDisplay="auto"
|
|
167
|
+
step={0.1}
|
|
168
|
+
marks
|
|
169
|
+
min={0.1}
|
|
170
|
+
max={2}
|
|
171
|
+
sx={{
|
|
172
|
+
marginRight: '10px',
|
|
173
|
+
maxWidth: '200px',
|
|
174
|
+
}}
|
|
175
|
+
/>
|
|
176
|
+
<Button
|
|
177
|
+
onClick={() => {
|
|
178
|
+
if (state.pitch === 0) {
|
|
179
|
+
setState((current) => {
|
|
180
|
+
return { ...current, pitch: 60 };
|
|
181
|
+
});
|
|
182
|
+
} else {
|
|
183
|
+
setState((current) => {
|
|
184
|
+
return { ...current, pitch: 0 };
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}}
|
|
188
|
+
>
|
|
189
|
+
{state.pitch === 0 ? '3D' : '2D'}
|
|
190
|
+
</Button>
|
|
191
|
+
</TopToolbar>
|
|
192
|
+
</>
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export const ExampleConfig = Template.bind({});
|
|
197
|
+
ExampleConfig.parameters = {};
|
|
198
|
+
ExampleConfig.args = {};
|