@mapcomponents/react-maplibre 0.1.26 → 0.1.30
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 +31 -0
- package/coverage/clover.xml +456 -479
- 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 +212 -26
- 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 +2 -2
- 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 +1 -1
- 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 +813 -858
- package/dist/index.esm.js +210 -425
- package/dist/index.esm.js.map +1 -1
- package/jsdoc.json +3 -3
- package/package.json +19 -13
- 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 +74 -12
- 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/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
package/jsdoc.json
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
},
|
|
9
9
|
"recurseDepth": 10,
|
|
10
10
|
"opts": {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"template": "node_modules/better-docs",
|
|
12
|
+
"destination": "docs/jsdocs"
|
|
13
|
+
},
|
|
14
14
|
"source": {
|
|
15
15
|
"include": ["./src/"],
|
|
16
16
|
"excludePattern": ".*/(utils|MlFeatureEditor\/lib)/.*"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mapcomponents/react-maplibre",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"private": false,
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -13,17 +13,17 @@
|
|
|
13
13
|
"@mapbox/mapbox-gl-draw": "^1.2.0",
|
|
14
14
|
"@mapbox/mapbox-gl-sync-move": "^0.3.0",
|
|
15
15
|
"@mapcomponents/react-core": "^0.1.7",
|
|
16
|
-
"@mui/icons-material": "^5.
|
|
17
|
-
"@mui/material": "5.
|
|
18
|
-
"@mui/styles": "^5.0
|
|
16
|
+
"@mui/icons-material": "^5.3.1",
|
|
17
|
+
"@mui/material": "5.4.0",
|
|
18
|
+
"@mui/styles": "^5.3.0",
|
|
19
19
|
"@turf/turf": "^6.5.0",
|
|
20
|
-
"jspdf": "^2.
|
|
21
|
-
"maplibre-gl": "^1.
|
|
20
|
+
"jspdf": "^2.5.1",
|
|
21
|
+
"maplibre-gl": "^2.1.6",
|
|
22
22
|
"react-i18next": "^11.14.3",
|
|
23
|
-
"three": "^0.
|
|
23
|
+
"three": "^0.137.5",
|
|
24
24
|
"uuid": "^8.3.2",
|
|
25
25
|
"wms-capabilities": "^0.5.1",
|
|
26
|
-
"xmldom": "^0.
|
|
26
|
+
"xmldom": "^0.6.0"
|
|
27
27
|
},
|
|
28
28
|
"dependenciesComment": {
|
|
29
29
|
"xmldom": "MlGPXLayer"
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"build-catalogue-meta": "node scripts/build-catalogue-meta.js",
|
|
47
47
|
"build-catalogue-markdown-docs": "node scripts/build-catalogue-markdown-docs.js",
|
|
48
48
|
"create-component": "./scripts/create-map-component.sh",
|
|
49
|
-
"docs-create": "jsdoc -r -c ./jsdoc.json -d
|
|
49
|
+
"docs-create": "jsdoc -r -c ./jsdoc.json -d docs/jsdocs/react-map-components-maplibre/$npm_package_version",
|
|
50
50
|
"docs-serve": "http-server ./js-docs/react-map-components-maplibre/$npm_package_version -p 3001"
|
|
51
51
|
},
|
|
52
52
|
"jest": {
|
|
@@ -76,13 +76,19 @@
|
|
|
76
76
|
"custom\\-.*\\-mode\\.js$",
|
|
77
77
|
"(.stories)\\.(ts|tsx|js)$",
|
|
78
78
|
"/distribution/.*\\.(ts|js)$"
|
|
79
|
-
]
|
|
79
|
+
],
|
|
80
|
+
"moduleNameMapper": {
|
|
81
|
+
"^!maplibre-gl$": "<rootDir>/node_modules/maplibre-gl"
|
|
82
|
+
}
|
|
80
83
|
},
|
|
81
84
|
"eslintConfig": {
|
|
82
85
|
"extends": [
|
|
83
86
|
"react-app",
|
|
84
87
|
"react-app/jest"
|
|
85
|
-
]
|
|
88
|
+
],
|
|
89
|
+
"rules": {
|
|
90
|
+
"import/no-webpack-loader-syntax": "off"
|
|
91
|
+
}
|
|
86
92
|
},
|
|
87
93
|
"browserslist": {
|
|
88
94
|
"production": [
|
|
@@ -102,7 +108,7 @@
|
|
|
102
108
|
"peerDependencies": {},
|
|
103
109
|
"devDependencies": {
|
|
104
110
|
"@babel/cli": "^7.15.4",
|
|
105
|
-
"@babel/core": "^7.
|
|
111
|
+
"@babel/core": "^7.17.5",
|
|
106
112
|
"@babel/plugin-external-helpers": "^7.14.5",
|
|
107
113
|
"@babel/plugin-syntax-jsx": "^7.14.5",
|
|
108
114
|
"@babel/preset-env": "^7.13.9",
|
|
@@ -125,7 +131,7 @@
|
|
|
125
131
|
"@testing-library/react": "^11.1.0",
|
|
126
132
|
"@testing-library/user-event": "^12.1.10",
|
|
127
133
|
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.3",
|
|
128
|
-
"babel-jest": "^
|
|
134
|
+
"babel-jest": "^27.5.1",
|
|
129
135
|
"better-docs": "^2.3.2",
|
|
130
136
|
"canvas": "^2.7.0",
|
|
131
137
|
"enzyme": "^3.11.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-ignore: TS export Problem to be fixed upstream
|
|
2
|
-
import maplibregl from "maplibre-gl
|
|
2
|
+
import maplibregl from "!maplibre-gl";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Creates a MapLibre-gl-js instance and offers all of the native MapLibre functions and properties as well as additional functionality such as element registration & cleanup and more events.
|
|
@@ -413,7 +413,7 @@ const MapLibreGlWrapper = function (props) {
|
|
|
413
413
|
|
|
414
414
|
this.addNativeMaplibreFunctionsAndProps = () => {
|
|
415
415
|
// add MapLibre-gl functions
|
|
416
|
-
Object.
|
|
416
|
+
Object.getOwnPropertyNames(Object.getPrototypeOf(this.map)).forEach((item) => {
|
|
417
417
|
if (typeof this[item] === "undefined") {
|
|
418
418
|
this[item] = (...props) => self.map[item](...props);
|
|
419
419
|
}
|
|
@@ -504,6 +504,10 @@ const MapLibreGlWrapper = function (props) {
|
|
|
504
504
|
self.wrapper.refreshViewport();
|
|
505
505
|
self.wrapper.fire("viewportchange");
|
|
506
506
|
|
|
507
|
+
self.map.on("load", () => {
|
|
508
|
+
self.addNativeMaplibreFunctionsAndProps();
|
|
509
|
+
});
|
|
510
|
+
|
|
507
511
|
self.map.on("move", () => {
|
|
508
512
|
self.wrapper.viewportState = self.wrapper.getViewport();
|
|
509
513
|
self.wrapper.fire("viewportchange");
|
|
@@ -297,7 +297,7 @@ describe("MapLibreGlWrapper - event tests", () => {
|
|
|
297
297
|
);
|
|
298
298
|
|
|
299
299
|
// MapLibreGlWrapper now subscribes to "data", "move" events on its own
|
|
300
|
-
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(
|
|
300
|
+
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5);
|
|
301
301
|
});
|
|
302
302
|
|
|
303
303
|
it("should remove an event using off from MapLibreGl using MapLibreGlWrapper.cleanup(componentId)", async () => {
|
|
@@ -310,7 +310,7 @@ describe("MapLibreGlWrapper - event tests", () => {
|
|
|
310
310
|
);
|
|
311
311
|
|
|
312
312
|
// MapLibreGlWrapper now subscribes to "data", "move" events on its own
|
|
313
|
-
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(
|
|
313
|
+
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5);
|
|
314
314
|
|
|
315
315
|
wrapper.find(".toggle_children_are_visible").simulate("click");
|
|
316
316
|
|
|
@@ -327,7 +327,7 @@ describe("MapLibreGlWrapper - event tests", () => {
|
|
|
327
327
|
);
|
|
328
328
|
|
|
329
329
|
// MapLibreGlWrapper now subscribes to "data", "move" events on its own
|
|
330
|
-
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(
|
|
330
|
+
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(7);
|
|
331
331
|
|
|
332
332
|
wrapper.find(".toggle_children_are_visible").simulate("click");
|
|
333
333
|
|
|
@@ -82,7 +82,7 @@ describe("<MlFeatureEditor>", () => {
|
|
|
82
82
|
);
|
|
83
83
|
|
|
84
84
|
// MapLibreGlWrapper now subscribes to "data", "move" events on its own
|
|
85
|
-
await waitFor(() => expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(
|
|
85
|
+
await waitFor(() => expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(6));
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
it("should deregister 2 event listeners to the maplibre instance", async () => {
|
|
@@ -93,7 +93,7 @@ describe("<MlFeatureEditor>", () => {
|
|
|
93
93
|
);
|
|
94
94
|
|
|
95
95
|
// MapLibreGlWrapper now subscribes to "data", "move" events on its own
|
|
96
|
-
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(
|
|
96
|
+
expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(6);
|
|
97
97
|
|
|
98
98
|
wrapper.find(".toggle_layer_visible").simulate("click");
|
|
99
99
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, { useEffect, useState, useCallback } from "react";
|
|
1
|
+
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import useMap from "../../hooks/useMap";
|
|
4
4
|
|
|
5
5
|
import Button from "@mui/material/Button";
|
|
6
|
-
import
|
|
7
|
-
import { point, circle } from "@turf/turf";
|
|
6
|
+
import GpsFixedIcon from "@mui/icons-material/GpsFixed";
|
|
7
|
+
import { point, circle, lineArc } from "@turf/turf";
|
|
8
8
|
import MlGeoJsonLayer from "../MlGeoJsonLayer/MlGeoJsonLayer";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -20,10 +20,10 @@ const MlFollowGps = (props) => {
|
|
|
20
20
|
const mapHook = useMap({ mapId: props.mapId, waitForLayer: props.insertBeforeLayer });
|
|
21
21
|
|
|
22
22
|
const [isFollowed, setIsFollowed] = useState(false);
|
|
23
|
-
const [
|
|
23
|
+
const [userLocationGeoJson, setUserLocationGeoJson] = useState(undefined);
|
|
24
24
|
const [locationAccessDenied, setLocationAccessDenied] = useState(false);
|
|
25
|
-
|
|
26
25
|
const [accuracyGeoJson, setAccuracyGeoJson] = useState();
|
|
26
|
+
const [deviceOrientation, setDeviceOrientation] = useState(0);
|
|
27
27
|
|
|
28
28
|
const getLocationSuccess = useCallback(
|
|
29
29
|
(pos) => {
|
|
@@ -35,11 +35,12 @@ const MlFollowGps = (props) => {
|
|
|
35
35
|
speed: 1,
|
|
36
36
|
curve: 1,
|
|
37
37
|
});
|
|
38
|
+
if (!props.showUserLocation) return;
|
|
38
39
|
const geoJsonPoint = point([pos.coords.longitude, pos.coords.latitude]);
|
|
39
|
-
|
|
40
|
+
setUserLocationGeoJson(geoJsonPoint);
|
|
40
41
|
setAccuracyGeoJson(circle(geoJsonPoint, pos.coords.accuracy / 1000));
|
|
41
42
|
},
|
|
42
|
-
[mapHook.map]
|
|
43
|
+
[mapHook.map, props]
|
|
43
44
|
);
|
|
44
45
|
|
|
45
46
|
const getLocationError = (err) => {
|
|
@@ -47,6 +48,37 @@ const MlFollowGps = (props) => {
|
|
|
47
48
|
setLocationAccessDenied(true);
|
|
48
49
|
};
|
|
49
50
|
|
|
51
|
+
const orientationCone = useMemo(
|
|
52
|
+
() => {
|
|
53
|
+
if (!userLocationGeoJson) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
let radius = 0.02;
|
|
57
|
+
let bearing1 = deviceOrientation - 15;
|
|
58
|
+
let bearing2 = deviceOrientation + 15;
|
|
59
|
+
const options = {steps: 65};
|
|
60
|
+
let arc = lineArc(userLocationGeoJson, radius, bearing1, bearing2, options);
|
|
61
|
+
let copy = arc;
|
|
62
|
+
copy.geometry.coordinates.push(userLocationGeoJson.geometry.coordinates);
|
|
63
|
+
copy.geometry.coordinates.slice(0, 0, userLocationGeoJson.geometry.coordinates);
|
|
64
|
+
return copy;
|
|
65
|
+
}, [deviceOrientation, userLocationGeoJson]
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const handleOrientation = (event) => {
|
|
69
|
+
setDeviceOrientation(-event.alpha)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (isFollowed) {
|
|
74
|
+
let _handleOrientation = handleOrientation;
|
|
75
|
+
window.addEventListener('deviceorientation', _handleOrientation)
|
|
76
|
+
return () => {
|
|
77
|
+
window.removeEventListener('deviceorientation', _handleOrientation)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}, [isFollowed]);
|
|
81
|
+
|
|
50
82
|
useEffect(() => {
|
|
51
83
|
if (!mapHook.map) return;
|
|
52
84
|
|
|
@@ -57,11 +89,11 @@ const MlFollowGps = (props) => {
|
|
|
57
89
|
navigator.geolocation.clearWatch(_watchId);
|
|
58
90
|
};
|
|
59
91
|
}
|
|
60
|
-
}, [isFollowed, getLocationSuccess]);
|
|
92
|
+
}, [mapHook.map, isFollowed, getLocationSuccess]);
|
|
61
93
|
|
|
62
94
|
return (
|
|
63
95
|
<>
|
|
64
|
-
{isFollowed &&
|
|
96
|
+
{isFollowed && userLocationGeoJson && (
|
|
65
97
|
<MlGeoJsonLayer
|
|
66
98
|
geojson={accuracyGeoJson}
|
|
67
99
|
type={"fill"}
|
|
@@ -74,9 +106,22 @@ const MlFollowGps = (props) => {
|
|
|
74
106
|
/>
|
|
75
107
|
)}
|
|
76
108
|
|
|
77
|
-
{isFollowed &&
|
|
109
|
+
{isFollowed && orientationCone && (
|
|
78
110
|
<MlGeoJsonLayer
|
|
79
|
-
geojson={
|
|
111
|
+
geojson={orientationCone}
|
|
112
|
+
type={"fill"}
|
|
113
|
+
paint={{
|
|
114
|
+
"fill-color": "#0000ff",
|
|
115
|
+
"fill-antialias": false,
|
|
116
|
+
"fill-opacity": 0.3,
|
|
117
|
+
}}
|
|
118
|
+
insertBeforeLayer={props.insertBeforeLayer}
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
|
|
122
|
+
{isFollowed && userLocationGeoJson && (
|
|
123
|
+
<MlGeoJsonLayer
|
|
124
|
+
geojson={userLocationGeoJson}
|
|
80
125
|
type={"circle"}
|
|
81
126
|
paint={{
|
|
82
127
|
"circle-color": "#009ee0",
|
|
@@ -97,7 +142,7 @@ const MlFollowGps = (props) => {
|
|
|
97
142
|
}}
|
|
98
143
|
>
|
|
99
144
|
{" "}
|
|
100
|
-
<
|
|
145
|
+
<GpsFixedIcon sx={{ fontSize: props.style.fontSize }} />{" "}
|
|
101
146
|
</Button>
|
|
102
147
|
</>
|
|
103
148
|
);
|
|
@@ -121,6 +166,9 @@ MlFollowGps.defaultProps = {
|
|
|
121
166
|
},
|
|
122
167
|
onColor: "#ececec",
|
|
123
168
|
offColor: "#666",
|
|
169
|
+
showAccuracyCircle: true,
|
|
170
|
+
showUserLocation: true,
|
|
171
|
+
showOrientation: true
|
|
124
172
|
};
|
|
125
173
|
|
|
126
174
|
MlFollowGps.propTypes = {
|
|
@@ -152,5 +200,19 @@ MlFollowGps.propTypes = {
|
|
|
152
200
|
* https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#fill
|
|
153
201
|
*/
|
|
154
202
|
circlePaint: PropTypes.object,
|
|
203
|
+
/**
|
|
204
|
+
* By default, if showUserLocation is true, a transparent circle will be drawn around the user location
|
|
205
|
+
* indicating the accuracy (95% confidence level) of the user's location. Set to false to disable.
|
|
206
|
+
*/
|
|
207
|
+
showAccuracyCircle: PropTypes.bool,
|
|
208
|
+
/**
|
|
209
|
+
* By default a dot will be shown on the map at the user's location. Set to false to disable.
|
|
210
|
+
*/
|
|
211
|
+
showUserLocation: PropTypes.bool,
|
|
212
|
+
/**
|
|
213
|
+
* By default a cone will be shown on the map at the user's location to indicate the device's orientation.
|
|
214
|
+
* Set to false to disable.
|
|
215
|
+
*/
|
|
216
|
+
showOrientation: PropTypes.bool,
|
|
155
217
|
};
|
|
156
218
|
export default MlFollowGps;
|
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
import React, {useContext, useRef, useEffect, useState} from "react";
|
|
1
|
+
import React, { useContext, useRef, useEffect, useState } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
|
-
import {
|
|
4
|
-
import {bbox} from "@turf/turf";
|
|
3
|
+
import { bbox } from "@turf/turf";
|
|
5
4
|
import Divider from "@mui/material/Divider";
|
|
6
5
|
import Typography from "@mui/material/Typography";
|
|
7
6
|
import Drawer from "@mui/material/Drawer";
|
|
8
7
|
import IconButton from "@mui/material/IconButton";
|
|
9
8
|
import InfoIcon from "@mui/icons-material/Info";
|
|
10
9
|
import FileCopy from "@mui/icons-material/FileCopy";
|
|
11
|
-
import {Popup} from "maplibre-gl";
|
|
10
|
+
import { Popup } from "maplibre-gl";
|
|
12
11
|
import List from "@mui/material/List";
|
|
13
12
|
import ListItem from "@mui/material/ListItem";
|
|
14
13
|
import ListItemText from "@mui/material/ListItemText";
|
|
15
14
|
import GeoJsonContext from "./util/GeoJsonContext";
|
|
16
15
|
import toGeoJSON from "./gpxConverter";
|
|
17
16
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
|
18
|
-
|
|
19
|
-
import {v4 as uuidv4} from "uuid";
|
|
17
|
+
import useMap from "../../hooks/useMap";
|
|
20
18
|
|
|
21
19
|
/**
|
|
22
20
|
* MlGPXViewer returns a dropzone and a button to load a GPX Track into the map.
|
|
@@ -25,11 +23,8 @@ import {v4 as uuidv4} from "uuid";
|
|
|
25
23
|
*/
|
|
26
24
|
const MlGPXViewer = (props) => {
|
|
27
25
|
const dataSource = useContext(GeoJsonContext);
|
|
28
|
-
const componentId = useRef((props.idPrefix ? props.idPrefix : "MlGpxViewer-") + uuidv4());
|
|
29
|
-
const mapContext = useContext(MapContext);
|
|
30
|
-
const mapId = props.mapId;
|
|
31
26
|
const initializedRef = useRef(false);
|
|
32
|
-
const
|
|
27
|
+
const mapHook = useMap({ mapId: props.mapId, waitForLayer: props.insertBeforeLayer });
|
|
33
28
|
const sourceName = "import-source";
|
|
34
29
|
const layerNameLines = "importer-layer-lines";
|
|
35
30
|
const layerNamePoints = "importer-layer-points";
|
|
@@ -49,36 +44,19 @@ const MlGPXViewer = (props) => {
|
|
|
49
44
|
);
|
|
50
45
|
|
|
51
46
|
useEffect(() => {
|
|
52
|
-
|
|
53
|
-
let _popup = popup.current;
|
|
54
|
-
return () => {
|
|
55
|
-
// This is the cleanup function, it is called when this react component is removed from react-dom
|
|
56
|
-
if (mapRef.current) {
|
|
57
|
-
mapRef.current.cleanup(_componentId);
|
|
58
|
-
|
|
59
|
-
mapRef.current.getCanvas().style.cursor = "";
|
|
60
|
-
|
|
61
|
-
mapRef.current = null;
|
|
62
|
-
}
|
|
63
|
-
_popup.remove();
|
|
64
|
-
};
|
|
65
|
-
}, []);
|
|
66
|
-
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
if (!mapContext.mapExists(mapId) || initializedRef.current) return;
|
|
47
|
+
if (!mapHook.map || initializedRef.current) return;
|
|
69
48
|
|
|
70
49
|
initializedRef.current = true;
|
|
71
|
-
mapRef.current = mapContext.getMap(mapId);
|
|
72
50
|
|
|
73
|
-
|
|
51
|
+
mapHook.map.addSource(
|
|
74
52
|
sourceName,
|
|
75
53
|
{
|
|
76
54
|
type: "geojson",
|
|
77
55
|
data: dataSource.data,
|
|
78
56
|
},
|
|
79
|
-
componentId
|
|
57
|
+
mapHook.componentId
|
|
80
58
|
);
|
|
81
|
-
|
|
59
|
+
mapHook.map.addLayer(
|
|
82
60
|
{
|
|
83
61
|
id: layerNameLines,
|
|
84
62
|
source: sourceName,
|
|
@@ -89,9 +67,9 @@ const MlGPXViewer = (props) => {
|
|
|
89
67
|
},
|
|
90
68
|
},
|
|
91
69
|
props.insertBeforeLayer,
|
|
92
|
-
componentId
|
|
70
|
+
mapHook.componentId
|
|
93
71
|
);
|
|
94
|
-
|
|
72
|
+
mapHook.map.addLayer(
|
|
95
73
|
{
|
|
96
74
|
id: layerNamePoints,
|
|
97
75
|
source: sourceName,
|
|
@@ -103,40 +81,49 @@ const MlGPXViewer = (props) => {
|
|
|
103
81
|
filter: ["==", "$type", "Point"],
|
|
104
82
|
},
|
|
105
83
|
props.insertBeforeLayer,
|
|
106
|
-
componentId
|
|
84
|
+
mapHook.componentId
|
|
107
85
|
);
|
|
108
86
|
|
|
109
87
|
[layerNameLines, layerNamePoints].forEach((layerName) => {
|
|
110
|
-
|
|
88
|
+
mapHook.map.setLayoutProperty(layerName, "visibility", "visible");
|
|
111
89
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
90
|
+
mapHook.map.on(
|
|
91
|
+
"mouseenter",
|
|
92
|
+
layerNamePoints,
|
|
93
|
+
(e) => {
|
|
94
|
+
// Change the cursor style as a UI indicator.
|
|
95
|
+
|
|
96
|
+
const coordinates = e.features[0].geometry.coordinates.slice();
|
|
97
|
+
//const description = e.features[0].properties.desc;
|
|
98
|
+
const name = e.features[0].properties.name;
|
|
99
|
+
|
|
100
|
+
// Ensure that if the map is zoomed out such that multiple
|
|
101
|
+
// copies of the feature are visible, the popup appears
|
|
102
|
+
// over the copy being pointed to.
|
|
103
|
+
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
|
|
104
|
+
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
|
|
105
|
+
}
|
|
126
106
|
|
|
127
|
-
|
|
107
|
+
// Populate the popup and set its coordinates
|
|
128
108
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
109
|
+
// based on the feature found.
|
|
110
|
+
popup.current.setLngLat(coordinates).setHTML(name).addTo(mapHook.map);
|
|
111
|
+
},
|
|
112
|
+
mapHook.componentId
|
|
113
|
+
);
|
|
132
114
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
115
|
+
mapHook.map.on(
|
|
116
|
+
"mouseleave",
|
|
117
|
+
"places",
|
|
118
|
+
function () {
|
|
119
|
+
mapHook.map.getCanvas().style.cursor = "";
|
|
120
|
+
popup.current.remove();
|
|
121
|
+
},
|
|
122
|
+
mapHook.componentId
|
|
123
|
+
);
|
|
137
124
|
|
|
138
|
-
|
|
139
|
-
}, [
|
|
125
|
+
mapHook.map.setZoom(10);
|
|
126
|
+
}, [mapHook.map]);
|
|
140
127
|
|
|
141
128
|
useEffect(() => {
|
|
142
129
|
const dropZoneCurrent = dropZone.current;
|
|
@@ -162,9 +149,8 @@ const MlGPXViewer = (props) => {
|
|
|
162
149
|
return () => {
|
|
163
150
|
window.removeEventListener("dragenter", raiseDropZoneAndStopDefault);
|
|
164
151
|
window.removeEventListener("dragover", stopDefault);
|
|
165
|
-
window.removeEventListener("drop", stopDefault);
|
|
166
152
|
dropZoneCurrent.removeEventListener("dragleave", lowerDropZone);
|
|
167
|
-
window.removeEventListener("drop",
|
|
153
|
+
window.removeEventListener("drop", lowerDropZoneAndStopDefault);
|
|
168
154
|
};
|
|
169
155
|
});
|
|
170
156
|
|
|
@@ -174,12 +160,12 @@ const MlGPXViewer = (props) => {
|
|
|
174
160
|
};
|
|
175
161
|
|
|
176
162
|
useEffect(() => {
|
|
177
|
-
if (!
|
|
163
|
+
if (!mapHook.map) return;
|
|
178
164
|
|
|
179
165
|
const visibility = props.visible ? "visible" : "none";
|
|
180
166
|
|
|
181
167
|
[layerNameLines, layerNamePoints].forEach((layerName) => {
|
|
182
|
-
|
|
168
|
+
mapHook.map.setLayoutProperty(layerName, "visibility", visibility);
|
|
183
169
|
});
|
|
184
170
|
}, [props.visible]);
|
|
185
171
|
|
|
@@ -205,7 +191,7 @@ const MlGPXViewer = (props) => {
|
|
|
205
191
|
};
|
|
206
192
|
|
|
207
193
|
const addGPXToMap = (gpxAsString) => {
|
|
208
|
-
if (!
|
|
194
|
+
if (!mapHook.map) return;
|
|
209
195
|
try {
|
|
210
196
|
setMetaData([]);
|
|
211
197
|
const domParser = new DOMParser();
|
|
@@ -229,9 +215,9 @@ const MlGPXViewer = (props) => {
|
|
|
229
215
|
});
|
|
230
216
|
const data = toGeoJSON.gpx(gpxDoc);
|
|
231
217
|
dataSource.setData(data);
|
|
232
|
-
|
|
218
|
+
mapHook.map.getSource(sourceName).setData(data);
|
|
233
219
|
const bounds = bbox(data);
|
|
234
|
-
|
|
220
|
+
mapHook.map.fitBounds(bounds);
|
|
235
221
|
} catch (e) {
|
|
236
222
|
console.log(e);
|
|
237
223
|
}
|
|
@@ -257,15 +243,17 @@ const MlGPXViewer = (props) => {
|
|
|
257
243
|
};
|
|
258
244
|
return (
|
|
259
245
|
<>
|
|
260
|
-
<div
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
246
|
+
<div
|
|
247
|
+
style={{
|
|
248
|
+
position: "fixed",
|
|
249
|
+
right: "5px",
|
|
250
|
+
bottom: mediaIsMobile ? "40px" : "25px",
|
|
251
|
+
display: "flex",
|
|
252
|
+
flexDirection: "column",
|
|
253
|
+
gap: "5px",
|
|
254
|
+
zIndex: 1000,
|
|
255
|
+
}}
|
|
256
|
+
>
|
|
269
257
|
<IconButton
|
|
270
258
|
onClick={manualUpload}
|
|
271
259
|
style={{
|
|
@@ -279,9 +267,9 @@ const MlGPXViewer = (props) => {
|
|
|
279
267
|
type="file"
|
|
280
268
|
id="input"
|
|
281
269
|
multiple
|
|
282
|
-
style={{display: "none"}}
|
|
270
|
+
style={{ display: "none" }}
|
|
283
271
|
></input>
|
|
284
|
-
<FileCopy/>
|
|
272
|
+
<FileCopy />
|
|
285
273
|
</IconButton>
|
|
286
274
|
<IconButton
|
|
287
275
|
onClick={toogleDrawer}
|
|
@@ -290,7 +278,7 @@ const MlGPXViewer = (props) => {
|
|
|
290
278
|
}}
|
|
291
279
|
size="large"
|
|
292
280
|
>
|
|
293
|
-
<InfoIcon/>
|
|
281
|
+
<InfoIcon />
|
|
294
282
|
</IconButton>
|
|
295
283
|
</div>
|
|
296
284
|
<Drawer variant="persistent" anchor="left" open={open}>
|
|
@@ -304,11 +292,11 @@ const MlGPXViewer = (props) => {
|
|
|
304
292
|
>
|
|
305
293
|
Informationen zur Route
|
|
306
294
|
</Typography>
|
|
307
|
-
<Divider/>
|
|
295
|
+
<Divider />
|
|
308
296
|
<List>
|
|
309
297
|
{metaData.map((item) => (
|
|
310
298
|
<ListItem key={`item--${item.id}`}>
|
|
311
|
-
<ListItemText primary={item.value}/>
|
|
299
|
+
<ListItemText primary={item.value} />
|
|
312
300
|
</ListItem>
|
|
313
301
|
))}
|
|
314
302
|
</List>
|
|
@@ -350,7 +338,7 @@ MlGPXViewer.defaultProps = {
|
|
|
350
338
|
|
|
351
339
|
MlGPXViewer.propTypes = {
|
|
352
340
|
/**
|
|
353
|
-
* Id of the target MapLibre instance in
|
|
341
|
+
* Id of the target MapLibre instance in mapHook
|
|
354
342
|
*/
|
|
355
343
|
mapId: PropTypes.string,
|
|
356
344
|
/**
|