Skip to content

Commit

Permalink
Merge pull request #1243 from jcardus/speed-based-color
Browse files Browse the repository at this point in the history
draw route with speed based color
  • Loading branch information
tananaev authored Jun 19, 2024
2 parents c42bb2b + e050151 commit cecc9dd
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 19 deletions.
23 changes: 23 additions & 0 deletions src/common/util/colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { decomposeColor } from '@mui/material';

export const interpolateColor = (color1, color2, factor) => {
if (factor > 1) factor = 1;
if (factor < 0) factor = 0;

const c1 = decomposeColor(color1).values;
const c2 = decomposeColor(color2).values;

const r = Math.round(c1[0] + factor * (c2[0] - c1[0]));
const g = Math.round(c1[1] + factor * (c2[1] - c1[1]));
const b = Math.round(c1[2] + factor * (c2[2] - c1[2]));

return `rgb(${r}, ${g}, ${b})`;
};

export const getSpeedColor = (color1, color2, color3, speed, max) => {
const factor = speed / max;
if (factor <= 0.5) {
return interpolateColor(color1, color2, factor * 2);
}
return interpolateColor(color2, color3, (factor - 0.5) * 2);
};
29 changes: 20 additions & 9 deletions src/map/MapRoutePath.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useTheme } from '@mui/styles';
import { useId, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { map } from './core/MapView';
import { getSpeedColor } from '../common/util/colors';

const MapRoutePath = ({ name, positions, coordinates }) => {
const id = useId();
Expand Down Expand Up @@ -79,16 +80,26 @@ const MapRoutePath = ({ name, positions, coordinates }) => {
if (!coordinates) {
coordinates = positions.map((item) => [item.longitude, item.latitude]);
}
const maxSpeed = positions.map((p) => p.speed).reduce((a, b) => Math.max(a, b), -Infinity);
const features = [];
for (let i = 0; i < positions.length - 1; i += 1) {
const p1 = positions[i];
const p2 = positions[i + 1];
features.push({
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [[p1.longitude, p1.latitude], [p2.longitude, p2.latitude]],
},
properties: {
color: getSpeedColor(theme.palette.success.main, theme.palette.warning.main, theme.palette.error.main, p1.speed, maxSpeed),
},
});
}

map.getSource(id)?.setData({
type: 'Feature',
geometry: {
type: 'LineString',
coordinates,
},
properties: {
name,
color: reportColor,
},
type: 'FeatureCollection',
features,
});
}, [theme, positions, coordinates, reportColor]);

Expand Down
15 changes: 11 additions & 4 deletions src/map/MapRoutePoints.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { useId, useCallback, useEffect } from 'react';
import { useTheme } from '@mui/styles';
import { map } from './core/MapView';
import { getSpeedColor } from '../common/util/colors';

const MapRoutePoints = ({ positions, onClick }) => {
const id = useId();
const theme = useTheme();

const onMouseEnter = () => map.getCanvas().style.cursor = 'pointer';
const onMouseLeave = () => map.getCanvas().style.cursor = '';
Expand All @@ -27,11 +30,13 @@ const MapRoutePoints = ({ positions, onClick }) => {
id,
type: 'symbol',
source: id,
paint: {
'text-color': ['get', 'color'],
},
layout: {
'icon-image': 'arrow',
'icon-allow-overlap': true,
'icon-rotate': ['get', 'rotation'],
'icon-rotation-alignment': 'map',
'text-field': '▲',
'text-allow-overlap': true,
'text-rotate': ['get', 'rotation'],
},
});

Expand All @@ -54,6 +59,7 @@ const MapRoutePoints = ({ positions, onClick }) => {
}, [onMarkerClick]);

useEffect(() => {
const maxSpeed = positions.map((p) => p.speed).reduce((a, b) => Math.max(a, b), -Infinity);
map.getSource(id)?.setData({
type: 'FeatureCollection',
features: positions.map((position, index) => ({
Expand All @@ -66,6 +72,7 @@ const MapRoutePoints = ({ positions, onClick }) => {
index,
id: position.id,
rotation: position.course,
color: getSpeedColor(theme.palette.success.main, theme.palette.warning.main, theme.palette.error.main, position.speed, maxSpeed),
},
})),
});
Expand Down
2 changes: 0 additions & 2 deletions src/map/core/preloadImages.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { grey } from '@mui/material/colors';
import createPalette from '@mui/material/styles/createPalette';
import { loadImage, prepareIcon } from './mapUtil';

import arrowSvg from '../../resources/images/arrow.svg';
import directionSvg from '../../resources/images/direction.svg';
import backgroundSvg from '../../resources/images/background.svg';
import animalSvg from '../../resources/images/icon/animal.svg';
Expand Down Expand Up @@ -65,7 +64,6 @@ export default async () => {
const background = await loadImage(backgroundSvg);
mapImages.background = await prepareIcon(background);
mapImages.direction = await prepareIcon(await loadImage(directionSvg));
mapImages.arrow = await prepareIcon(await loadImage(arrowSvg));
await Promise.all(Object.keys(mapIcons).map(async (category) => {
const results = [];
['info', 'success', 'error', 'neutral'].forEach((color) => {
Expand Down
4 changes: 0 additions & 4 deletions src/resources/images/arrow.svg

This file was deleted.

0 comments on commit cecc9dd

Please sign in to comment.