diff --git a/src/map/Route/index.tsx b/src/map/Route/index.tsx index 993e256..1501f0a 100644 --- a/src/map/Route/index.tsx +++ b/src/map/Route/index.tsx @@ -2,18 +2,19 @@ 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 } from '~/redux/editor/selectors'; +import { selectEditor, selectEditorMode, selectEditorEditing } from '~/redux/editor/selectors'; import pick from 'ramda/es/pick'; import * as MAP_ACTIONS from '~/redux/map/actions'; import { connect } from 'react-redux'; -import { selectMap } from '~/redux/map/selectors'; +import { selectMap, selectMapRoute } from '~/redux/map/selectors'; import { MainMap } from '~/constants/map'; import { MODES } from '~/constants/modes'; import * as EDITOR_ACTIONS from '~/redux/editor/actions'; const mapStateToProps = state => ({ - editor: pick(['mode', 'editing'], selectEditor(state)), - map: pick(['route'], selectMap(state)), + mode: selectEditorMode(state), + editing: selectEditorEditing(state), + route: selectMapRoute(state), }); const mapDispatchToProps = { @@ -25,13 +26,7 @@ const mapDispatchToProps = { type Props = ReturnType & typeof mapDispatchToProps & {}; const RouteUnconnected: FC = memo( - ({ - map: { route }, - editor: { editing, mode }, - mapSetRoute, - editorSetDistance, - editorSetMarkersShown, - }) => { + ({ route, editing, mode, mapSetRoute, editorSetDistance, editorSetMarkersShown }) => { const [layer, setLayer] = useState(null); const onDistanceChange = useCallback(({ distance }) => editorSetDistance(distance), [ diff --git a/src/map/Router/index.tsx b/src/map/Router/index.tsx index a2dd2dd..a075186 100644 --- a/src/map/Router/index.tsx +++ b/src/map/Router/index.tsx @@ -1,16 +1,18 @@ -import { FC, useEffect, useCallback, memo } from 'react'; -import pick from 'ramda/es/pick'; +import { FC, useEffect, useCallback, memo, useState } from 'react'; import { OsrmRouter } from '~/utils/map/OsrmRouter'; 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 { MainMap } from '~/constants/map'; import * as EDITOR_ACTIONS from '~/redux/editor/actions'; import { MODES } from '~/constants/modes'; +import { LatLngLiteral, marker, divIcon } from 'leaflet'; +import classNames from 'classnames'; +import { angleBetweenPoints } from '~/utils/geom'; const mapStateToProps = state => ({ - map: pick(['route'], selectMap(state)), - router: pick(['waypoints', 'points'], selectEditorRouter(state)), + route: selectMapRoute(state), + router: selectEditorRouter(state), mode: selectEditorMode(state), }); @@ -21,20 +23,94 @@ const mapDispatchToProps = { type Props = ReturnType & typeof mapDispatchToProps & {}; const RouterUnconnected: FC = memo( - ({ map: { route }, mode, router: { waypoints }, editorSetRouter }) => { + ({ route, mode, router: { waypoints }, editorSetRouter }) => { + const [distance, setDistance] = useState(0); + const [end, setEnd] = useState(null); + const [direction, setDirection] = useState(false); + const updateWaypoints = useCallback( - ({ waypoints }) => editorSetRouter({ waypoints: waypoints.filter(wp => !!wp.latLng) }), - [editorSetRouter] + ({ waypoints }) => { + 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(() => { - OsrmRouter.on('waypointschanged', updateWaypoints).addTo(MainMap); + OsrmRouter.on('waypointschanged', updateWaypoints) + .on('routesfound', updateDistance) + .addTo(MainMap); return () => { OsrmRouter.off('waypointschanged', updateWaypoints).setWaypoints([]); }; }, [MainMap, updateWaypoints, mode]); + useEffect(() => { + if (!distance || !end) { + return; + } + + const item = marker(end, { + draggable: false, + interactive: false, + icon: divIcon({ + html: ` +
+ ${parseFloat(distance.toFixed(1))} +
+ `, + 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(() => { if (mode !== MODES.ROUTER) return; diff --git a/src/styles/map.less b/src/styles/map.less index cab4e8e..06bfaf1 100644 --- a/src/styles/map.less +++ b/src/styles/map.less @@ -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-dist { background: green;