From b8545105c82e74a9e41eeac0ea062ecd6d988998 Mon Sep 17 00:00:00 2001 From: muerwre Date: Fri, 24 Aug 2018 12:36:36 +0700 Subject: [PATCH] dist and time finishing route --- package-lock.json | 8 +++++ package.json | 1 + src/components/panels/EditorDialog.jsx | 5 +-- src/components/panels/EditorPanel.jsx | 26 +++++++++++++--- src/components/router/RouterHelper.jsx | 42 +++++++++++++++++--------- src/constants/modes.js | 1 + src/containers/App.jsx | 14 ++++++++- src/modules/Editor.js | 17 ++++++++--- src/modules/Poly.js | 28 +++++++++++++++-- src/modules/Router.js | 29 +++++++++++++++--- src/modules/Sticker.js | 6 ++-- src/sprites/icon.svg | 20 +++++++++++- src/styles/panel.less | 9 ++++++ src/utils/simplify.js | 21 +++++++++++++ src/utils/time.js | 5 +++ 15 files changed, 195 insertions(+), 37 deletions(-) create mode 100644 src/utils/simplify.js create mode 100644 src/utils/time.js diff --git a/package-lock.json b/package-lock.json index 581dc5a..f256d72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7629,6 +7629,14 @@ "resolved": "https://registry.npmjs.org/leaflet-editable/-/leaflet-editable-1.1.0.tgz", "integrity": "sha1-93dZekCoGic/KHtIn9D+XM1gyNA=" }, + "leaflet-geometryutil": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/leaflet-geometryutil/-/leaflet-geometryutil-0.9.0.tgz", + "integrity": "sha512-xlie+JCF+zJKc8fujgIUFnob5roEz4GTiZ8GaDR6O24g3I2nsOcCc4GQUgKGpnDMOV4BKa7QavKxy/d92bLyYw==", + "requires": { + "leaflet": ">=0.7.0" + } + }, "leaflet-routing-machine": { "version": "github:muerwre/leaflet-routing-machine#4be3c24db31b7c2e9750f5894e538969e953a093", "from": "github:muerwre/leaflet-routing-machine#no-osrm-text", diff --git a/package.json b/package.json index b4ff768..7f040ac 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "history": "^4.7.2", "leaflet": "^1.3.3", "leaflet-editable": "^1.1.0", + "leaflet-geometryutil": "^0.9.0", "leaflet-routing-machine": "muerwre/leaflet-routing-machine#no-osrm-text", "less": "^3.8.1", "lodash": "^4.17.10", diff --git a/src/components/panels/EditorDialog.jsx b/src/components/panels/EditorDialog.jsx index cd2fc14..b660ee9 100644 --- a/src/components/panels/EditorDialog.jsx +++ b/src/components/panels/EditorDialog.jsx @@ -3,12 +3,13 @@ import { MODES } from '$constants/modes'; import { RouterHelper } from '$components/router/RouterHelper'; -export const EditorDialog = ({ mode, routerPoints }) => { +export const EditorDialog = ({ mode, routerPoints, editor }) => { const showDialog = (mode === MODES.ROUTER); + return ( showDialog &&
- { mode === MODES.ROUTER && } + { mode === MODES.ROUTER && }
); }; diff --git a/src/components/panels/EditorPanel.jsx b/src/components/panels/EditorPanel.jsx index f8def92..24f5da1 100644 --- a/src/components/panels/EditorPanel.jsx +++ b/src/components/panels/EditorPanel.jsx @@ -2,6 +2,8 @@ import React from 'react'; import { MODES } from '$constants/modes'; import classnames from 'classnames'; +import { toHours } from '$utils/time'; + import { Icon } from '$components/panels/Icon'; import { EditorDialog } from '$components/panels/EditorDialog'; @@ -15,7 +17,9 @@ export class EditorPanel extends React.PureComponent { startShotterMode = () => this.props.editor.changeMode(MODES.SHOTTER); render() { - const { mode, routerPoints } = this.props; + const { + mode, routerPoints, editor, totalDistance, estimateTime + } = this.props; return (
@@ -23,6 +27,7 @@ export class EditorPanel extends React.PureComponent {
@@ -36,6 +41,12 @@ export class EditorPanel extends React.PureComponent {
+
+ {totalDistance} км + { + (estimateTime > 0) && (estimateTime > 0) && {toHours(estimateTime)} + } +
+ +
@@ -81,4 +99,4 @@ export class EditorPanel extends React.PureComponent {
); } -}; +} diff --git a/src/components/router/RouterHelper.jsx b/src/components/router/RouterHelper.jsx index 07b139b..1ea49c0 100644 --- a/src/components/router/RouterHelper.jsx +++ b/src/components/router/RouterHelper.jsx @@ -1,54 +1,68 @@ import React from 'react'; -const noPoints = () => ( +const noPoints = ({ cancelDrawing }) => (
Укажите на карте первую точку маршрута
Путь прокладывается по улицам, тротуарам и тропинкам
-
+
Отмена
); -const firstPoint = () => ( +const firstPoint = ({ cancelDrawing }) => (
Укажите на карте конечную точку маршрута
Вы сможете добавить уточняющие точки
-
+
Отмена
); -const draggablePoints = () => ( +const draggablePoints = ({ cancelDrawing, submitDrawing }) => (
Продолжите маршрут, щелкая по карте
Потяните линию, чтобы указать промежуточные точки
-
+
Отмена
-
+
Применить
); -export const RouterHelper = ({ routerPoints }) => ( -
- { !routerPoints && noPoints() } - { routerPoints === 1 && firstPoint() } - { routerPoints >= 2 && draggablePoints() } -
-); +export class RouterHelper extends React.Component { + cancelDrawing = () => { + this.props.editor.router.cancelDrawing(); + }; + + submitDrawing = () => { + this.props.editor.router.submitDrawing(); + }; + + render() { + const { routerPoints, editor } = this.props; + const { cancelDrawing, submitDrawing } = this; + return ( +
+ {!routerPoints && noPoints({ cancelDrawing })} + {routerPoints === 1 && firstPoint({ cancelDrawing })} + {routerPoints >= 2 && draggablePoints({ cancelDrawing, submitDrawing })} +
+ ); + } +} diff --git a/src/constants/modes.js b/src/constants/modes.js index 134f887..d14390e 100644 --- a/src/constants/modes.js +++ b/src/constants/modes.js @@ -3,5 +3,6 @@ export const MODES = { STICKERS: 'STICKERS', ROUTER: 'ROUTER', SHOTTER: 'SHOTTER', + TRASH: 'TRASH', NONE: 'NONE', }; diff --git a/src/containers/App.jsx b/src/containers/App.jsx index 8904bb7..866bf18 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -8,26 +8,36 @@ export class App extends React.Component { state = { mode: 'none', routerPoints: 0, + totalDistance: 0, + estimateTime: 0, }; setMode = mode => { this.setState({ mode }); }; + setRouterPoints = routerPoints => { this.setState({ routerPoints }); }; + setTotalDist = totalDistance => { + const time = (totalDistance && (totalDistance / 15)) || 0; + const estimateTime = (time && parseFloat(time.toFixed(1))); + this.setState({ totalDistance, estimateTime }); + }; + editor = new Editor({ container: 'map', mode: this.state.mode, setMode: this.setMode, setRouterPoints: this.setRouterPoints, + setTotalDist: this.setTotalDist, }); render() { const { editor, - state: { mode, routerPoints }, + state: { mode, routerPoints, totalDistance, estimateTime }, } = this; @@ -38,6 +48,8 @@ export class App extends React.Component { editor={editor} mode={mode} routerPoints={routerPoints} + totalDistance={totalDistance} + estimateTime={estimateTime} />
); diff --git a/src/modules/Editor.js b/src/modules/Editor.js index 68ddf8d..f504986 100644 --- a/src/modules/Editor.js +++ b/src/modules/Editor.js @@ -11,14 +11,19 @@ export class Editor { mode, setMode, setRouterPoints, + setTotalDist, }) { this.map = new Map({ container }); - const { lockMapClicks, routerMoveStart, map: { map } } = this; + const { + lockMapClicks, routerMoveStart, changeMode, pushPolyPoints, map: { map } + } = this; - this.poly = new Poly({ map, routerMoveStart, lockMapClicks }); + this.poly = new Poly({ map, routerMoveStart, lockMapClicks, setTotalDist }); this.stickers = new Stickers({ map, lockMapClicks }); - this.router = new Router({ map, lockMapClicks, setRouterPoints }); + this.router = new Router({ + map, lockMapClicks, setRouterPoints, changeMode, pushPolyPoints + }); this.shotter = new Shotter({ map }); this.setMode = setMode; @@ -98,6 +103,10 @@ export class Editor { routerMoveStart = () => { const { _latlngs } = this.poly.poly; - if (_latlngs) this.router.moveStart(_latlngs[_latlngs.length-1]); + if (_latlngs) this.router.moveStart(_latlngs[_latlngs.length - 1]); + }; + + pushPolyPoints = latlngs => { + this.poly.pushPoints(latlngs); } } diff --git a/src/modules/Poly.js b/src/modules/Poly.js index ab9fa96..9d60a50 100644 --- a/src/modules/Poly.js +++ b/src/modules/Poly.js @@ -1,16 +1,21 @@ -import { polyline } from "leaflet"; +import L from 'leaflet'; +import 'leaflet-geometryutil'; +import { simplify } from '$utils/simplify'; const polyStyle = { color: 'url(#activePathGradient)', weight: '6' }; // const polyStyle = { color: '#ff3344', weight: '5' }; export class Poly { - constructor({ map, routerMoveStart, lockMapClicks }) { - this.poly = polyline([], polyStyle); + constructor({ + map, routerMoveStart, lockMapClicks, setTotalDist + }) { + this.poly = L.polyline([], polyStyle); this.latlngs = []; this.poly.addTo(map); this.map = map; this.routerMoveStart = routerMoveStart; + this.setTotalDist = setTotalDist; this.lockMapClicks = lockMapClicks; this.bindEvents(); } @@ -19,7 +24,10 @@ export class Poly { console.log('upd'); const coords = this.poly.toGeoJSON().geometry.coordinates; this.latlngs = (coords && coords.length && coords.map(([lng, lat]) => ({ lng, lat }))) || []; + const meters = (this.poly && (L.GeometryUtil.length(this.poly) / 1000)) || 0; + const kilometers = (meters && parseFloat(meters.toFixed(1))) || 0; + this.setTotalDist(kilometers); this.routerMoveStart(); }; @@ -59,9 +67,11 @@ export class Poly { continue = () => { if (this.latlngs && this.latlngs.length) { + console.log('continue?'); this.poly.enableEdit().continueForward(); this.poly.editor.reset(); } else { + console.log('start over'); this.poly = this.map.editTools.startPolyline(); this.poly.setStyle(polyStyle); } @@ -78,5 +88,17 @@ export class Poly { lockMap = () => { this.lockMapClicks(true); + }; + + pushPoints = latlngs => { + const { map } = this; + const simplified = simplify({ map, latlngs }); + const summary = [ + ...this.poly.getLatLngs(), + ...simplified, + ]; + + this.poly.setLatLngs(summary); + this.updateMarks(); } } diff --git a/src/modules/Router.js b/src/modules/Router.js index bd89613..7382c1f 100644 --- a/src/modules/Router.js +++ b/src/modules/Router.js @@ -2,9 +2,16 @@ import L from 'leaflet'; import Routing from 'leaflet-routing-machine/src/index'; import { CONFIG } from '$config'; import { DomMarker } from '$utils/DomMarker'; +import { MODES } from '$constants/modes'; export class Router { - constructor({ map, lockMapClicks, setRouterPoints }) { + constructor({ map, lockMapClicks, setRouterPoints, changeMode, pushPolyPoints }) { + this.waypoints = []; + this.lockMapClicks = lockMapClicks; + this.setRouterPoints = setRouterPoints; + this.changeMode = changeMode; + this.pushPolyPoints = pushPolyPoints; + const routeLine = r => Routing.line(r, { styles: [ { color: 'white', opacity: 0.8, weight: 6 }, @@ -36,9 +43,6 @@ export class Router { this.router.addTo(map); - this.waypoints = []; - this.lockMapClicks = lockMapClicks; - this.setRouterPoints = setRouterPoints; // this.router._line.on('mousedown', console.log); } // @@ -109,5 +113,20 @@ export class Router { updateWaypointsCount = () => { const waypoints = this.router.getWaypoints().filter(({ latLng }) => !!latLng); this.setRouterPoints(waypoints.length); - } + }; + + cancelDrawing = () => { + this.router.setWaypoints([]); + this.changeMode(MODES.NONE); + }; + + submitDrawing = () => { + const [route] = this.router._routes; + if (!route) return; + + const { coordinates, summary: { totalDistance } } = route; + this.pushPolyPoints(coordinates); + this.router.setWaypoints([]); + this.changeMode(MODES.POLY); + }; } diff --git a/src/modules/Sticker.js b/src/modules/Sticker.js index 28bee27..539695f 100644 --- a/src/modules/Sticker.js +++ b/src/modules/Sticker.js @@ -118,9 +118,9 @@ export class Sticker { generateStickerSVG = sticker => ( ` - - - + + + ` ) } diff --git a/src/sprites/icon.svg b/src/sprites/icon.svg index d54d719..c2be3cd 100644 --- a/src/sprites/icon.svg +++ b/src/sprites/icon.svg @@ -32,11 +32,29 @@ - + + + + + + + + + + + + + + + + + + + diff --git a/src/styles/panel.less b/src/styles/panel.less index 0ecbe2d..7200727 100644 --- a/src/styles/panel.less +++ b/src/styles/panel.less @@ -5,6 +5,15 @@ box-shadow: rgba(0,0,0,0.3) 0 2px 0, inset rgba(255, 255, 255, 0.05) 1px 1px; } +.control-dist { + height: 44px; + background: #222222; + padding: 0 10px; + display: flex; + align-items: center; + border-radius: 3px 0 0 3px; +} + .control-sep { height: 44px; background: #222222; diff --git a/src/utils/simplify.js b/src/utils/simplify.js new file mode 100644 index 0000000..ce729ef --- /dev/null +++ b/src/utils/simplify.js @@ -0,0 +1,21 @@ +import L from 'leaflet'; + +export const simplify = ({ map, latlngs }) => { + const points = []; + const target = []; + const zoom = 12; + const mul = 0.7; // 0 - not simplifying, 1 - very rude. + // its better to estimate mul value by route length + + for (let i = 0; i < latlngs.length; i += 1) { + points.push(map.project({ lat: latlngs[i].lat, lng: latlngs[i].lng }, zoom)); + } + + const simplified = L.LineUtil.simplify(points, mul); + + for (let i = 0; i < simplified.length; i += 1) { + target.push(map.unproject(simplified[i], zoom)); + } + + return target; +}; diff --git a/src/utils/time.js b/src/utils/time.js new file mode 100644 index 0000000..b822710 --- /dev/null +++ b/src/utils/time.js @@ -0,0 +1,5 @@ +export const toHours = (info) => { + const hrs = parseInt(Number(info)); + const min = Math.round((Number(info)-hrs) * 60); + return hrs+':'+min; +}