Skip to content

Commit ece7ed5

Browse files
committed
Adjust map route editor styles
This commit aims to make the route editor visuals better. - Less clutter on the map - Changes in the edit layer functionality
1 parent fab76b8 commit ece7ed5

5 files changed

Lines changed: 117 additions & 52 deletions

File tree

315 Bytes
Loading

ui/src/components/map/DrawControl.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from 'react';
99
import { ControlPosition, IControl, useControl } from 'react-map-gl/maplibre';
1010
import { styles } from './routes/editorStyles';
11+
import { joreDrawModes } from './utils/drawModeUtils';
1112

1213
type DrawControlProps = ConstructorParameters<typeof MapboxDraw>[0] & {
1314
readonly position?: ControlPosition;
@@ -32,7 +33,12 @@ const DrawControlComponent: ForwardRefRenderFunction<
3233
> = (props, ref) => {
3334
const { onCreate, onModeChange, onUpdate, position } = props;
3435
const drawRef = useControl<MapLibreMapboxDraw>(
35-
() => new MapboxDraw({ styles, ...props }) as MapLibreMapboxDraw,
36+
() =>
37+
new MapboxDraw({
38+
styles,
39+
...props,
40+
modes: joreDrawModes,
41+
}) as MapLibreMapboxDraw,
3642
({ map }) => {
3743
map.on('draw.create', onCreate);
3844
map.on('draw.update', onUpdate);
Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
const FEATURE_INACTIVE_COLOR = '#696969'; // Dark grey
2-
const FEATURE_ACTIVE_COLOR = FEATURE_INACTIVE_COLOR;
1+
import { theme } from '../../../generated/theme';
32

43
export const ACTIVE_LINE_STROKE_ID = 'active-line-stroke';
54

@@ -13,57 +12,31 @@ export const styles = [
1312
'line-join': 'round',
1413
},
1514
paint: {
16-
'line-color': FEATURE_INACTIVE_COLOR,
17-
'line-dasharray': [1.2, 0.8],
18-
'line-width': 8,
15+
'line-color': theme.colors.hslDark80,
16+
'line-dasharray': [1, 0.5],
17+
'line-width': 2,
1918
},
2019
},
2120
{
2221
id: 'gl-draw-polygon-midpoint',
23-
type: 'circle',
22+
type: 'symbol',
2423
filter: ['all', ['==', '$type', 'Point'], ['==', 'meta', 'midpoint']],
25-
paint: {
26-
'circle-radius': 8,
27-
'circle-color': FEATURE_INACTIVE_COLOR,
28-
},
29-
},
30-
{
31-
id: 'gl-draw-line-vertex-halo-inactive',
32-
type: 'circle',
33-
filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
34-
paint: {
35-
'circle-radius': 12,
36-
'circle-color': FEATURE_INACTIVE_COLOR,
24+
layout: {
25+
'icon-image': 'route_vector_icon',
26+
'icon-size': ['interpolate', ['linear'], ['zoom'], 8, 0.11, 16, 0.2],
27+
'icon-allow-overlap': true,
28+
'icon-ignore-placement': true,
3729
},
3830
},
3931
{
4032
id: 'gl-draw-line-vertex-inactive',
41-
type: 'circle',
42-
filter: [
43-
'all',
44-
['==', 'meta', 'vertex'],
45-
['==', '$type', 'Point'],
46-
['!=', 'mode', 'static'],
47-
['!=', 'mode', 'simple_select'],
48-
],
49-
paint: {
50-
'circle-radius': 9,
51-
'circle-color': 'white',
52-
},
53-
},
54-
{
55-
id: 'gl-draw-line-vertex-active',
56-
type: 'circle',
57-
filter: [
58-
'all',
59-
['==', 'meta', 'vertex'],
60-
['==', '$type', 'Point'],
61-
['!=', 'mode', 'static'],
62-
['==', 'active', 'true'],
63-
],
64-
paint: {
65-
'circle-radius': 4,
66-
'circle-color': FEATURE_ACTIVE_COLOR,
33+
type: 'symbol',
34+
filter: ['all', ['==', 'meta', 'vertex'], ['==', '$type', 'Point']],
35+
layout: {
36+
'icon-image': 'route_vector_icon',
37+
'icon-size': ['interpolate', ['linear'], ['zoom'], 8, 0.17, 16, 0.27],
38+
'icon-allow-overlap': true,
39+
'icon-ignore-placement': true,
6740
},
6841
},
6942
];
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import MapboxDraw, {
2+
DrawCustomMode,
3+
DrawCustomModeThis,
4+
MapMouseEvent,
5+
MapTouchEvent,
6+
MapboxDrawOptions,
7+
} from '@mapbox/mapbox-gl-draw';
8+
9+
const defaultModes = MapboxDraw.modes;
10+
const directSelectMode = defaultModes.direct_select;
11+
const simpleSelectMode = defaultModes.simple_select;
12+
13+
type ObjectLikeState = { [key: string]: unknown };
14+
15+
// Change from simple_select to direct_select on feature click, to immediately show vertices with mid-points.
16+
// Default behavior is to first show vertices, then it requires another click to enter direct_select and show mid-points.
17+
// Internally onTap = onClick = function implementation()... by default.
18+
function onSimpleModeClick(
19+
this: DrawCustomModeThis & DrawCustomMode,
20+
state: ObjectLikeState,
21+
e: MapMouseEvent | MapTouchEvent,
22+
) {
23+
const isFeature = MapboxDraw.lib.CommonSelectors.isFeature(e);
24+
const featureId = e.featureTarget?.properties?.id;
25+
26+
if (isFeature && featureId) {
27+
this.changeMode('direct_select', { featureId });
28+
} else {
29+
simpleSelectMode.onClick?.call(this, state, e as MapMouseEvent);
30+
}
31+
}
32+
33+
// Disable vertex selection on click, enforce drag-only behavior.
34+
// This avoids reloading the edited line when clicking vertices.
35+
// Internally onTouchStart = onMouseDown = function implementation()... by default.
36+
function onDirectModeMouseDown(
37+
this: DrawCustomModeThis & DrawCustomMode,
38+
state: ObjectLikeState,
39+
e: MapMouseEvent | MapTouchEvent,
40+
) {
41+
const isVertex = MapboxDraw.lib.CommonSelectors.isVertex(e);
42+
43+
// This replaces onVertex code path from:
44+
// https://github.com/mapbox/mapbox-gl-draw/blob/eb42344e32ec884c6f15fe483ad1c9311c309a36/src/modes/direct_select.js#L51
45+
if (isVertex) {
46+
// Drag-only behavior: keep one vertex as drag target, skip click-selection visuals.
47+
const coordPath = e.featureTarget.properties?.coord_path;
48+
if (coordPath) {
49+
state.selectedCoordPaths = [coordPath];
50+
51+
// This calls a private function from the internal implementation from:
52+
// https://github.com/mapbox/mapbox-gl-draw/blob/eb42344e32ec884c6f15fe483ad1c9311c309a36/src/modes/direct_select.js#L30
53+
if (
54+
'startDragging' in directSelectMode &&
55+
typeof directSelectMode.startDragging === 'function'
56+
) {
57+
directSelectMode.startDragging.call(this, state, e);
58+
} else {
59+
throw new Error(
60+
'mapbox-gl-draw DirectDrawMode internal implementation changed! Expected to find function startDragging, but it does not exist!',
61+
);
62+
}
63+
}
64+
} else {
65+
directSelectMode.onMouseDown?.call(this, state, e as MapMouseEvent);
66+
}
67+
}
68+
69+
export const joreDrawModes: MapboxDrawOptions['modes'] = {
70+
...defaultModes,
71+
simple_select: {
72+
...simpleSelectMode,
73+
onClick: onSimpleModeClick,
74+
onTap: onSimpleModeClick,
75+
},
76+
direct_select: {
77+
...directSelectMode,
78+
onMouseDown: onDirectModeMouseDown,
79+
onTouchStart: onDirectModeMouseDown,
80+
},
81+
};

ui/src/utils/map/mapUtils.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ import { MapInstance, MapRef } from 'react-map-gl/maplibre';
66
import { isRouteGeometryLayer } from '../../components/map/routes/utils';
77
import { theme } from '../../generated/theme';
88

9+
type ImageAsset = { name: string; fileUrl: string; sdf: boolean };
10+
11+
const imageAssets: ImageAsset[] = [
12+
{ name: 'arrow', fileUrl: '/img/arrow-right.png', sdf: true },
13+
{
14+
name: 'route_vector_icon',
15+
fileUrl: '/img/route_vector_icon.png',
16+
sdf: false,
17+
},
18+
];
19+
920
export const removeLayer = (map: MapInstance, id: string) => {
1021
if (map.getLayer(id)) {
1122
map.removeLayer(id);
@@ -28,10 +39,6 @@ export const loadMapAssets = (mapRef: RefObject<MapRef>) => {
2839
return;
2940
}
3041

31-
const imageAssets: { name: string; fileUrl: string }[] = [
32-
{ name: 'arrow', fileUrl: '/img/arrow-right.png' },
33-
];
34-
3542
imageAssets.forEach(async (asset) => {
3643
if (map.hasImage(asset.name)) {
3744
return;
@@ -42,9 +49,7 @@ export const loadMapAssets = (mapRef: RefObject<MapRef>) => {
4249
// we need to check it again here because this code is inside event callback
4350
// which could be called multiple times before the map actually has the image
4451
if (!map.hasImage(asset.name)) {
45-
// Enable Signed Distance Fields (sdf) to make enable icon coloring.
46-
// https://docs.mapbox.com/help/troubleshooting/using-recolorable-images-in-mapbox-maps/
47-
map.addImage(asset.name, response.data, { sdf: true });
52+
map.addImage(asset.name, response.data, { sdf: asset.sdf });
4853
}
4954
});
5055
};

0 commit comments

Comments
 (0)