forwards and backwards drawing

This commit is contained in:
Fedor Katurov 2020-01-22 15:16:34 +07:00
parent bbd7d6a89a
commit ad676d5fde
11 changed files with 119 additions and 21 deletions

View file

@ -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>

View file

@ -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,
}) => (

View file

@ -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;
}
);

View file

@ -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,
});

View file

@ -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`,
};

View file

@ -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,
};

View file

@ -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,

View file

@ -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;

View file

@ -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

Before After
Before After

View file

@ -430,6 +430,12 @@
&.inactive {
opacity: 0.5;
}
&.active {
svg {
fill: url(#activeButtonGradient);
}
}
}
.helper__buttons {

View file

@ -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();