displaying end marker

This commit is contained in:
Fedor Katurov 2020-01-17 17:13:57 +07:00
parent 72c6b99f58
commit 5db6d85e35
3 changed files with 128 additions and 20 deletions

View file

@ -2,18 +2,19 @@ import React, { FC, useEffect, memo, useState, useCallback } from 'react';
import { InteractivePoly } from '~/utils/map/InteractivePoly'; import { InteractivePoly } from '~/utils/map/InteractivePoly';
import { isMobile } from '~/utils/window'; import { isMobile } from '~/utils/window';
import { LatLng } from 'leaflet'; import { LatLng } from 'leaflet';
import { selectEditor } from '~/redux/editor/selectors'; import { selectEditor, selectEditorMode, selectEditorEditing } from '~/redux/editor/selectors';
import pick from 'ramda/es/pick'; import pick from 'ramda/es/pick';
import * as MAP_ACTIONS from '~/redux/map/actions'; import * as MAP_ACTIONS from '~/redux/map/actions';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectMap } from '~/redux/map/selectors'; import { selectMap, selectMapRoute } from '~/redux/map/selectors';
import { MainMap } from '~/constants/map'; import { MainMap } from '~/constants/map';
import { MODES } from '~/constants/modes'; import { MODES } from '~/constants/modes';
import * as EDITOR_ACTIONS from '~/redux/editor/actions'; import * as EDITOR_ACTIONS from '~/redux/editor/actions';
const mapStateToProps = state => ({ const mapStateToProps = state => ({
editor: pick(['mode', 'editing'], selectEditor(state)), mode: selectEditorMode(state),
map: pick(['route'], selectMap(state)), editing: selectEditorEditing(state),
route: selectMapRoute(state),
}); });
const mapDispatchToProps = { const mapDispatchToProps = {
@ -25,13 +26,7 @@ const mapDispatchToProps = {
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {}; type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
const RouteUnconnected: FC<Props> = memo( const RouteUnconnected: FC<Props> = memo(
({ ({ route, editing, mode, mapSetRoute, editorSetDistance, editorSetMarkersShown }) => {
map: { route },
editor: { editing, mode },
mapSetRoute,
editorSetDistance,
editorSetMarkersShown,
}) => {
const [layer, setLayer] = useState<InteractivePoly>(null); const [layer, setLayer] = useState<InteractivePoly>(null);
const onDistanceChange = useCallback(({ distance }) => editorSetDistance(distance), [ const onDistanceChange = useCallback(({ distance }) => editorSetDistance(distance), [

View file

@ -1,16 +1,18 @@
import { FC, useEffect, useCallback, memo } from 'react'; import { FC, useEffect, useCallback, memo, useState } from 'react';
import pick from 'ramda/es/pick';
import { OsrmRouter } from '~/utils/map/OsrmRouter'; import { OsrmRouter } from '~/utils/map/OsrmRouter';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectMap } from '~/redux/map/selectors'; import { selectMapRoute } from '~/redux/map/selectors';
import { selectEditorRouter, selectEditorMode } from '~/redux/editor/selectors'; import { selectEditorRouter, selectEditorMode } from '~/redux/editor/selectors';
import { MainMap } from '~/constants/map'; import { MainMap } from '~/constants/map';
import * as EDITOR_ACTIONS from '~/redux/editor/actions'; import * as EDITOR_ACTIONS from '~/redux/editor/actions';
import { MODES } from '~/constants/modes'; import { MODES } from '~/constants/modes';
import { LatLngLiteral, marker, divIcon } from 'leaflet';
import classNames from 'classnames';
import { angleBetweenPoints } from '~/utils/geom';
const mapStateToProps = state => ({ const mapStateToProps = state => ({
map: pick(['route'], selectMap(state)), route: selectMapRoute(state),
router: pick(['waypoints', 'points'], selectEditorRouter(state)), router: selectEditorRouter(state),
mode: selectEditorMode(state), mode: selectEditorMode(state),
}); });
@ -21,20 +23,94 @@ const mapDispatchToProps = {
type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {}; type Props = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
const RouterUnconnected: FC<Props> = memo( const RouterUnconnected: FC<Props> = memo(
({ map: { route }, mode, router: { waypoints }, editorSetRouter }) => { ({ route, mode, router: { waypoints }, editorSetRouter }) => {
const [distance, setDistance] = useState(0);
const [end, setEnd] = useState<LatLngLiteral>(null);
const [direction, setDirection] = useState<boolean>(false);
const updateWaypoints = useCallback( const updateWaypoints = useCallback(
({ waypoints }) => editorSetRouter({ waypoints: waypoints.filter(wp => !!wp.latLng) }), ({ waypoints }) => {
[editorSetRouter] const filtered = waypoints.filter(wp => !!wp.latLng);
if (filtered.length < 2) {
setDistance(0);
}
editorSetRouter({ waypoints: filtered });
},
[editorSetRouter, setDistance]
);
const updateDistance = useCallback(
({ routes, waypoints }) => {
console.log(routes.length, waypoints.length);
if (!routes || !routes.length || waypoints.length < 2) {
console.log('hm 1');
setDistance(0);
return;
}
const { summary, coordinates } = routes[0];
if (coordinates.length <= 1) {
console.log('hm 2');
setDistance(0);
return;
}
const totalDistance = parseFloat((summary.totalDistance / 1000).toFixed(1)) || 0;
const latlng = (coordinates.length && coordinates[coordinates.length - 1]) || null;
const angle = angleBetweenPoints(
MainMap.latLngToContainerPoint(coordinates[coordinates.length - 2]),
MainMap.latLngToContainerPoint(coordinates[coordinates.length - 3])
);
setDistance(totalDistance);
setEnd(latlng);
setDirection(angle > -90 && angle < 90);
},
[setDistance, setEnd]
); );
useEffect(() => { useEffect(() => {
OsrmRouter.on('waypointschanged', updateWaypoints).addTo(MainMap); OsrmRouter.on('waypointschanged', updateWaypoints)
.on('routesfound', updateDistance)
.addTo(MainMap);
return () => { return () => {
OsrmRouter.off('waypointschanged', updateWaypoints).setWaypoints([]); OsrmRouter.off('waypointschanged', updateWaypoints).setWaypoints([]);
}; };
}, [MainMap, updateWaypoints, mode]); }, [MainMap, updateWaypoints, mode]);
useEffect(() => {
if (!distance || !end) {
return;
}
const item = marker(end, {
draggable: false,
interactive: false,
icon: divIcon({
html: `
<div class="leaflet-km-dist">
${parseFloat(distance.toFixed(1))}
</div>
`,
className: classNames('leaflet-km-marker router-end-marker', { right: !direction }),
iconSize: [11, 11],
iconAnchor: [6, 6],
}),
zIndexOffset: -100,
});
item.addTo(MainMap);
return () => {
item.removeFrom(MainMap);
};
}, [distance, end, direction]);
useEffect(() => { useEffect(() => {
if (mode !== MODES.ROUTER) return; if (mode !== MODES.ROUTER) return;

View file

@ -186,6 +186,43 @@
} }
} }
.router-end-marker {
.leaflet-km-dist {
background: @router_line;
left: auto;
right: -3px;
top: -3px;
position: absolute;
z-index: -10;
padding: 2px 16px 2px 4px;
&::after {
content: ' ';
width: 8px;
height: 8px;
border-radius: 4px;
background: white;
position: absolute;
right: 5px;
top: 5px;
}
}
&.right {
.leaflet-km-dist {
padding: 2px 4px 2px 16px;
left: -3px;
right: auto;
&::after {
left: 5px;
right: auto;
}
}
}
}
.leaflet-km-marker-2 { .leaflet-km-marker-2 {
.leaflet-km-dist { .leaflet-km-dist {
background: green; background: green;