dist and time

finishing route
This commit is contained in:
muerwre 2018-08-24 12:36:36 +07:00
parent 102328a1b2
commit b8545105c8
15 changed files with 195 additions and 37 deletions

8
package-lock.json generated
View file

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

View file

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

View file

@ -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 &&
<div id="control-dialog">
{ mode === MODES.ROUTER && <RouterHelper routerPoints={routerPoints} /> }
{ mode === MODES.ROUTER && <RouterHelper routerPoints={routerPoints} editor={editor} /> }
</div>
);
};

View file

@ -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 (
<div>
@ -23,6 +27,7 @@ export class EditorPanel extends React.PureComponent {
<EditorDialog
mode={mode}
routerPoints={routerPoints}
editor={editor}
/>
<div className="panel">
@ -36,6 +41,12 @@ export class EditorPanel extends React.PureComponent {
</div>
<div className="panel right">
<div className="control-dist">
{totalDistance} км
{
(estimateTime > 0) && (estimateTime > 0) && <span>{toHours(estimateTime)}</span>
}
</div>
<div className="control-bar">
<button
className={classnames({ active: mode === MODES.ROUTER })}
@ -69,11 +80,18 @@ export class EditorPanel extends React.PureComponent {
</button>
<button
className={classnames('highlighted', { active: mode === MODES.SHOTTER })}
className={classnames({ active: mode === MODES.TRASH })}
onClick={this.startShotterMode}
>
<Icon icon="icon-trash" />
</button>
<button
className="highlighted"
onClick={this.startShotterMode}
>
<span>СХОРОНИТЬ</span>
<Icon icon="icon-shooter" />
<Icon icon="icon-save" />
</button>
</div>
@ -81,4 +99,4 @@ export class EditorPanel extends React.PureComponent {
</div>
);
}
};
}

View file

@ -1,54 +1,68 @@
import React from 'react';
const noPoints = () => (
const noPoints = ({ cancelDrawing }) => (
<div className="router-helper">
<div className="router-helper__text">
<div className="big white">Укажите на карте первую точку маршрута</div>
<div className="small gray">Путь прокладывается по улицам, тротуарам и тропинкам</div>
</div>
<div className="router-helper__buttons">
<div className="button router-helper__button">
<div className="button router-helper__button" onClick={cancelDrawing}>
Отмена
</div>
</div>
</div>
);
const firstPoint = () => (
const firstPoint = ({ cancelDrawing }) => (
<div className="router-helper">
<div className="router-helper__text">
<div className="big white">Укажите на карте конечную точку маршрута</div>
<div className="small gray"> Вы сможете добавить уточняющие точки</div>
</div>
<div className="router-helper__buttons">
<div className="button router-helper__button">
<div className="button router-helper__button" onClick={cancelDrawing}>
Отмена
</div>
</div>
</div>
);
const draggablePoints = () => (
const draggablePoints = ({ cancelDrawing, submitDrawing }) => (
<div className="router-helper">
<div className="router-helper__text">
<div className="big white">Продолжите маршрут, щелкая по карте</div>
<div className="small gray">Потяните линию, чтобы указать промежуточные точки</div>
</div>
<div className="router-helper__buttons button-group">
<div className="button button_red router-helper__button">
<div className="button button_red router-helper__button" onClick={cancelDrawing}>
Отмена
</div>
<div className="button primary router-helper__button">
<div className="button primary router-helper__button" onClick={submitDrawing}>
Применить
</div>
</div>
</div>
);
export const RouterHelper = ({ routerPoints }) => (
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 (
<div>
{ !routerPoints && noPoints() }
{ routerPoints === 1 && firstPoint() }
{ routerPoints >= 2 && draggablePoints() }
{!routerPoints && noPoints({ cancelDrawing })}
{routerPoints === 1 && firstPoint({ cancelDrawing })}
{routerPoints >= 2 && draggablePoints({ cancelDrawing, submitDrawing })}
</div>
);
}
}

View file

@ -3,5 +3,6 @@ export const MODES = {
STICKERS: 'STICKERS',
ROUTER: 'ROUTER',
SHOTTER: 'SHOTTER',
TRASH: 'TRASH',
NONE: 'NONE',
};

View file

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

View file

@ -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;
@ -99,5 +104,9 @@ export class Editor {
const { _latlngs } = this.poly.poly;
if (_latlngs) this.router.moveStart(_latlngs[_latlngs.length - 1]);
};
pushPolyPoints = latlngs => {
this.poly.pushPoints(latlngs);
}
}

View file

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

View file

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

View file

@ -38,5 +38,23 @@
</g>
</g>
<g id="icon-trash">
<g transform="matrix(4.2 0 0 4.2 -3 -2 )" stroke="none">
<path fill="white" d="M2.783 3.626h2.923v2.923H2.783z"/>
<path fill="white" d="M2.479 2.597h3.508v.748H2.479z"/>
<path fill="white" d="M3.438 1.919h1.473v.865H3.438z"/>
<path fill="black" d="M3.859 2.25h.631v.386h-.631z"/>
<path fill="black" d="M3.134 3.906h.468v2.315h-.468z"/>
<path fill="black" d="M-4.537 3.906h.444v2.315h-.444z" transform="scale(-1 1)"/>
<path fill="black" d="M4.958 3.906h.444v2.315h-.444z"/>
</g>
</g>
<g id="icon-save" stroke="none">
<path fill="black" d="M0 0h32v32H0z"/>
<path fill="white" d="M6.844 8.459V24h18.312V11.375H14.031V8.459z"/>
<rect fill="black" width="2.74" height="5.038" x="14.63" y="14.411" stroke-width="3.603" />
<path fill="black" d="M16.866 19.73l-4.315-.06-4.314.06 2.209-3.707 2.105-3.766 2.106 3.766z" transform="matrix(.45903 -.40628 .79506 .23456 -3.467 21.088)"/>
</g>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Before After
Before After

View file

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

21
src/utils/simplify.js Normal file
View file

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

5
src/utils/time.js Normal file
View file

@ -0,0 +1,5 @@
export const toHours = (info) => {
const hrs = parseInt(Number(info));
const min = Math.round((Number(info)-hrs) * 60);
return hrs+':'+min;
}