@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.
Files changed (102) hide show
  1. package/.eslintignore +2 -1
  2. package/CHANGELOG.md +5 -0
  3. package/coverage/clover.xml +94 -3
  4. package/coverage/coverage-final.json +1 -0
  5. package/coverage/lcov-report/index.html +24 -9
  6. package/coverage/lcov-report/src/components/MapLibreMap/MapLibreMap.tsx.html +1 -1
  7. package/coverage/lcov-report/src/components/MapLibreMap/index.html +1 -1
  8. package/coverage/lcov-report/src/components/MlCenterPosition/MlCenterPosition.tsx.html +1 -1
  9. package/coverage/lcov-report/src/components/MlCenterPosition/index.html +1 -1
  10. package/coverage/lcov-report/src/components/MlCreatePdfButton/MlCreatePdfButton.tsx.html +1 -1
  11. package/coverage/lcov-report/src/components/MlCreatePdfButton/index.html +1 -1
  12. package/coverage/lcov-report/src/components/MlCreatePdfForm/MlCreatePdfForm.tsx.html +1 -1
  13. package/coverage/lcov-report/src/components/MlCreatePdfForm/index.html +1 -1
  14. package/coverage/lcov-report/src/components/MlFeatureEditor/MlFeatureEditor.tsx.html +1 -1
  15. package/coverage/lcov-report/src/components/MlFeatureEditor/index.html +1 -1
  16. package/coverage/lcov-report/src/components/MlFillExtrusionLayer/MlFillExtrusionLayer.tsx.html +1 -1
  17. package/coverage/lcov-report/src/components/MlFillExtrusionLayer/index.html +1 -1
  18. package/coverage/lcov-report/src/components/MlFollowGps/MlFollowGps.tsx.html +1 -1
  19. package/coverage/lcov-report/src/components/MlFollowGps/index.html +1 -1
  20. package/coverage/lcov-report/src/components/MlGPXViewer/MlGPXViewer.tsx.html +1 -1
  21. package/coverage/lcov-report/src/components/MlGPXViewer/gpxConverter.js.html +1 -1
  22. package/coverage/lcov-report/src/components/MlGPXViewer/index.html +1 -1
  23. package/coverage/lcov-report/src/components/MlGeoJsonLayer/MlGeoJsonLayer.tsx.html +1 -1
  24. package/coverage/lcov-report/src/components/MlGeoJsonLayer/index.html +1 -1
  25. package/coverage/lcov-report/src/components/MlGeojsonLayerWithSource/MlGeojsonLayerWithSource.tsx.html +1 -1
  26. package/coverage/lcov-report/src/components/MlGeojsonLayerWithSource/index.html +1 -1
  27. package/coverage/lcov-report/src/components/MlImageMarkerLayer/MlImageMarkerLayer.tsx.html +1 -1
  28. package/coverage/lcov-report/src/components/MlImageMarkerLayer/index.html +1 -1
  29. package/coverage/lcov-report/src/components/MlLayer/MlLayer.tsx.html +1 -1
  30. package/coverage/lcov-report/src/components/MlLayer/index.html +1 -1
  31. package/coverage/lcov-report/src/components/MlLayerMagnify/MlLayerMagnify.tsx.html +1 -1
  32. package/coverage/lcov-report/src/components/MlLayerMagnify/index.html +1 -1
  33. package/coverage/lcov-report/src/components/MlLayerSwipe/MlLayerSwipe.tsx.html +1 -1
  34. package/coverage/lcov-report/src/components/MlLayerSwipe/index.html +1 -1
  35. package/coverage/lcov-report/src/components/MlLayerSwitcher/MlLayerSwitcher.js.html +1 -1
  36. package/coverage/lcov-report/src/components/MlLayerSwitcher/components/LayerBox.js.html +1 -1
  37. package/coverage/lcov-report/src/components/MlLayerSwitcher/components/index.html +1 -1
  38. package/coverage/lcov-report/src/components/MlLayerSwitcher/index.html +1 -1
  39. package/coverage/lcov-report/src/components/MlMarker/MlMarker.tsx.html +1 -1
  40. package/coverage/lcov-report/src/components/MlMarker/index.html +1 -1
  41. package/coverage/lcov-report/src/components/MlMeasureTool/MlMeasureTool.tsx.html +1 -1
  42. package/coverage/lcov-report/src/components/MlMeasureTool/index.html +1 -1
  43. package/coverage/lcov-report/src/components/MlNavigationCompass/MlNavigationCompass.tsx.html +1 -1
  44. package/coverage/lcov-report/src/components/MlNavigationCompass/index.html +1 -1
  45. package/coverage/lcov-report/src/components/MlNavigationTools/MlNavigationTools.tsx.html +1 -1
  46. package/coverage/lcov-report/src/components/MlNavigationTools/index.html +1 -1
  47. package/coverage/lcov-report/src/components/MlOsmLayer/MlOsmLayer.js.html +1 -1
  48. package/coverage/lcov-report/src/components/MlOsmLayer/MlOsmLayer.stories_.js.html +1 -1
  49. package/coverage/lcov-report/src/components/MlOsmLayer/index.html +1 -1
  50. package/coverage/lcov-report/src/components/MlScaleReference/MlScaleReference.js.html +1 -1
  51. package/coverage/lcov-report/src/components/MlScaleReference/index.html +1 -1
  52. package/coverage/lcov-report/src/components/MlShareMapState/MlShareMapState.js.html +1 -1
  53. package/coverage/lcov-report/src/components/MlShareMapState/index.html +1 -1
  54. package/coverage/lcov-report/src/components/MlSpatialElevationProfile/MlSpatialElevationProfile.js.html +1 -1
  55. package/coverage/lcov-report/src/components/MlSpatialElevationProfile/index.html +1 -1
  56. package/coverage/lcov-report/src/components/MlThreeJsLayer/MlThreeJsLayer.js.html +1 -1
  57. package/coverage/lcov-report/src/components/MlThreeJsLayer/index.html +1 -1
  58. package/coverage/lcov-report/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.tsx.html +1 -1
  59. package/coverage/lcov-report/src/components/MlTransitionGeoJsonLayer/index.html +1 -1
  60. package/coverage/lcov-report/src/components/MlUseMapDebugger/MlUseMapDebugger.js.html +1 -1
  61. package/coverage/lcov-report/src/components/MlUseMapDebugger/index.html +1 -1
  62. package/coverage/lcov-report/src/components/MlVectorTileLayer/MlVectorTileLayer.tsx.html +1 -1
  63. package/coverage/lcov-report/src/components/MlVectorTileLayer/index.html +1 -1
  64. package/coverage/lcov-report/src/components/MlWmsFeatureInfoPopup/MlWmsFeatureInfoPopup.js.html +1 -1
  65. package/coverage/lcov-report/src/components/MlWmsFeatureInfoPopup/index.html +1 -1
  66. package/coverage/lcov-report/src/components/MlWmsLayer/MlWmsLayer.tsx.html +1 -1
  67. package/coverage/lcov-report/src/components/MlWmsLayer/index.html +1 -1
  68. package/coverage/lcov-report/src/components/MlWmsLoader/MlWmsLoader.tsx.html +1 -1
  69. package/coverage/lcov-report/src/components/MlWmsLoader/index.html +1 -1
  70. package/coverage/lcov-report/src/contexts/MapContext.tsx.html +1 -1
  71. package/coverage/lcov-report/src/contexts/SimpleDataContext.js.html +1 -1
  72. package/coverage/lcov-report/src/contexts/SimpleDataProvider.js.html +1 -1
  73. package/coverage/lcov-report/src/contexts/index.html +1 -1
  74. package/coverage/lcov-report/src/hooks/index.html +1 -1
  75. package/coverage/lcov-report/src/hooks/useCameraFollowPath/index.html +116 -0
  76. package/coverage/lcov-report/src/hooks/useCameraFollowPath/useCameraFollowPath.tsx.html +661 -0
  77. package/coverage/lcov-report/src/hooks/useExportMap/index.html +1 -1
  78. package/coverage/lcov-report/src/hooks/useExportMap/index.ts.html +1 -1
  79. package/coverage/lcov-report/src/hooks/useExportMap/lib.ts.html +1 -1
  80. package/coverage/lcov-report/src/hooks/useLayer.ts.html +1 -1
  81. package/coverage/lcov-report/src/hooks/useLayerEvent.js.html +1 -1
  82. package/coverage/lcov-report/src/hooks/useMap.ts.html +1 -1
  83. package/coverage/lcov-report/src/hooks/useMapState.ts.html +1 -1
  84. package/coverage/lcov-report/src/hooks/useSource.ts.html +1 -1
  85. package/coverage/lcov-report/src/hooks/useWms.js.html +1 -1
  86. package/coverage/lcov-report/src/index.html +1 -1
  87. package/coverage/lcov-report/src/index.ts.html +5 -2
  88. package/coverage/lcov.info +172 -0
  89. package/dist/hooks/useCameraFollowPath/useCameraFollowPath.d.ts +35 -0
  90. package/dist/hooks/useCameraFollowPath/useCameraFollowPath.stories.d.ts +17 -0
  91. package/dist/index.d.ts +1 -0
  92. package/dist/index.esm.js +152 -1
  93. package/dist/index.esm.js.map +1 -1
  94. package/package.json +2 -1
  95. package/scripts/build-catalogue-meta.js +1 -1
  96. package/src/components/MlCreatePdfForm/lib/PdfForm.tsx +2 -2
  97. package/src/hooks/useCameraFollowPath/useCameraFollowPath.doc.de.md +4 -0
  98. package/src/hooks/useCameraFollowPath/useCameraFollowPath.doc.en.md +1 -0
  99. package/src/hooks/useCameraFollowPath/useCameraFollowPath.meta.json +15 -0
  100. package/src/hooks/useCameraFollowPath/useCameraFollowPath.stories.tsx +198 -0
  101. package/src/hooks/useCameraFollowPath/useCameraFollowPath.tsx +192 -0
  102. 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.60",
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/components/**/*.meta.json", options, function (er, files) {
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,4 @@
1
+ # Kamerafahrt entlang eines Pfades
2
+
3
+ Das Component akzeptiert einen Array bestehend aus Koordinaten und fährt diese Strecke mit der Kamera ab.
4
+ Einstellungsmöglichkeiten für Geschwindigkeit, Initiale Zoomstufe und End-Zoomstufe sind ebenfalls vorhanden.
@@ -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";