aboutsummaryrefslogtreecommitdiff
path: root/modern/src
diff options
context:
space:
mode:
Diffstat (limited to 'modern/src')
-rw-r--r--modern/src/main/MainPage.js5
-rw-r--r--modern/src/map/MapDirection.js57
-rw-r--r--modern/src/map/MapPositions.js2
-rw-r--r--modern/src/map/core/preloadImages.js2
-rw-r--r--modern/src/resources/images/direction.svg4
5 files changed, 68 insertions, 2 deletions
diff --git a/modern/src/main/MainPage.js b/modern/src/main/MainPage.js
index 5a35dcef..27e2631f 100644
--- a/modern/src/main/MainPage.js
+++ b/modern/src/main/MainPage.js
@@ -31,6 +31,7 @@ import usePersistedState from '../common/util/usePersistedState';
import MapLiveRoutes from '../map/main/MapLiveRoutes';
import { useDeviceReadonly } from '../common/util/permissions';
import MapPositions from '../map/MapPositions';
+import MapDirection from '../map/MapDirection';
const useStyles = makeStyles((theme) => ({
root: {
@@ -135,6 +136,7 @@ const MainPage = () => {
const selectedDeviceId = useSelector((state) => state.devices.selectedId);
const positions = useSelector((state) => Object.values(state.positions.items));
+ const selectedPosition = positions.find((position) => selectedDeviceId && position.deviceId === selectedDeviceId);
const [searchKeyword, setSearchKeyword] = useState('');
const [collapsed, setCollapsed] = useState(false);
@@ -162,6 +164,9 @@ const MainPage = () => {
<MapAccuracy />
{mapLiveRoutes && <MapLiveRoutes />}
<MapPositions positions={positions} onClick={onClick} showStatus />
+ {selectedPosition && selectedPosition.course && (
+ <MapDirection position={selectedPosition} />
+ )}
<MapDefaultCamera />
<MapSelectedDevice />
<PoiMap />
diff --git a/modern/src/map/MapDirection.js b/modern/src/map/MapDirection.js
new file mode 100644
index 00000000..251fa962
--- /dev/null
+++ b/modern/src/map/MapDirection.js
@@ -0,0 +1,57 @@
+import { useEffect } from 'react';
+
+import { map } from './core/MapView';
+
+const MapDirection = ({ position }) => {
+ const id = 'directions';
+
+ useEffect(() => {
+ map.addSource(id, {
+ type: 'geojson',
+ data: {
+ type: 'FeatureCollection',
+ features: [],
+ },
+ });
+ map.addLayer({
+ id,
+ type: 'symbol',
+ source: id,
+ layout: {
+ 'icon-image': 'direction',
+ 'icon-rotate': ['get', 'rotation'],
+ },
+ });
+
+ return () => {
+ if (map.getLayer(id)) {
+ map.removeLayer(id);
+ }
+ if (map.getSource(id)) {
+ map.removeSource(id);
+ }
+ };
+ }, []);
+
+ useEffect(() => {
+ map.getSource(id).setData({
+ type: 'FeatureCollection',
+ features: [
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [position.longitude, position.latitude],
+ },
+ properties: {
+ rotation: position.course,
+ },
+ },
+ ],
+ });
+ }, [position]);
+
+ return null;
+};
+
+export default MapDirection;
diff --git a/modern/src/map/MapPositions.js b/modern/src/map/MapPositions.js
index 4b53255a..070ec0c8 100644
--- a/modern/src/map/MapPositions.js
+++ b/modern/src/map/MapPositions.js
@@ -101,8 +101,6 @@ const MapPositions = ({ positions, onClick, showStatus }) => {
map.on('click', clusters, onClusterClick);
return () => {
- Array.from(map.getContainer().getElementsByClassName('maplibregl-popup')).forEach((el) => el.remove());
-
map.off('mouseenter', id, onMouseEnter);
map.off('mouseleave', id, onMouseLeave);
map.off('mouseenter', clusters, onMouseEnter);
diff --git a/modern/src/map/core/preloadImages.js b/modern/src/map/core/preloadImages.js
index e0cf42f2..c66ec5de 100644
--- a/modern/src/map/core/preloadImages.js
+++ b/modern/src/map/core/preloadImages.js
@@ -1,6 +1,7 @@
import palette from '../../common/theme/palette';
import { loadImage, prepareIcon } from './mapUtil';
+import directionSvg from '../../resources/images/direction.svg';
import backgroundSvg from '../../resources/images/background.svg';
import animalSvg from '../../resources/images/icon/animal.svg';
import bicycleSvg from '../../resources/images/icon/bicycle.svg';
@@ -53,6 +54,7 @@ export const mapImages = {};
export default async () => {
const background = await loadImage(backgroundSvg);
mapImages.background = await prepareIcon(background);
+ mapImages.direction = await prepareIcon(await loadImage(directionSvg));
await Promise.all(Object.keys(mapIcons).map(async (category) => {
const results = [];
['positive', 'negative', 'neutral'].forEach((color) => {
diff --git a/modern/src/resources/images/direction.svg b/modern/src/resources/images/direction.svg
new file mode 100644
index 00000000..9f2874fc
--- /dev/null
+++ b/modern/src/resources/images/direction.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="56" height="56" version="1.1" viewBox="0 0 11.667 11.667" xmlns="http://www.w3.org/2000/svg">
+ <path transform="rotate(45)" d="m4.6303-3.6193v1.2838a4.3079 4.3079 0 0 1 0.57314-0.71067 4.3079 4.3079 0 0 1 0.7101-0.57314h-1.2832z" fill="#283593"/>
+</svg>