@mapcomponents/react-maplibre 0.1.60 → 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 +5 -0
- package/coverage/clover.xml +94 -3
- package/coverage/coverage-final.json +1 -0
- package/coverage/lcov-report/index.html +24 -9
- 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 +1 -1
- 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 +1 -1
- package/coverage/lcov-report/src/components/MlVectorTileLayer/index.html +1 -1
- 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/useExportMap/index.html +1 -1
- package/coverage/lcov-report/src/hooks/useExportMap/index.ts.html +1 -1
- package/coverage/lcov-report/src/hooks/useExportMap/lib.ts.html +1 -1
- 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 +1 -1
- 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 +5 -2
- package/coverage/lcov.info +172 -0
- package/dist/hooks/useCameraFollowPath/useCameraFollowPath.d.ts +35 -0
- package/dist/hooks/useCameraFollowPath/useCameraFollowPath.stories.d.ts +17 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +152 -1
- 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/lib/PdfForm.tsx +2 -2
- 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/index.ts +1 -0
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++) {
|
|
@@ -40,10 +40,10 @@ 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
|
|
@@ -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 = {};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { useEffect, useCallback, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import * as turf from '@turf/turf';
|
|
4
|
+
import useMap from '../useMap';
|
|
5
|
+
import { LngLatBoundsLike, LngLatLike } from 'maplibre-gl';
|
|
6
|
+
|
|
7
|
+
interface useCameraFollowPathProps {
|
|
8
|
+
/**
|
|
9
|
+
* Id of the target MapLibre instance in mapContext
|
|
10
|
+
*/
|
|
11
|
+
mapId?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Id of an existing layer in the mapLibre instance to help specify the layer order
|
|
14
|
+
* This layer will be visually beneath the layer with the "insertBeforeLayer" id.
|
|
15
|
+
*/
|
|
16
|
+
insertBeforeLayer?: string;
|
|
17
|
+
/* pause is an useRef const and is triggerd in the storie */
|
|
18
|
+
pause?: boolean;
|
|
19
|
+
/* zoom is an useRef const and is triggerd in the storie */
|
|
20
|
+
zoom?: number;
|
|
21
|
+
/* pitch is an useRef const and is triggerd in the storie */
|
|
22
|
+
pitch?: number;
|
|
23
|
+
/* speed is an useRef const and is triggerd in the storie */
|
|
24
|
+
speed?: number;
|
|
25
|
+
/* kmPerStep is an useRef const */
|
|
26
|
+
kmPerStep?: number;
|
|
27
|
+
/* route is a json file, which is defined loaded in the storie */
|
|
28
|
+
route?: any;
|
|
29
|
+
/* stepDuration is a const */
|
|
30
|
+
stepDuration?: number;
|
|
31
|
+
/* timeoutId is an useRef const */
|
|
32
|
+
timeoutId?: number;
|
|
33
|
+
}
|
|
34
|
+
export type { useCameraFollowPathProps };
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Component template
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
const useCameraFollowPath = (props: useCameraFollowPathProps) => {
|
|
41
|
+
// Use a useRef hook to reference the layer object to be able to access it later inside useEffect hooks
|
|
42
|
+
// without the requirement of adding it to the dependency list (ignore the false eslint exhaustive deps warning)
|
|
43
|
+
const initializedRef = useRef(false);
|
|
44
|
+
const pause = useRef<boolean | undefined>(props.pause);
|
|
45
|
+
const zoom = useRef<number | undefined>(props.zoom);
|
|
46
|
+
const pitch = useRef<number | undefined>(props.pitch);
|
|
47
|
+
const step = useRef(1);
|
|
48
|
+
const speed = useRef<number | undefined>(props.speed);
|
|
49
|
+
const timeoutId = useRef();
|
|
50
|
+
|
|
51
|
+
const kmPerStep = props.kmPerStep || 0.01;
|
|
52
|
+
const routeDistance = turf.lineDistance(props.route);
|
|
53
|
+
const stepDuration = props.stepDuration || 70;
|
|
54
|
+
|
|
55
|
+
const mapHook = useMap({
|
|
56
|
+
mapId: props.mapId,
|
|
57
|
+
waitForLayer: props.insertBeforeLayer,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
pause.current = props.pause;
|
|
62
|
+
if (!pause.current) {
|
|
63
|
+
play();
|
|
64
|
+
}
|
|
65
|
+
}, [props.pause]);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!mapHook.map) return;
|
|
68
|
+
zoom.current = props.zoom;
|
|
69
|
+
if (typeof zoom.current !== 'undefined' && mapHook.map.map.getZoom() !== zoom.current) {
|
|
70
|
+
mapHook.map.map.setZoom(zoom.current);
|
|
71
|
+
}
|
|
72
|
+
}, [mapHook.map, props.zoom]);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (!mapHook.map) return;
|
|
75
|
+
pitch.current = props.pitch;
|
|
76
|
+
if (typeof pitch.current !== 'undefined' && pitch.current !== mapHook.map.map.getPitch()) {
|
|
77
|
+
mapHook.map.map.setPitch(pitch.current);
|
|
78
|
+
}
|
|
79
|
+
}, [mapHook.map, props.pitch]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
speed.current = props.speed;
|
|
82
|
+
}, [props.speed]);
|
|
83
|
+
|
|
84
|
+
const disableInteractivity = useCallback(() => {
|
|
85
|
+
if (!mapHook.map) return;
|
|
86
|
+
mapHook.map.map['scrollZoom'].disable();
|
|
87
|
+
mapHook.map.map['boxZoom'].disable();
|
|
88
|
+
mapHook.map.map['dragRotate'].disable();
|
|
89
|
+
mapHook.map.map['dragPan'].disable();
|
|
90
|
+
mapHook.map.map['keyboard'].disable();
|
|
91
|
+
mapHook.map.map['doubleClickZoom'].disable();
|
|
92
|
+
mapHook.map.map['touchZoomRotate'].disable();
|
|
93
|
+
}, [mapHook.map]);
|
|
94
|
+
const enableInteractivity = useCallback(() => {
|
|
95
|
+
if (!mapHook.map) return;
|
|
96
|
+
mapHook.map.map['scrollZoom'].enable();
|
|
97
|
+
mapHook.map.map['boxZoom'].enable();
|
|
98
|
+
mapHook.map.map['dragRotate'].enable();
|
|
99
|
+
mapHook.map.map['dragPan'].enable();
|
|
100
|
+
mapHook.map.map['keyboard'].enable();
|
|
101
|
+
mapHook.map.map['doubleClickZoom'].enable();
|
|
102
|
+
mapHook.map.map['touchZoomRotate'].enable();
|
|
103
|
+
}, [mapHook.map]);
|
|
104
|
+
|
|
105
|
+
function centerRoute() {
|
|
106
|
+
if (!mapHook.map || !props.route) return;
|
|
107
|
+
const bbox = turf.bbox(props.route);
|
|
108
|
+
let bounds: LngLatBoundsLike;
|
|
109
|
+
if (bbox && bbox.length > 3) {
|
|
110
|
+
bounds = [
|
|
111
|
+
[bbox[0], bbox[1]],
|
|
112
|
+
[bbox[2], bbox[3]],
|
|
113
|
+
];
|
|
114
|
+
mapHook.map.map.fitBounds(bounds, { padding: 100 });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function play() {
|
|
118
|
+
if (!mapHook.map) return;
|
|
119
|
+
|
|
120
|
+
if (!pause.current) {
|
|
121
|
+
disableInteractivity();
|
|
122
|
+
if (typeof zoom.current !== 'undefined' && mapHook.map.map.getZoom() !== zoom.current) {
|
|
123
|
+
mapHook.map.map.setZoom(zoom.current);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const alongRoutelati: number[] = turf.along(props.route, step.current * kmPerStep).geometry
|
|
127
|
+
.coordinates;
|
|
128
|
+
|
|
129
|
+
if (step.current * kmPerStep < routeDistance) {
|
|
130
|
+
mapHook.map.map.easeTo({
|
|
131
|
+
center: alongRoutelati as LngLatLike,
|
|
132
|
+
bearing: turf.bearing(
|
|
133
|
+
turf.point([mapHook.map.map.getCenter().lng, mapHook.map.map.getCenter().lat]),
|
|
134
|
+
turf.point(alongRoutelati)
|
|
135
|
+
),
|
|
136
|
+
duration: stepDuration,
|
|
137
|
+
essential: true,
|
|
138
|
+
});
|
|
139
|
+
if (typeof speed.current !== 'undefined') {
|
|
140
|
+
step.current = step.current + speed.current;
|
|
141
|
+
} else {
|
|
142
|
+
step.current++;
|
|
143
|
+
}
|
|
144
|
+
console.log('PAN MOVE');
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
play();
|
|
147
|
+
}, 100);
|
|
148
|
+
} else {
|
|
149
|
+
mapHook.map.map.setPitch(0);
|
|
150
|
+
centerRoute();
|
|
151
|
+
enableInteractivity();
|
|
152
|
+
console.log('ENABLE CONTROLS');
|
|
153
|
+
step.current = 1;
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
enableInteractivity();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function reset() {
|
|
161
|
+
if (!mapHook.map) return;
|
|
162
|
+
centerRoute();
|
|
163
|
+
enableInteractivity();
|
|
164
|
+
step.current = 1;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
if (!mapHook.map || initializedRef.current) return;
|
|
169
|
+
initializedRef.current = true;
|
|
170
|
+
centerRoute();
|
|
171
|
+
}, [mapHook.map]);
|
|
172
|
+
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
return () => {
|
|
175
|
+
if (timeoutId.current) {
|
|
176
|
+
clearTimeout(timeoutId.current);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}, []);
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
play: play,
|
|
183
|
+
reset: reset,
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
useCameraFollowPath.defaultProps = {
|
|
188
|
+
mapId: undefined,
|
|
189
|
+
zoom: 18,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export default useCameraFollowPath;
|
package/src/index.ts
CHANGED
|
@@ -36,6 +36,7 @@ export { default as useMap } from "./hooks/useMap";
|
|
|
36
36
|
export { default as useWms } from "./hooks/useWms.js";
|
|
37
37
|
export { default as useSource } from "./hooks/useSource";
|
|
38
38
|
export { default as useExportMap } from "./hooks/useExportMap";
|
|
39
|
+
export { default as useCameraFollowPath } from "./hooks/useCameraFollowPath/useCameraFollowPath";
|
|
39
40
|
|
|
40
41
|
export { MapComponentsProvider } from "./contexts/MapContext";
|
|
41
42
|
export { default as MapContext } from "./contexts/MapContext";
|