mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 02:56:41 +07:00
forwards and backwards drawing
This commit is contained in:
parent
bbd7d6a89a
commit
ad676d5fde
11 changed files with 119 additions and 21 deletions
|
@ -5,18 +5,28 @@ import * as MAP_ACTIONS from '~/redux/map/actions';
|
|||
import { IState } from '~/redux/store';
|
||||
import { selectMapRoute } from '~/redux/map/selectors';
|
||||
import classNames from 'classnames';
|
||||
import { selectEditorDirection } from '~/redux/editor/selectors';
|
||||
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||
import { DRAWING_DIRECTIONS } from '~/redux/editor/constants';
|
||||
|
||||
const mapStateToProps = (state: IState) => ({
|
||||
route: selectMapRoute(state),
|
||||
direction: selectEditorDirection(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
mapSetRoute: MAP_ACTIONS.mapSetRoute,
|
||||
editorSetDirection: EDITOR_ACTIONS.editorSetDirection,
|
||||
};
|
||||
|
||||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||
|
||||
const PolylineDialogUnconnected: FC<Props> = ({ route, mapSetRoute }) => {
|
||||
const PolylineDialogUnconnected: FC<Props> = ({
|
||||
route,
|
||||
direction,
|
||||
editorSetDirection,
|
||||
mapSetRoute,
|
||||
}) => {
|
||||
const reverseRoute = useCallback(() => {
|
||||
if (route.length < 2) return;
|
||||
mapSetRoute([...route].reverse());
|
||||
|
@ -34,6 +44,14 @@ const PolylineDialogUnconnected: FC<Props> = ({ route, mapSetRoute }) => {
|
|||
mapSetRoute(route.slice(0, route.length - 1));
|
||||
}, [mapSetRoute, route]);
|
||||
|
||||
const continueBackward = useCallback(() => {
|
||||
editorSetDirection(DRAWING_DIRECTIONS.BACKWARDS);
|
||||
}, [editorSetDirection]);
|
||||
|
||||
const continueForward = useCallback(() => {
|
||||
editorSetDirection(DRAWING_DIRECTIONS.FORWARDS);
|
||||
}, [editorSetDirection]);
|
||||
|
||||
return (
|
||||
<div className="control-dialog control-dialog__medium">
|
||||
<div className="helper">
|
||||
|
@ -59,6 +77,24 @@ const PolylineDialogUnconnected: FC<Props> = ({ route, mapSetRoute }) => {
|
|||
<Icon icon="icon-drop-end" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
className={classNames('helper__icon_button', {
|
||||
active: direction === DRAWING_DIRECTIONS.BACKWARDS,
|
||||
})}
|
||||
onClick={continueBackward}
|
||||
>
|
||||
<Icon icon="icon-draw-backward" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
className={classNames('helper__icon_button', {
|
||||
active: direction === DRAWING_DIRECTIONS.FORWARDS,
|
||||
})}
|
||||
onClick={continueForward}
|
||||
>
|
||||
<Icon icon="icon-draw-forward" />
|
||||
</button>
|
||||
|
||||
<div className="flex_1" />
|
||||
|
||||
<div className="big white upper">Ручной режим</div>
|
||||
|
|
|
@ -3,8 +3,9 @@ import { Icon } from '~/components/panels/Icon';
|
|||
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||
import classnames from 'classnames';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectEditor } from '~/redux/editor/selectors';
|
||||
import { selectEditor, selectEditorRouter, selectEditorDirection } from '~/redux/editor/selectors';
|
||||
import pick from 'ramda/es/pick';
|
||||
import { IState } from '~/redux/store';
|
||||
|
||||
const noPoints = ({
|
||||
editorRouterCancel,
|
||||
|
@ -84,8 +85,8 @@ const draggablePoints = ({
|
|||
</React.Fragment>
|
||||
);
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
editor: pick(['router'], selectEditor(state)),
|
||||
const mapStateToProps = (state: IState) => ({
|
||||
router: selectEditorRouter(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
|
@ -96,9 +97,7 @@ const mapDispatchToProps = {
|
|||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||
|
||||
const RouterDialogUnconnected: FC<Props> = ({
|
||||
editor: {
|
||||
router: { waypoints },
|
||||
},
|
||||
editorRouterCancel,
|
||||
editorRouterSubmit,
|
||||
}) => (
|
||||
|
|
|
@ -2,19 +2,20 @@ import React, { FC, useEffect, memo, useState, useCallback } from 'react';
|
|||
import { InteractivePoly } from '~/utils/map/InteractivePoly';
|
||||
import { isMobile } from '~/utils/window';
|
||||
import { LatLng } from 'leaflet';
|
||||
import { selectEditor, selectEditorMode, selectEditorEditing } from '~/redux/editor/selectors';
|
||||
import pick from 'ramda/es/pick';
|
||||
import { selectEditorMode, selectEditorEditing, selectEditorDirection } from '~/redux/editor/selectors';
|
||||
import * as MAP_ACTIONS from '~/redux/map/actions';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectMap, selectMapRoute } from '~/redux/map/selectors';
|
||||
import { selectMapRoute } from '~/redux/map/selectors';
|
||||
import { MainMap } from '~/constants/map';
|
||||
import { MODES } from '~/constants/modes';
|
||||
import * as EDITOR_ACTIONS from '~/redux/editor/actions';
|
||||
import { IState } from '~/redux/store';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
const mapStateToProps = (state: IState) => ({
|
||||
mode: selectEditorMode(state),
|
||||
editing: selectEditorEditing(state),
|
||||
route: selectMapRoute(state),
|
||||
drawing_direction: selectEditorDirection(state),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
|
@ -26,7 +27,7 @@ const mapDispatchToProps = {
|
|||
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||
|
||||
const RouteUnconnected: FC<Props> = memo(
|
||||
({ route, editing, mode, mapSetRoute, editorSetDistance, editorSetMarkersShown }) => {
|
||||
({ route, editing, mode, drawing_direction, mapSetRoute, editorSetDistance, editorSetMarkersShown }) => {
|
||||
const [layer, setLayer] = useState<InteractivePoly>(null);
|
||||
|
||||
const onDistanceChange = useCallback(({ distance }) => editorSetDistance(distance), [
|
||||
|
@ -103,6 +104,12 @@ const RouteUnconnected: FC<Props> = memo(
|
|||
}
|
||||
}, [mode, layer]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!layer) return;
|
||||
|
||||
layer.setDirection(drawing_direction);
|
||||
}, [drawing_direction, layer]);
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
|
|
@ -146,3 +146,8 @@ export const editorRedo = () => ({
|
|||
export const editorCaptureHistory = () => ({
|
||||
type: EDITOR_ACTIONS.CAPTURE_HIPSTORY,
|
||||
});
|
||||
|
||||
export const editorSetDirection = (drawing_direction: IEditorState['drawing_direction']) => ({
|
||||
type: EDITOR_ACTIONS.SET_DIRECTION,
|
||||
drawing_direction,
|
||||
});
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
const P = 'EDITOR';
|
||||
|
||||
export const DRAWING_DIRECTIONS: Record<'FORWARDS' | 'BACKWARDS', 'forward' | 'backward'> = {
|
||||
FORWARDS: 'forward',
|
||||
BACKWARDS: 'backward',
|
||||
};
|
||||
|
||||
export const EDITOR_HISTORY_LENGTH = 100;
|
||||
|
||||
export const EDITOR_ACTIONS = {
|
||||
|
@ -54,4 +59,6 @@ export const EDITOR_ACTIONS = {
|
|||
UNDO: `${P}-UNDO`,
|
||||
REDO: `${P}-REDO`,
|
||||
CAPTURE_HIPSTORY: `${P}-CAPTURE_HIPSTORY`,
|
||||
|
||||
SET_DIRECTION: `${P}-SET_DIRECTION`,
|
||||
};
|
||||
|
|
|
@ -179,6 +179,14 @@ const setHistory = (
|
|||
},
|
||||
});
|
||||
|
||||
const setDirection = (
|
||||
state,
|
||||
{ drawing_direction }: ReturnType<typeof ACTIONS.editorSetDirection>
|
||||
): IEditorState => ({
|
||||
...state,
|
||||
drawing_direction,
|
||||
});
|
||||
|
||||
export const EDITOR_HANDLERS = {
|
||||
[EDITOR_ACTIONS.SET_EDITING]: setEditing,
|
||||
[EDITOR_ACTIONS.SET_CHANGED]: setChanged,
|
||||
|
@ -209,4 +217,6 @@ export const EDITOR_HANDLERS = {
|
|||
[EDITOR_ACTIONS.SET_NOMINATIM]: setNominatim,
|
||||
|
||||
[EDITOR_ACTIONS.SET_HISTORY]: setHistory,
|
||||
|
||||
[EDITOR_ACTIONS.SET_DIRECTION]: setDirection,
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@ import { EDITOR_HANDLERS } from './handlers';
|
|||
import { ILatLng } from '../map/types';
|
||||
import { INominatimResult } from '~/redux/types';
|
||||
import { IMapReducer } from '../map';
|
||||
import { DRAWING_DIRECTIONS } from './constants';
|
||||
|
||||
export interface IEditorHistoryItem {
|
||||
route: IMapReducer['route'];
|
||||
|
@ -35,6 +36,7 @@ export interface IEditorState {
|
|||
is_empty: boolean;
|
||||
is_published: boolean;
|
||||
is_routing: boolean;
|
||||
drawing_direction: typeof DRAWING_DIRECTIONS[keyof typeof DRAWING_DIRECTIONS];
|
||||
|
||||
features: {
|
||||
routing: boolean;
|
||||
|
@ -63,6 +65,7 @@ export interface IEditorState {
|
|||
processing: boolean;
|
||||
loading: boolean;
|
||||
};
|
||||
|
||||
history: {
|
||||
records: IEditorHistoryItem[];
|
||||
position: number;
|
||||
|
@ -84,13 +87,16 @@ export const EDITOR_INITIAL_STATE = {
|
|||
estimated: 0,
|
||||
speed: 15,
|
||||
activeSticker: { set: null, sticker: null },
|
||||
drawing_direction: DRAWING_DIRECTIONS.FORWARDS,
|
||||
|
||||
is_published: false,
|
||||
is_empty: true,
|
||||
is_routing: false,
|
||||
|
||||
router: {
|
||||
waypoints: [],
|
||||
points: [],
|
||||
},
|
||||
is_published: false,
|
||||
is_empty: true,
|
||||
is_routing: false,
|
||||
|
||||
features: {
|
||||
routing: false,
|
||||
|
|
|
@ -9,3 +9,4 @@ export const selectEditorRenderer = (state: IState) => state.editor.renderer;
|
|||
export const selectEditorRouter = (state: IState) => state.editor.router;
|
||||
export const selectEditorDistance = (state: IState) => state.editor.distance;
|
||||
export const selectEditorNominatim = (state: IState) => state.editor.nominatim;
|
||||
export const selectEditorDirection = (state: IState) => state.editor.drawing_direction;
|
||||
|
|
|
@ -372,7 +372,7 @@
|
|||
</g>
|
||||
<g id="icon-drop-start" stroke="none">
|
||||
<g transform="translate(6 12)" fill="white">
|
||||
<path d="M23.528 6.662H11.979L9.953 4.98l2.026-1.887h11.549zM7.572 9.755l2.183-2.183-2.696-2.695 2.696-2.695L7.572 0 4.877 2.695 2.182 0 0 2.182l2.695 2.695L0 7.572l2.182 2.183 2.695-2.696z" fill="#fff"/>
|
||||
<path d="M23.528 6.662H11.979L9.953 4.98l2.026-1.887h11.549zM7.572 9.755l2.183-2.183-2.696-2.695 2.696-2.695L7.572 0 4.877 2.695 2.182 0 0 2.182l2.695 2.695L0 7.572l2.182 2.183 2.695-2.696z" fill="#fff" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="icon-drop-end" stroke="none">
|
||||
|
@ -382,12 +382,24 @@
|
|||
</g>
|
||||
<g id="icon-undo" stroke="none">
|
||||
<g transform="translate(8 8)" fill="white">
|
||||
<path d="M5.912 1.278c-.967 0-2.84.42-2.84.42L2.257 0 0 4.855 5.094 6.19l-.777-1.938s1.101-.113 1.595-.115a6.974 6.974 0 016.972 6.973 6.97 6.97 0 01-.921 3.457l2.07 2.07a9.833 9.833 0 001.71-5.527c0-5.43-4.401-9.832-9.831-9.832z" fill="#fff"/>
|
||||
<path d="M5.912 1.278c-.967 0-2.84.42-2.84.42L2.257 0 0 4.855 5.094 6.19l-.777-1.938s1.101-.113 1.595-.115a6.974 6.974 0 016.972 6.973 6.97 6.97 0 01-.921 3.457l2.07 2.07a9.833 9.833 0 001.71-5.527c0-5.43-4.401-9.832-9.831-9.832z" fill="#fff" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="icon-redo" stroke="none">
|
||||
<g transform="translate(8 8)" fill="white">
|
||||
<path d="M9.832 1.278c.967 0 2.84.42 2.84.42L13.486 0l2.257 4.855L10.65 6.19l.777-1.938s-1.101-.113-1.595-.115a6.974 6.974 0 00-6.973 6.973 6.97 6.97 0 00.922 3.457l-2.07 2.07A9.833 9.833 0 010 11.11c0-5.43 4.402-9.832 9.832-9.832z" fill="#fff"/>
|
||||
<path d="M9.832 1.278c.967 0 2.84.42 2.84.42L13.486 0l2.257 4.855L10.65 6.19l.777-1.938s-1.101-.113-1.595-.115a6.974 6.974 0 00-6.973 6.973 6.97 6.97 0 00.922 3.457l-2.07 2.07A9.833 9.833 0 010 11.11c0-5.43 4.402-9.832 9.832-9.832z" fill="#fff" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="icon-draw-forward" stroke="none">
|
||||
<g transform="translate(4 11)" fill="white">
|
||||
<path d="M19.38 0l5.374 4.547-5.374 4.655V0z" />
|
||||
<path d="M0 2.872h19.91v3.569H0z" />
|
||||
</g>
|
||||
</g>
|
||||
<g id="icon-draw-backward" stroke="none">
|
||||
<g transform="translate(4 11)" fill="white">
|
||||
<path d="M5.374 9.202L0 4.655 5.374 0v9.202z" />
|
||||
<path d="M24.754 6.33H4.844V2.762h19.91z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
@ -430,6 +430,12 @@
|
|||
&.inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&.active {
|
||||
svg {
|
||||
fill: url(#activeButtonGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.helper__buttons {
|
||||
|
|
|
@ -45,9 +45,7 @@ class InteractivePoly extends Polyline {
|
|||
this.startDragHinting();
|
||||
}
|
||||
|
||||
setLatLngs = (latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][]) => {
|
||||
super.setLatLngs(latlngs);
|
||||
|
||||
updateConstraintsToLatLngs = (latlngs: LatLngExpression[]) => {
|
||||
if (this.is_drawing) {
|
||||
// update mouse hinter on latlngs change
|
||||
const constraints = this.constrLine.getLatLngs() as LatLng[];
|
||||
|
@ -63,6 +61,12 @@ class InteractivePoly extends Polyline {
|
|||
|
||||
this.setConstraints([constraints[0], source as LatLng]);
|
||||
}
|
||||
}
|
||||
|
||||
setLatLngs = (latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][]) => {
|
||||
super.setLatLngs(latlngs);
|
||||
|
||||
this.updateConstraintsToLatLngs(latlngs as LatLngExpression[]);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
@ -492,6 +496,11 @@ class InteractivePoly extends Polyline {
|
|||
this.constrLine.setLatLngs(coords);
|
||||
};
|
||||
|
||||
setDirection = (direction: 'forward' | 'backward') => {
|
||||
this.drawing_direction = direction;
|
||||
this.updateConstraintsToLatLngs(this.getLatLngs() as LatLngExpression[]);
|
||||
}
|
||||
|
||||
dropMarker = ({ target }: LeafletMouseEvent): void => {
|
||||
const index = this.markers.indexOf(target);
|
||||
const latlngs = this.getLatLngs();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue