@mapcomponents/react-maplibre 0.1.25 → 0.1.29
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/CHANGELOG.md +78 -7
- package/coverage/clover.xml +463 -486
- package/coverage/coverage-final.json +21 -20
- package/coverage/lcov-report/index.html +94 -79
- package/coverage/lcov-report/src/components/MapLibreMap/MapLibreMap.js.html +22 -22
- package/coverage/lcov-report/src/components/MapLibreMap/index.html +1 -1
- package/coverage/lcov-report/src/components/MlCreatePdfButton/MlCreatePdfButton.js.html +11 -11
- package/coverage/lcov-report/src/components/MlCreatePdfButton/index.html +11 -11
- package/coverage/lcov-report/src/components/MlFeatureEditor/MlFeatureEditor.js.html +1 -1
- package/coverage/lcov-report/src/components/MlFeatureEditor/index.html +1 -1
- package/coverage/lcov-report/src/components/MlFillExtrusionLayer/MlFillExtrusionLayer.js.html +4 -4
- package/coverage/lcov-report/src/components/MlFillExtrusionLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlFollowGps/MlFollowGps.js.html +234 -36
- package/coverage/lcov-report/src/components/MlFollowGps/index.html +19 -19
- package/coverage/lcov-report/src/components/MlGPXViewer/MlGPXViewer.js.html +129 -165
- package/coverage/lcov-report/src/components/MlGPXViewer/gpxConverter.js.html +8 -8
- package/coverage/lcov-report/src/components/MlGPXViewer/index.html +20 -20
- package/coverage/lcov-report/src/components/MlGeoJsonLayer/MlGeoJsonLayer.js.html +45 -297
- package/coverage/lcov-report/src/components/MlGeoJsonLayer/index.html +19 -19
- package/coverage/lcov-report/src/components/MlImageMarkerLayer/MlImageMarkerLayer.js.html +1 -1
- package/coverage/lcov-report/src/components/MlImageMarkerLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayer/MlLayer.js.html +2 -2
- package/coverage/lcov-report/src/components/MlLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerMagnify/MlLayerMagnify.js.html +4 -4
- package/coverage/lcov-report/src/components/MlLayerMagnify/index.html +1 -1
- package/coverage/lcov-report/src/components/MlLayerSwipe/MlLayerSwipe.js.html +3 -3
- 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.js.html +1 -1
- package/coverage/lcov-report/src/components/MlMarker/index.html +1 -1
- package/coverage/lcov-report/src/components/MlNavigationCompass/MlNavigationCompass.js.html +38 -104
- package/coverage/lcov-report/src/components/MlNavigationCompass/index.html +19 -19
- package/coverage/lcov-report/src/components/MlNavigationTools/MlNavigationTools.js.html +40 -139
- package/coverage/lcov-report/src/components/MlNavigationTools/index.html +15 -15
- package/coverage/lcov-report/src/components/MlOsmLayer/MlOsmLayer.js.html +32 -155
- package/coverage/lcov-report/src/components/MlOsmLayer/index.html +19 -19
- package/coverage/lcov-report/src/components/MlScaleReference/MlScaleReference.js.html +39 -198
- package/coverage/lcov-report/src/components/MlScaleReference/index.html +9 -9
- 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 +4 -4
- 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.js.html +580 -0
- package/coverage/lcov-report/src/components/MlTransitionGeoJsonLayer/index.html +116 -0
- 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.js.html +3 -3
- 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.js.html +8 -11
- package/coverage/lcov-report/src/components/MlWmsLayer/index.html +1 -1
- package/coverage/lcov-report/src/components/MlWmsLoader/MlWmsLoader.js.html +1 -1
- package/coverage/lcov-report/src/components/MlWmsLoader/index.html +1 -1
- package/coverage/lcov-report/src/hooks/index.html +6 -6
- package/coverage/lcov-report/src/hooks/useMap.js.html +38 -26
- package/coverage/lcov-report/src/hooks/useMapState.js.html +47 -38
- package/coverage/lcov-report/src/hooks/useWms.js.html +2 -2
- package/coverage/lcov-report/src/i18n.js.html +1 -1
- package/coverage/lcov-report/src/index.html +1 -1
- package/coverage/lcov-report/src/translations/english.js.html +1 -1
- package/coverage/lcov-report/src/translations/german.js.html +1 -1
- package/coverage/lcov-report/src/translations/index.html +1 -1
- package/coverage/lcov.info +827 -872
- package/dist/index.esm.js +281 -490
- package/dist/index.esm.js.map +1 -1
- package/jsdoc.json +3 -3
- package/package.json +13 -10
- package/src/components/MapLibreMap/lib/MapLibreGlWrapper.js +6 -2
- package/src/components/MapLibreMap/lib/MapLibreGlWrapper.test.js +3 -3
- package/src/components/MlFeatureEditor/MlFeatureEditor.test.js +2 -2
- package/src/components/MlFollowGps/MlFollowGps.js +85 -19
- package/src/components/MlGPXViewer/MlGPXViewer.js +69 -81
- package/src/components/MlGeoJsonLayer/MlGeoJsonLayer.js +6 -90
- package/src/components/MlGeoJsonLayer/MlGeoJsonLayer.stories.js +4 -22
- package/src/components/MlGeoJsonLayer/util/getDefaultPaintPropsByType.js +2 -2
- package/src/components/MlNavigationCompass/MlNavigationCompass.js +17 -39
- package/src/components/MlNavigationCompass/MlNavigationCompass.test.js +3 -3
- package/src/components/MlNavigationTools/MlNavigationTools.js +30 -63
- package/src/components/MlOsmLayer/MlOsmLayer.js +15 -56
- package/src/components/MlOsmLayer/MlOsmLayer.stories.js +21 -10
- package/src/components/MlOsmLayer/MlOsmLayer.test.js +4 -4
- package/src/components/MlScaleReference/MlScaleReference.js +29 -82
- package/src/components/MlShareMapState/MlShareMapState.stories.js +1 -3
- package/src/components/MlThreeJsLayer/lib/GLTFLoader.js +2369 -2591
- package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.doc.de.md +3 -0
- package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.js +165 -0
- package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.meta.json +15 -0
- package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.stories.js +52 -0
- package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.test.js +20 -0
- package/src/components/MlTransitionGeoJsonLayer/assets/sample_1.json +26 -0
- package/src/components/MlTransitionGeoJsonLayer/assets/sample_2.json +22 -0
- package/src/components/MlTransitionGeoJsonLayer/assets/sample_polygon_1.json +33 -0
- package/src/components/{MlGeoJsonLayer → MlTransitionGeoJsonLayer}/util/transitionFunctions.js +63 -97
- package/src/components/MlWmsLayer/MlWmsLayer.js +1 -2
- package/src/decorators/MapContextDecorator.js +5 -0
- package/src/decorators/MultiMapContextDecorator.js +6 -0
- package/src/hooks/useMap.js +8 -4
- package/src/hooks/useMapState.js +4 -1
- package/src/hooks/useWms.js +1 -1
- package/dist/b556faa3bc6829d2.png +0 -0
- package/src/components/MlFollowGps/assets/marker.png +0 -0
- package/src/decorators/EmptyMapContextDecorator.js +0 -25
- package/src/decorators/MapContext3DDecorator.js +0 -39
- package/src/decorators/MapContextDashboardDecorator.js +0 -19
- package/src/decorators/MapContextKlokantechBasicDecorator.js +0 -39
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import React, { useRef, useEffect, useCallback } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
|
|
4
|
-
import * as turf from "@turf/turf";
|
|
5
|
-
|
|
6
4
|
import useMap from "../../hooks/useMap";
|
|
7
5
|
|
|
8
|
-
import { _transitionToGeojson } from "./util/transitionFunctions";
|
|
9
6
|
import getDefaultPaintPropsByType from "./util/getDefaultPaintPropsByType";
|
|
10
7
|
import getDefaulLayerTypeByGeometry from "./util/getDefaultLayerTypeByGeometry";
|
|
11
8
|
|
|
12
|
-
const msPerStep = 50;
|
|
13
9
|
const legalLayerTypes = ["circle", "fill", "line"];
|
|
14
10
|
|
|
15
11
|
/**
|
|
@@ -24,23 +20,6 @@ const MlGeoJsonLayer = (props) => {
|
|
|
24
20
|
const layerId = useRef(props.layerId || "MlGeoJsonLayer-" + mapHook.componentId);
|
|
25
21
|
const layerTypeRef = useRef(undefined);
|
|
26
22
|
|
|
27
|
-
// transition effect variables
|
|
28
|
-
const oldGeojsonRef = useRef(null);
|
|
29
|
-
const transitionInProgressRef = useRef(false);
|
|
30
|
-
const transitionTimeoutRef = useRef(undefined);
|
|
31
|
-
const currentTransitionStepRef = useRef(false);
|
|
32
|
-
const transitionGeojsonDataRef = useRef([]);
|
|
33
|
-
const transitionGeojsonCommonDataRef = useRef([]);
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
return () => {
|
|
37
|
-
// This is the cleanup function, it is called when this react component is removed from react-dom
|
|
38
|
-
if (transitionTimeoutRef.current) {
|
|
39
|
-
clearTimeout(transitionTimeoutRef.current);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}, []);
|
|
43
|
-
|
|
44
23
|
useEffect(() => {
|
|
45
24
|
if (!mapHook.map || !initializedRef.current) return;
|
|
46
25
|
|
|
@@ -60,64 +39,15 @@ const MlGeoJsonLayer = (props) => {
|
|
|
60
39
|
}
|
|
61
40
|
}, [props.paint, mapHook.map, props.mapId, props.defaultPaintOverrides]);
|
|
62
41
|
|
|
63
|
-
const transitionToGeojson = useCallback(
|
|
64
|
-
(newGeojson) => {
|
|
65
|
-
_transitionToGeojson(
|
|
66
|
-
newGeojson,
|
|
67
|
-
props,
|
|
68
|
-
transitionGeojsonCommonDataRef,
|
|
69
|
-
transitionGeojsonDataRef,
|
|
70
|
-
transitionInProgressRef,
|
|
71
|
-
oldGeojsonRef,
|
|
72
|
-
msPerStep,
|
|
73
|
-
currentTransitionStepRef,
|
|
74
|
-
mapHook.map,
|
|
75
|
-
layerId.current,
|
|
76
|
-
transitionTimeoutRef
|
|
77
|
-
);
|
|
78
|
-
},
|
|
79
|
-
[props, mapHook.map]
|
|
80
|
-
);
|
|
81
|
-
|
|
82
42
|
useEffect(() => {
|
|
83
43
|
if (!mapHook?.map?.getSource(layerId.current) || !initializedRef.current) return;
|
|
84
44
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
props.type === "line" &&
|
|
88
|
-
oldGeojsonRef.current
|
|
89
|
-
) {
|
|
90
|
-
transitionInProgressRef.current = false;
|
|
91
|
-
currentTransitionStepRef.current = false;
|
|
92
|
-
transitionGeojsonDataRef.current = [];
|
|
93
|
-
transitionGeojsonCommonDataRef.current = [];
|
|
94
|
-
transitionToGeojson(props.geojson);
|
|
95
|
-
} else {
|
|
96
|
-
mapHook.map.getSource(layerId.current).setData(props.geojson);
|
|
97
|
-
}
|
|
98
|
-
oldGeojsonRef.current = props.geojson;
|
|
99
|
-
}, [
|
|
100
|
-
props.geojson,
|
|
101
|
-
props.mapId,
|
|
102
|
-
mapHook.map,
|
|
103
|
-
props.type,
|
|
104
|
-
transitionToGeojson,
|
|
105
|
-
props.transitionTime,
|
|
106
|
-
]);
|
|
45
|
+
mapHook.map.getSource(layerId.current).setData(props.geojson);
|
|
46
|
+
}, [props.geojson, mapHook.map, props.type]);
|
|
107
47
|
|
|
108
48
|
const createLayer = useCallback(() => {
|
|
109
49
|
let geojson = props.geojson;
|
|
110
50
|
|
|
111
|
-
if (
|
|
112
|
-
props.type === "line" &&
|
|
113
|
-
typeof props.transitionTime !== "undefined" &&
|
|
114
|
-
props.transitionTime &&
|
|
115
|
-
typeof props.geojson.geometry !== "undefined"
|
|
116
|
-
) {
|
|
117
|
-
var tmpChunks = turf.lineChunk(props.geojson, 0.01);
|
|
118
|
-
geojson = tmpChunks.features[0];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
51
|
layerTypeRef.current = props.type || getDefaulLayerTypeByGeometry(props.geojson);
|
|
122
52
|
|
|
123
53
|
mapHook.map.addLayer(
|
|
@@ -149,19 +79,10 @@ const MlGeoJsonLayer = (props) => {
|
|
|
149
79
|
if (typeof props.onLeave !== "undefined") {
|
|
150
80
|
mapHook.map.on("mouseleave", layerId.current, props.onLeave, mapHook.componentId);
|
|
151
81
|
}
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
props.type === "line" &&
|
|
155
|
-
typeof props.transitionTime !== "undefined" &&
|
|
156
|
-
typeof props.geojson.geometry !== "undefined"
|
|
157
|
-
) {
|
|
158
|
-
transitionToGeojson(props.geojson);
|
|
159
|
-
oldGeojsonRef.current = props.geojson;
|
|
160
|
-
}
|
|
161
|
-
}, [mapHook.map, props, transitionToGeojson]);
|
|
82
|
+
}, [mapHook, props]);
|
|
162
83
|
|
|
163
84
|
useEffect(() => {
|
|
164
|
-
if (!mapHook.
|
|
85
|
+
if (!mapHook.map || !props.geojson) return;
|
|
165
86
|
|
|
166
87
|
if (
|
|
167
88
|
initializedRef.current &&
|
|
@@ -169,6 +90,7 @@ const MlGeoJsonLayer = (props) => {
|
|
|
169
90
|
layerTypeRef.current &&
|
|
170
91
|
props.type !== layerTypeRef.current
|
|
171
92
|
) {
|
|
93
|
+
// remove (cleanup) & reinitialize the layer if type has changed
|
|
172
94
|
mapHook.map.cleanup(mapHook.componentId);
|
|
173
95
|
} else if (
|
|
174
96
|
initializedRef.current &&
|
|
@@ -178,11 +100,10 @@ const MlGeoJsonLayer = (props) => {
|
|
|
178
100
|
return;
|
|
179
101
|
}
|
|
180
102
|
|
|
181
|
-
// initialize the layer and add it to the MapLibre-gl instance or do something else with it
|
|
182
103
|
initializedRef.current = true;
|
|
183
104
|
|
|
184
105
|
createLayer();
|
|
185
|
-
}, [mapHook
|
|
106
|
+
}, [mapHook, createLayer, props]);
|
|
186
107
|
|
|
187
108
|
return <></>;
|
|
188
109
|
};
|
|
@@ -247,11 +168,6 @@ MlGeoJsonLayer.propTypes = {
|
|
|
247
168
|
* left/unhovered.
|
|
248
169
|
*/
|
|
249
170
|
onLeave: PropTypes.func,
|
|
250
|
-
/**
|
|
251
|
-
* Creates transition animation whenever the geojson prop changes.
|
|
252
|
-
* Only works with layer type "line" and LineString GeoJSON data.
|
|
253
|
-
*/
|
|
254
|
-
transitionTime: PropTypes.number,
|
|
255
171
|
};
|
|
256
172
|
|
|
257
173
|
export default MlGeoJsonLayer;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
|
|
3
3
|
import MlGeoJsonLayer from "./MlGeoJsonLayer";
|
|
4
4
|
|
|
5
5
|
import mapContextDecorator from "../../decorators/MapContextDecorator";
|
|
6
|
-
import { MapContext } from "@mapcomponents/react-core";
|
|
7
6
|
|
|
8
7
|
import sample_geojson_1 from "./assets/sample_1.json";
|
|
9
|
-
import sample_geojson_2 from "./assets/sample_2.json";
|
|
10
8
|
import sample_polygon_geojson_1 from "./assets/sample_polygon_1.json";
|
|
11
9
|
|
|
12
10
|
console.log(sample_polygon_geojson_1);
|
|
@@ -28,31 +26,15 @@ const Template = (props) => {
|
|
|
28
26
|
</>
|
|
29
27
|
);
|
|
30
28
|
};
|
|
31
|
-
const
|
|
32
|
-
const mapContext = useContext(MapContext);
|
|
33
|
-
const [geojson, setGeojson] = useState(sample_geojson_1);
|
|
34
|
-
const initializedRef = useRef(false);
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
if (!mapContext.getMap() || initializedRef.current) return;
|
|
38
|
-
|
|
39
|
-
initializedRef.current = true;
|
|
40
|
-
mapContext.getMap().setCenter({ lng: 7.137609868988648, lat: 50.74746799549129 });
|
|
41
|
-
mapContext.getMap().setZoom(9.5);
|
|
42
|
-
|
|
43
|
-
setTimeout(() => {
|
|
44
|
-
setGeojson(sample_geojson_2);
|
|
45
|
-
}, 4000);
|
|
46
|
-
}, [geojson, mapContext]);
|
|
47
|
-
|
|
29
|
+
const LinestringTemplate = (props) => {
|
|
48
30
|
return (
|
|
49
31
|
<>
|
|
50
|
-
<MlGeoJsonLayer type="line" geojson={
|
|
32
|
+
<MlGeoJsonLayer type="line" geojson={sample_geojson_1} />
|
|
51
33
|
</>
|
|
52
34
|
);
|
|
53
35
|
};
|
|
54
36
|
|
|
55
|
-
export const Linestring =
|
|
37
|
+
export const Linestring = LinestringTemplate.bind({});
|
|
56
38
|
Linestring.parameters = {};
|
|
57
39
|
Linestring.args = {};
|
|
58
40
|
|
|
@@ -12,7 +12,7 @@ const getDefaultPaintPropsByType = (type, defaultPaintOverrides) => {
|
|
|
12
12
|
return defaultPaintOverrides.line;
|
|
13
13
|
}
|
|
14
14
|
return {
|
|
15
|
-
"line-color": "rgb(
|
|
15
|
+
"line-color": "rgb(203,211,2)",
|
|
16
16
|
"line-width": 5,
|
|
17
17
|
};
|
|
18
18
|
case "circle":
|
|
@@ -21,7 +21,7 @@ const getDefaultPaintPropsByType = (type, defaultPaintOverrides) => {
|
|
|
21
21
|
return defaultPaintOverrides.circle;
|
|
22
22
|
}
|
|
23
23
|
return {
|
|
24
|
-
"circle-color": "
|
|
24
|
+
"circle-color": "rgba(10,240,256)",
|
|
25
25
|
"circle-stroke-color": "#fff",
|
|
26
26
|
"circle-stroke-width": 2,
|
|
27
27
|
};
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import React, { useState,
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
|
|
4
|
-
import { MapContext } from "@mapcomponents/react-core";
|
|
5
|
-
import { v4 as uuidv4 } from "uuid";
|
|
6
|
-
|
|
7
4
|
import { ReactComponent as RotateRightIcon } from "./assets/rotate_right.svg";
|
|
8
5
|
import { ReactComponent as RotateLeftIcon } from "./assets/rotate_left.svg";
|
|
9
6
|
import { ReactComponent as NeedleIcon } from "./assets/needle.svg";
|
|
10
7
|
|
|
11
8
|
import styled from "@emotion/styled";
|
|
12
9
|
import { css } from "@emotion/css";
|
|
10
|
+
import useMap from "../../hooks/useMap";
|
|
13
11
|
|
|
14
12
|
const NeedleButton = styled.div`
|
|
15
13
|
width: 40%;
|
|
@@ -88,43 +86,23 @@ const RotateButton = styled.div`
|
|
|
88
86
|
* @component
|
|
89
87
|
*/
|
|
90
88
|
const MlNavigationCompass = (props) => {
|
|
91
|
-
|
|
92
|
-
const mapContext = useContext(MapContext);
|
|
93
|
-
|
|
94
|
-
const initializedRef = useRef(false);
|
|
95
|
-
const mapRef = useRef(undefined);
|
|
96
|
-
const componentId = useRef((props.idPrefix ? props.idPrefix : "MlNavigationCompass-") + uuidv4());
|
|
97
|
-
|
|
89
|
+
const mapHook = useMap({ mapId: props.mapId, waitForLayer: props.insertBeforeLayer });
|
|
98
90
|
const [bearing, setBearing] = useState(0);
|
|
99
91
|
|
|
100
92
|
useEffect(() => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return () => {
|
|
104
|
-
// This is the cleanup function, it is called when this react component is removed from react-dom
|
|
93
|
+
if (!mapHook.map) return;
|
|
105
94
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
mapRef.current = undefined;
|
|
109
|
-
}
|
|
110
|
-
initializedRef.current = false;
|
|
95
|
+
let _updateBearing = () => {
|
|
96
|
+
setBearing(Math.round(mapHook.map.getBearing()));
|
|
111
97
|
};
|
|
112
|
-
}, []);
|
|
113
98
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
initializedRef.current = true;
|
|
117
|
-
mapRef.current = mapContext.getMap(props.mapId);
|
|
99
|
+
mapHook.map.on("rotate", _updateBearing, mapHook.componentId);
|
|
100
|
+
_updateBearing();
|
|
118
101
|
|
|
119
|
-
|
|
120
|
-
"rotate",
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
124
|
-
componentId.current
|
|
125
|
-
);
|
|
126
|
-
setBearing(Math.round(mapRef.current.getBearing()));
|
|
127
|
-
}, [mapContext.mapIds, mapContext, props.mapId]);
|
|
102
|
+
return () => {
|
|
103
|
+
mapHook.map.off("rotate", _updateBearing);
|
|
104
|
+
};
|
|
105
|
+
}, [mapHook.map, props.mapId]);
|
|
128
106
|
|
|
129
107
|
return (
|
|
130
108
|
<>
|
|
@@ -154,7 +132,7 @@ const MlNavigationCompass = (props) => {
|
|
|
154
132
|
<RotateButton className={css({ ...props.rotateRightStyle })}>
|
|
155
133
|
<RotateRightIcon
|
|
156
134
|
onClick={() => {
|
|
157
|
-
let bearing = Math.round(
|
|
135
|
+
let bearing = Math.round(mapHook.map?.getBearing());
|
|
158
136
|
let rest = Math.round(bearing % 90);
|
|
159
137
|
if (bearing > 0) {
|
|
160
138
|
rest = 90 - rest;
|
|
@@ -162,14 +140,14 @@ const MlNavigationCompass = (props) => {
|
|
|
162
140
|
if (rest === 0) {
|
|
163
141
|
rest = 90;
|
|
164
142
|
}
|
|
165
|
-
|
|
143
|
+
mapHook.map?.setBearing(Math.round(bearing + Math.abs(rest)));
|
|
166
144
|
}}
|
|
167
145
|
></RotateRightIcon>
|
|
168
146
|
</RotateButton>
|
|
169
147
|
<NeedleButton
|
|
170
148
|
className={css({ ...props.needleStyle })}
|
|
171
149
|
onClick={() => {
|
|
172
|
-
|
|
150
|
+
mapHook.map?.setBearing(0);
|
|
173
151
|
}}
|
|
174
152
|
>
|
|
175
153
|
<NeedleContainer
|
|
@@ -183,7 +161,7 @@ const MlNavigationCompass = (props) => {
|
|
|
183
161
|
<RotateButton className={css({ ...props.rotateLeftStyle })}>
|
|
184
162
|
<RotateLeftIcon
|
|
185
163
|
onClick={() => {
|
|
186
|
-
let bearing = Math.round(
|
|
164
|
+
let bearing = Math.round(mapHook.map?.getBearing());
|
|
187
165
|
let rest = Math.round(bearing % 90);
|
|
188
166
|
if (bearing < 0) {
|
|
189
167
|
rest = 90 + rest;
|
|
@@ -191,7 +169,7 @@ const MlNavigationCompass = (props) => {
|
|
|
191
169
|
if (rest === 0) {
|
|
192
170
|
rest = 90;
|
|
193
171
|
}
|
|
194
|
-
|
|
172
|
+
mapHook.map?.setBearing(Math.round(bearing - Math.abs(rest)));
|
|
195
173
|
}}
|
|
196
174
|
></RotateLeftIcon>
|
|
197
175
|
</RotateButton>
|
|
@@ -48,7 +48,7 @@ describe("<MlNavigationCompass>", () => {
|
|
|
48
48
|
);
|
|
49
49
|
|
|
50
50
|
// MapLibreGlWrapper now subscribes to "data", "move" events on its own
|
|
51
|
-
await waitFor(() => expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(
|
|
51
|
+
await waitFor(() => expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5));
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
it("should deregister 1 event listener to the maplibre instance", async () => {
|
|
@@ -59,10 +59,10 @@ describe("<MlNavigationCompass>", () => {
|
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
// MapLibreGlWrapper now subscribes to "data", "move" events on its own
|
|
62
|
-
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(
|
|
62
|
+
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5);
|
|
63
63
|
|
|
64
64
|
wrapper.find(".toggle_layer_visible").simulate("click");
|
|
65
65
|
|
|
66
|
-
expect(mockMapLibreMethods.off).toHaveBeenCalledTimes(
|
|
66
|
+
expect(mockMapLibreMethods.off).toHaveBeenCalledTimes(2);
|
|
67
67
|
});
|
|
68
68
|
});
|
|
@@ -1,25 +1,17 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import {MapContext} from "@mapcomponents/react-core";
|
|
4
|
-
import {useEffect, useRef, useContext, useState} from "react";
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
5
2
|
import Button from "@mui/material/Button";
|
|
6
3
|
import ButtonGroup from "@mui/material/ButtonGroup";
|
|
7
4
|
import ControlPointIcon from "@mui/icons-material/ControlPoint";
|
|
8
5
|
import RemoveCircleOutlineIcon from "@mui/icons-material/RemoveCircleOutline";
|
|
9
|
-
//import ZoomOutIcon from "@mui/icons-material/ZoomOut";
|
|
10
|
-
//import ZoomInIcon from "@mui/icons-material/ZoomIn";
|
|
11
6
|
import GpsFixedIcon from "@mui/icons-material/GpsFixed";
|
|
12
|
-
import {v4 as uuidv4} from "uuid";
|
|
13
7
|
|
|
14
8
|
import MlNavigationCompass from "../MlNavigationCompass/MlNavigationCompass";
|
|
15
9
|
import MlFollowGps from "../MlFollowGps/MlFollowGps";
|
|
16
10
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
|
11
|
+
import useMap from "../../hooks/useMap";
|
|
17
12
|
|
|
18
13
|
const MlNavigationTools = (props) => {
|
|
19
|
-
const
|
|
20
|
-
const initializedRef = useRef(false);
|
|
21
|
-
const mapRef = useRef(undefined);
|
|
22
|
-
const componentId = useRef((props.idPrefix ? props.idPrefix : "MlComponentTemplate-") + uuidv4());
|
|
14
|
+
const mapHook = useMap({ mapId: props.mapId, waitForLayer: props.insertBeforeLayer });
|
|
23
15
|
|
|
24
16
|
const [pitch, setPitch] = useState(0);
|
|
25
17
|
const [locationAccessDenied, setLocationAccessDenied] = useState(false);
|
|
@@ -38,67 +30,42 @@ const MlNavigationTools = (props) => {
|
|
|
38
30
|
":hover": {
|
|
39
31
|
backgroundColor: "#515151",
|
|
40
32
|
},
|
|
41
|
-
color: "#ececec"
|
|
33
|
+
color: "#ececec",
|
|
42
34
|
};
|
|
43
35
|
|
|
44
36
|
useEffect(() => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return () => {
|
|
48
|
-
// This is the cleanup function, it is called when this react component is removed from react-dom
|
|
49
|
-
// try to remove anything this component has added to the MapLibre-gl instance
|
|
50
|
-
// e.g.: remove the layer
|
|
51
|
-
// mapContext.getMap(props.mapId).removeLayer(layerRef.current);
|
|
52
|
-
// check for the existence of map.style before calling getLayer or getSource
|
|
53
|
-
|
|
54
|
-
if (mapRef.current) {
|
|
55
|
-
mapRef.current.cleanup(_componentId);
|
|
56
|
-
mapRef.current = undefined;
|
|
57
|
-
}
|
|
58
|
-
initializedRef.current = false;
|
|
59
|
-
};
|
|
60
|
-
}, []);
|
|
37
|
+
if (!mapHook.map) return;
|
|
61
38
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
mapRef.current = mapContext.getMap(props.mapId);
|
|
68
|
-
mapRef.current.on(
|
|
69
|
-
"pitchend",
|
|
70
|
-
() => {
|
|
71
|
-
setPitch(mapRef.current.getPitch());
|
|
72
|
-
},
|
|
73
|
-
componentId.current
|
|
74
|
-
);
|
|
75
|
-
setPitch(mapRef.current.getPitch());
|
|
76
|
-
}, [mapContext.mapIds, mapContext, props.mapId]);
|
|
39
|
+
mapHook.map.on("pitchend", () => {
|
|
40
|
+
setPitch(mapHook.map.getPitch());
|
|
41
|
+
});
|
|
42
|
+
setPitch(mapHook.map.getPitch());
|
|
43
|
+
}, [mapHook.map, props.mapId]);
|
|
77
44
|
|
|
78
45
|
const zoomIn = () => {
|
|
79
|
-
if (!
|
|
46
|
+
if (!mapHook.map) return;
|
|
80
47
|
|
|
81
|
-
if (
|
|
82
|
-
|
|
48
|
+
if (mapHook.map.transform._zoom + 0.5 <= mapHook.map.transform._maxZoom) {
|
|
49
|
+
mapHook.map.easeTo({ zoom: mapHook.map.transform._zoom + 0.5 });
|
|
83
50
|
}
|
|
84
51
|
};
|
|
85
52
|
|
|
86
53
|
const zoomOut = () => {
|
|
87
|
-
if (!
|
|
54
|
+
if (!mapHook.map) return;
|
|
88
55
|
|
|
89
|
-
if (
|
|
90
|
-
|
|
56
|
+
if (mapHook.map.transform._zoom - 0.5 >= mapHook.map.transform._minZoom) {
|
|
57
|
+
mapHook.map.easeTo({ zoom: mapHook.map.transform._zoom - 0.5 });
|
|
91
58
|
}
|
|
92
59
|
};
|
|
93
60
|
|
|
94
61
|
const adjustPitch = () => {
|
|
95
|
-
if (!
|
|
62
|
+
if (!mapHook.map) return;
|
|
96
63
|
|
|
97
64
|
let targetPitch = 60;
|
|
98
|
-
if (
|
|
65
|
+
if (mapHook.map.getPitch() !== 0) {
|
|
99
66
|
targetPitch = 0;
|
|
100
67
|
}
|
|
101
|
-
|
|
68
|
+
mapHook.map.easeTo({ pitch: targetPitch });
|
|
102
69
|
};
|
|
103
70
|
|
|
104
71
|
const moveToCurrentLocation = () => {
|
|
@@ -106,7 +73,7 @@ const MlNavigationTools = (props) => {
|
|
|
106
73
|
};
|
|
107
74
|
|
|
108
75
|
const getLocationSuccess = (location) => {
|
|
109
|
-
|
|
76
|
+
mapHook.map.setCenter([location.coords.longitude, location.coords.latitude]);
|
|
110
77
|
};
|
|
111
78
|
|
|
112
79
|
const getLocationError = () => {
|
|
@@ -131,33 +98,33 @@ const MlNavigationTools = (props) => {
|
|
|
131
98
|
position: "relative",
|
|
132
99
|
height: mediaIsMobile ? "55px" : "45px",
|
|
133
100
|
marginLeft: mediaIsMobile ? "3px" : "-5px",
|
|
134
|
-
transform: mediaIsMobile ? "scale(1.6)" : "scale(1)"
|
|
101
|
+
transform: mediaIsMobile ? "scale(1.6)" : "scale(1)",
|
|
135
102
|
}}
|
|
136
103
|
backgroundStyle={{
|
|
137
104
|
boxShadow: "0px 0px 18px rgba(0,0,0,.5)",
|
|
138
105
|
}}
|
|
139
106
|
/>
|
|
140
|
-
<Button sx={{...buttonStyle, fontWeight: 600}} onClick={adjustPitch}>
|
|
107
|
+
<Button sx={{ ...buttonStyle, fontWeight: 600 }} onClick={adjustPitch}>
|
|
141
108
|
{pitch ? "2D" : "3D"}
|
|
142
109
|
</Button>
|
|
143
110
|
<Button sx={buttonStyle} onClick={moveToCurrentLocation} disabled={locationAccessDenied}>
|
|
144
|
-
<GpsFixedIcon sx={{fontSize: mediaIsMobile ? "1.5em" : "1.2em"}}/>
|
|
111
|
+
<GpsFixedIcon sx={{ fontSize: mediaIsMobile ? "1.5em" : "1.2em" }} />
|
|
145
112
|
</Button>
|
|
146
|
-
<MlFollowGps style={{...(({color, ...rest}) => rest)(buttonStyle)}} />
|
|
113
|
+
<MlFollowGps style={{ ...(({ color, ...rest }) => rest)(buttonStyle) }} />
|
|
147
114
|
<ButtonGroup
|
|
148
115
|
orientation="vertical"
|
|
149
116
|
sx={{
|
|
150
117
|
width: "50px",
|
|
151
118
|
border: "none",
|
|
152
|
-
Button: {minWidth: "20px !important", border: "none", padding: 0},
|
|
153
|
-
"Button:hover": {border: "none"},
|
|
119
|
+
Button: { minWidth: "20px !important", border: "none", padding: 0 },
|
|
120
|
+
"Button:hover": { border: "none" },
|
|
154
121
|
}}
|
|
155
122
|
>
|
|
156
|
-
<Button sx={{...buttonStyle, color: "#ececec"
|
|
157
|
-
<ControlPointIcon sx={{fontSize: mediaIsMobile ? "1.5em" : "1.2em"}}/>
|
|
123
|
+
<Button sx={{ ...buttonStyle, color: "#ececec" }} onClick={zoomIn}>
|
|
124
|
+
<ControlPointIcon sx={{ fontSize: mediaIsMobile ? "1.5em" : "1.2em" }} />
|
|
158
125
|
</Button>
|
|
159
|
-
<Button sx={{...buttonStyle, color: "#ececec"
|
|
160
|
-
<RemoveCircleOutlineIcon sx={{fontSize: mediaIsMobile ? "1.5em" : "1.2em"}}/>
|
|
126
|
+
<Button sx={{ ...buttonStyle, color: "#ececec" }} onClick={zoomOut}>
|
|
127
|
+
<RemoveCircleOutlineIcon sx={{ fontSize: mediaIsMobile ? "1.5em" : "1.2em" }} />
|
|
161
128
|
</Button>
|
|
162
129
|
</ButtonGroup>
|
|
163
130
|
</div>
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { MapContext } from "@mapcomponents/react-core";
|
|
3
|
-
import { v4 as uuidv4 } from "uuid";
|
|
1
|
+
import React, { useRef, useEffect, useState } from "react";
|
|
4
2
|
|
|
5
|
-
import Button from "@mui/material/Button";
|
|
6
3
|
import PropTypes from "prop-types";
|
|
4
|
+
import useMap from "../../hooks/useMap";
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Adds a standard OSM tile layer to the maplibre-gl instancereference by
|
|
@@ -12,81 +10,42 @@ import PropTypes from "prop-types";
|
|
|
12
10
|
* @component
|
|
13
11
|
*/
|
|
14
12
|
const MlOsmLayer = (props) => {
|
|
15
|
-
const
|
|
16
|
-
const mapRef = useRef(undefined);
|
|
13
|
+
const mapHook = useMap({ mapId: props.mapId, waitForLayer: props.insertBeforeLayer });
|
|
17
14
|
|
|
18
|
-
const
|
|
19
|
-
const componentId = useRef((props.idPrefix ? props.idPrefix : "MlOsmLayer-") + uuidv4());
|
|
20
|
-
const initializedRef = useRef(false);
|
|
21
|
-
const sourceIdRef = useRef((props.idPrefix ? props.idPrefix : "MlOsmLayer-source-") + uuidv4());
|
|
22
|
-
const layerIdRef = useRef((props.idPrefix ? props.idPrefix : "MlOsmLayer-layer-") + uuidv4());
|
|
15
|
+
const layerId = useRef(props.layerId || "MlOsmLayer-" + mapHook.componentId);
|
|
23
16
|
|
|
24
17
|
useEffect(() => {
|
|
25
|
-
|
|
26
|
-
return () => {
|
|
27
|
-
// This is the cleanup function, it is called when this react component is removed from react-dom
|
|
28
|
-
if (mapRef.current) {
|
|
29
|
-
mapRef.current.cleanup(_componentId);
|
|
18
|
+
if (!mapHook.map) return;
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
}, []);
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
if (!mapContext.mapExists(props.mapId) || initializedRef.current) return;
|
|
38
|
-
|
|
39
|
-
initializedRef.current = true;
|
|
40
|
-
mapRef.current = mapContext.getMap(props.mapId);
|
|
41
|
-
|
|
42
|
-
mapRef.current.addSource(
|
|
43
|
-
sourceIdRef.current,
|
|
20
|
+
mapHook.map.addSource(
|
|
21
|
+
layerId.current,
|
|
44
22
|
{
|
|
45
23
|
type: "raster",
|
|
46
24
|
tileSize: 256,
|
|
47
25
|
...props.sourceOptions,
|
|
48
26
|
},
|
|
49
|
-
componentId
|
|
27
|
+
mapHook.componentId
|
|
50
28
|
);
|
|
51
|
-
|
|
29
|
+
mapHook.map.addLayer(
|
|
52
30
|
{
|
|
53
|
-
id:
|
|
31
|
+
id: layerId.current,
|
|
54
32
|
type: "raster",
|
|
55
|
-
source:
|
|
33
|
+
source: layerId.current,
|
|
56
34
|
minzoom: 0,
|
|
57
35
|
maxzoom: 22,
|
|
58
36
|
...props.layerOptions,
|
|
59
37
|
},
|
|
60
38
|
props.insertBeforeLayer,
|
|
61
|
-
componentId
|
|
39
|
+
mapHook.componentId
|
|
62
40
|
);
|
|
63
|
-
}, [
|
|
64
|
-
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
if (!mapRef.current) return;
|
|
67
|
-
|
|
68
|
-
// toggle layer visibility by changing the layout object's visibility property
|
|
69
|
-
if (showLayer) {
|
|
70
|
-
mapRef.current.setLayoutProperty(layerIdRef.current, "visibility", "visible");
|
|
71
|
-
} else {
|
|
72
|
-
mapRef.current.setLayoutProperty(layerIdRef.current, "visibility", "none");
|
|
73
|
-
}
|
|
74
|
-
}, [showLayer]);
|
|
41
|
+
}, [props, mapHook.map]);
|
|
75
42
|
|
|
76
|
-
return
|
|
77
|
-
<Button
|
|
78
|
-
color="primary"
|
|
79
|
-
variant={showLayer ? "contained" : "outlined"}
|
|
80
|
-
onClick={() => setShowLayer(!showLayer)}
|
|
81
|
-
>
|
|
82
|
-
OSM
|
|
83
|
-
</Button>
|
|
84
|
-
);
|
|
43
|
+
return <></>;
|
|
85
44
|
};
|
|
86
45
|
|
|
87
46
|
MlOsmLayer.propTypes = {
|
|
88
47
|
/**
|
|
89
|
-
* Id of the target MapLibre instance in
|
|
48
|
+
* Id of the target MapLibre instance in mapHook
|
|
90
49
|
*/
|
|
91
50
|
mapId: PropTypes.string,
|
|
92
51
|
/**
|