basic router

This commit is contained in:
Fedor Katurov 2018-08-16 12:29:58 +07:00
parent 0d8a507620
commit e477f50283
12 changed files with 215 additions and 15 deletions

25
package-lock.json generated
View file

@ -689,6 +689,16 @@
"to-fast-properties": "^2.0.0"
}
},
"@mapbox/corslite": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/@mapbox/corslite/-/corslite-0.0.7.tgz",
"integrity": "sha1-KfW2oYi6lG5RS98LZAHtT74To54="
},
"@mapbox/polyline": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@mapbox/polyline/-/polyline-0.2.0.tgz",
"integrity": "sha1-biWYB0SqIjMflLZFpULALT/P7pc="
},
"@mrmlnc/readdir-enhanced": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@ -7418,6 +7428,16 @@
"resolved": "https://registry.npmjs.org/leaflet-editable/-/leaflet-editable-1.1.0.tgz",
"integrity": "sha1-93dZekCoGic/KHtIn9D+XM1gyNA="
},
"leaflet-routing-machine": {
"version": "3.2.8",
"resolved": "https://registry.npmjs.org/leaflet-routing-machine/-/leaflet-routing-machine-3.2.8.tgz",
"integrity": "sha512-cJPN//kMu6J7L7M/apfjx3SEAt7TFSFGj285To4vLTnq4h9uPo5u6Rd8JdIipyBJXED/UvUVG7LlpguQ+G7gqA==",
"requires": {
"@mapbox/corslite": "0.0.7",
"@mapbox/polyline": "^0.2.0",
"osrm-text-instructions": "^0.11.5"
}
},
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@ -8881,6 +8901,11 @@
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"osrm-text-instructions": {
"version": "0.11.5",
"resolved": "https://registry.npmjs.org/osrm-text-instructions/-/osrm-text-instructions-0.11.5.tgz",
"integrity": "sha512-EKCfIXhJHsYQLcuctymvSVH7ulRXx5sGb2MdZL3NzD6XhRVZRkqwRicd9/QI27A5oXW4ojOEJ81RGay7bO6dbA=="
},
"output-file-sync": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz",

View file

@ -48,6 +48,7 @@
"history": "^4.7.2",
"leaflet": "^1.3.3",
"leaflet-editable": "^1.1.0",
"leaflet-routing-machine": "^3.2.8",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-hot-loader": "^4.1.1",

3
src/config.js Normal file
View file

@ -0,0 +1,3 @@
export const CONFIG = {
OSRM_URL: 'http://vault48.org:5000/route/v1',
};

View file

@ -1,5 +1,6 @@
export const MODES = {
POLY: 'POLY',
STICKERS: 'STICKERS',
ROUTER: 'ROUTER',
NONE: 'NONE',
};

View file

@ -30,6 +30,8 @@ export class App extends React.Component {
startStickerMode = () => this.editor.changeMode(MODES.STICKERS);
startRouterMode = () => this.editor.changeMode(MODES.ROUTER);
render() {
const { mode } = this.state;
@ -43,6 +45,9 @@ export class App extends React.Component {
<button onClick={this.startStickerMode}>
{mode === MODES.STICKERS && '-->'}{MODES.STICKERS}
</button>
<button onClick={this.startRouterMode}>
{mode === MODES.ROUTER && '-->'}{MODES.ROUTER}
</button>
</ControlsScreen>
</div>
);

View file

@ -1,7 +1,8 @@
import { Map } from '$modules/Map';
import { Poly } from "$modules/Poly";
import { Poly } from '$modules/Poly';
import { MODES } from '$constants/modes';
import { Stickers } from '$modules/Stickers';
import { Router } from '$modules/Router';
export class Editor {
constructor({
@ -10,8 +11,12 @@ export class Editor {
setMode
}) {
this.map = new Map({ container });
const { lockMapClicks, map: { map } } = this;
this.poly = new Poly({ map: this.map.map });
this.stickers = new Stickers({ map: this.map.map });
this.stickers = new Stickers({ map, lockMapClicks });
this.router = new Router({ map, lockMapClicks });
this.setMode = setMode;
this.mode = mode;
@ -20,14 +25,20 @@ export class Editor {
[MODES.POLY]: {
start: this.poly.continue,
stop: this.poly.stop,
},
[MODES.ROUTER]: {
start: this.routerSetStart,
}
};
this.clickHandlers = {
[MODES.STICKERS]: this.stickers.createOnClick
[MODES.STICKERS]: this.stickers.createOnClick,
[MODES.ROUTER]: this.router.pushWaypointOnClick,
};
this.map.map.addEventListener('mousedown', this.onClick);
map.addEventListener('mouseup', this.onClick);
map.addEventListener('dragstart', () => lockMapClicks(true));
map.addEventListener('dragstop', () => lockMapClicks(false));
}
changeMode = mode => {
@ -52,6 +63,29 @@ export class Editor {
};
onClick = e => {
if (e.originalEvent.which === 3) return; // skip right click
if (this.clickHandlers[this.mode]) this.clickHandlers[this.mode](e);
};
lockMapClicks = lock => {
if (lock) {
this.map.map.removeEventListener('mouseup', this.onClick);
this.map.map.addEventListener('mouseup', this.unlockMapClicks);
} else {
this.map.map.removeEventListener('mouseup', this.unlockMapClicks);
this.map.map.addEventListener('mouseup', this.onClick);
}
};
unlockMapClicks = () => {
this.lockMapClicks(false);
};
routerSetStart = () => {
const { latlngs } = this.poly;
if (!latlngs || !latlngs.length) return;
this.router.startFrom(latlngs.pop());
};
}

View file

@ -8,7 +8,7 @@ export class Map {
constructor({ container }) {
this.map = L.map(container, { editable: true }).setView([55.0153275, 82.9071235], 13);
this.tileLayer = L.tileLayer(providers.dgis, {
this.tileLayer = L.tileLayer(providers.default, {
attribution: 'Независимое Велосообщество',
maxNativeZoom: 18,
maxZoom: 18,

100
src/modules/Router.js Normal file
View file

@ -0,0 +1,100 @@
import L from 'leaflet';
import 'leaflet-routing-machine';
import { CONFIG } from '$config';
import { DomMarker } from '$utils/DomMarker';
export class Router {
constructor({ map, lockMapClicks }) {
const routeLine = r => L.Routing.line(r, {
styles: [
{ color: 'white', opacity: 0.8, weight: 6 },
{ color: '#4597d0', opacity: 1, weight: 4, dashArray: '15,10' }
],
addWaypoints: true,
}).on('linetouched', this.lockPropagations);
this.router = L.Routing.control({
serviceUrl: CONFIG.OSRM_URL,
profile: 'bike',
fitSelectedRoutes: false,
routeLine,
altLineOptions: {
styles: [{ color: '#4597d0', opacity: 1, weight: 3 }]
},
show: false,
plan: L.Routing.plan([], {
createMarker: (i, wp) => L.marker(wp.latLng, {
draggable: true,
icon: this.createWaypointMarker(),
}),
routeWhileDragging: true,
}),
routeWhileDragging: true
});
// .on('waypointschanged', this.updateWaypointsByEvent);
this.router.addTo(map);
this.waypoints = [];
this.lockMapClicks = lockMapClicks;
console.log('router', this.router);
// this.router._line.on('mousedown', console.log);
console.log('map', map);
}
//
pushWaypointOnClick = ({ latlng: { lat, lng } }) => {
const waypoints = this.router.getWaypoints().filter(({ latLng }) => !!latLng);
console.log('push', waypoints);
this.router.setWaypoints([...waypoints, { lat, lng }]);
};
//
// pushWaypoint = latlng => {
// this.waypoints.push(latlng);
// this.updateWaypoints();
// };
//
// updateWaypointsByEvent = (e) => {
// console.log('upd', e);
// // this.waypoints = waypoints.map(({ latlng }) => latlng);
//
// };
//
// updateWaypoints = () => {
// this.router.setWaypoints(this.waypoints);
// };
//
createWaypointMarker = () => {
const element = document.createElement('div');
element.addEventListener('mousedown', this.lockPropagations);
element.addEventListener('mouseup', this.unlockPropagations);
return new DomMarker({
element,
className: 'router-waypoint',
});
};
//
lockPropagations = () => {
console.log('lock');
window.addEventListener('mouseup', this.unlockPropagations);
this.lockMapClicks(true);
};
//
unlockPropagations = e => {
console.log('unlock');
if (e && e.preventPropagations) {
console.log('stop');
e.preventDefault();
e.preventPropagations();
}
window.removeEventListener('mouseup', this.unlockPropagations);
setTimeout(() => this.lockMapClicks(false), 300);
};
startFrom = latlngs => {
this.router.setWaypoints([{ ...latlngs }]);
}
}

View file

@ -1,17 +1,18 @@
import L from 'leaflet';
import 'leaflet-editable';
import { DomMarker } from '$utils/leafletDomMarkers';
import { DomMarker } from '$utils/DomMarker';
export class Sticker {
constructor({
latlng, deleteSticker, map
latlng, deleteSticker, map, lockMapClicks
}) {
this.angle = 2.2;
this.isDragging = false;
this.map = map;
this.deleteSticker = deleteSticker;
this.lockMapClicks = lockMapClicks;
this.element = document.createElement('div');
this.stickerImage = document.createElement('div');
@ -34,14 +35,12 @@ export class Sticker {
this.sticker = L.marker(latlng, { icon: marker });
this.stickerImage.addEventListener('mousedown', this.onDragStart);
this.stickerImage.addEventListener('mouseup', this.onDragStop);
this.stickerImage.addEventListener('click', this.preventPropagations);
this.element.addEventListener('mousedown', this.preventPropagations);
this.setAngle(this.angle);
this.stickerImage.addEventListener('mousedown', this.onDragStart);
this.stickerImage.addEventListener('mouseup', this.onDragStop);
this.element.addEventListener('mouseup', this.preventPropagations);
this.stickerDelete.addEventListener('click', this.onDelete);
}
@ -55,6 +54,8 @@ export class Sticker {
this.isDragging = true;
this.sticker.disableEdit();
this.lockMapClicks(true);
window.addEventListener('mousemove', this.onDrag);
window.addEventListener('mouseup', this.onDragStop);
};
@ -74,6 +75,8 @@ export class Sticker {
window.removeEventListener('mousemove', this.onDrag);
window.removeEventListener('mouseup', this.onDragStop);
this.lockMapClicks(false);
};
onDrag = e => {
@ -82,7 +85,6 @@ export class Sticker {
};
estimateAngle = e => {
console.log('est');
const { x, y } = this.element.getBoundingClientRect();
const { pageX, pageY } = e;
this.angle = Math.atan2((y - pageY), (x - pageX));

View file

@ -2,10 +2,11 @@ import L from 'leaflet';
import { Sticker } from '$modules/Sticker';
export class Stickers {
constructor({ map }) {
constructor({ map, lockMapClicks }) {
this.map = map;
this.layer = L.layerGroup();
this.lockMapClicks = lockMapClicks;
this.stickers = [];
this.layer.addTo(this.map);
@ -23,6 +24,7 @@ export class Stickers {
latlng,
deleteSticker: this.deleteStickerByReference,
map: this.map,
lockMapClicks: this.lockMapClicks,
});
this.stickers.push(sticker);

View file

@ -28,6 +28,32 @@ const vertexMixin = css`
}
`;
const routerMixin = css`
.leaflet-control-container .leaflet-routing-container-hide {
display: none;
}
.router-waypoint {
width: 40px;
height: 40px;
margin-left: -20px;
margin-top: -20px;
outline: none;
z-index: 10001;
::after {
content: ' ';
display: block;
width: 20px;
height: 20px;
border-radius: 10px;
box-shadow: 0 0 0 2px #4597d0;
margin-left: 10px;
margin-top: 10px;
}
}
`;
const stickers = css`
.sticker-container {
outline: none;
@ -132,4 +158,5 @@ export const MapScreen = styled.div.attrs({ id: 'map' })`
${vertexMixin}
${stickers}
${routerMixin}
`;