mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 02:56:41 +07:00
basic router
This commit is contained in:
parent
0d8a507620
commit
e477f50283
12 changed files with 215 additions and 15 deletions
25
package-lock.json
generated
25
package-lock.json
generated
|
@ -689,6 +689,16 @@
|
||||||
"to-fast-properties": "^2.0.0"
|
"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": {
|
"@mrmlnc/readdir-enhanced": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/leaflet-editable/-/leaflet-editable-1.1.0.tgz",
|
||||||
"integrity": "sha1-93dZekCoGic/KHtIn9D+XM1gyNA="
|
"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": {
|
"levn": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||||
|
@ -8881,6 +8901,11 @@
|
||||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||||
"dev": true
|
"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": {
|
"output-file-sync": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz",
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
"history": "^4.7.2",
|
"history": "^4.7.2",
|
||||||
"leaflet": "^1.3.3",
|
"leaflet": "^1.3.3",
|
||||||
"leaflet-editable": "^1.1.0",
|
"leaflet-editable": "^1.1.0",
|
||||||
|
"leaflet-routing-machine": "^3.2.8",
|
||||||
"react": "^16.3.2",
|
"react": "^16.3.2",
|
||||||
"react-dom": "^16.3.2",
|
"react-dom": "^16.3.2",
|
||||||
"react-hot-loader": "^4.1.1",
|
"react-hot-loader": "^4.1.1",
|
||||||
|
|
3
src/config.js
Normal file
3
src/config.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const CONFIG = {
|
||||||
|
OSRM_URL: 'http://vault48.org:5000/route/v1',
|
||||||
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
export const MODES = {
|
export const MODES = {
|
||||||
POLY: 'POLY',
|
POLY: 'POLY',
|
||||||
STICKERS: 'STICKERS',
|
STICKERS: 'STICKERS',
|
||||||
|
ROUTER: 'ROUTER',
|
||||||
NONE: 'NONE',
|
NONE: 'NONE',
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,6 +30,8 @@ export class App extends React.Component {
|
||||||
|
|
||||||
startStickerMode = () => this.editor.changeMode(MODES.STICKERS);
|
startStickerMode = () => this.editor.changeMode(MODES.STICKERS);
|
||||||
|
|
||||||
|
startRouterMode = () => this.editor.changeMode(MODES.ROUTER);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { mode } = this.state;
|
const { mode } = this.state;
|
||||||
|
|
||||||
|
@ -43,6 +45,9 @@ export class App extends React.Component {
|
||||||
<button onClick={this.startStickerMode}>
|
<button onClick={this.startStickerMode}>
|
||||||
{mode === MODES.STICKERS && '-->'}{MODES.STICKERS}
|
{mode === MODES.STICKERS && '-->'}{MODES.STICKERS}
|
||||||
</button>
|
</button>
|
||||||
|
<button onClick={this.startRouterMode}>
|
||||||
|
{mode === MODES.ROUTER && '-->'}{MODES.ROUTER}
|
||||||
|
</button>
|
||||||
</ControlsScreen>
|
</ControlsScreen>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Map } from '$modules/Map';
|
import { Map } from '$modules/Map';
|
||||||
import { Poly } from "$modules/Poly";
|
import { Poly } from '$modules/Poly';
|
||||||
import { MODES } from '$constants/modes';
|
import { MODES } from '$constants/modes';
|
||||||
import { Stickers } from '$modules/Stickers';
|
import { Stickers } from '$modules/Stickers';
|
||||||
|
import { Router } from '$modules/Router';
|
||||||
|
|
||||||
export class Editor {
|
export class Editor {
|
||||||
constructor({
|
constructor({
|
||||||
|
@ -10,8 +11,12 @@ export class Editor {
|
||||||
setMode
|
setMode
|
||||||
}) {
|
}) {
|
||||||
this.map = new Map({ container });
|
this.map = new Map({ container });
|
||||||
|
|
||||||
|
const { lockMapClicks, map: { map } } = this;
|
||||||
|
|
||||||
this.poly = new Poly({ map: this.map.map });
|
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.setMode = setMode;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
@ -20,14 +25,20 @@ export class Editor {
|
||||||
[MODES.POLY]: {
|
[MODES.POLY]: {
|
||||||
start: this.poly.continue,
|
start: this.poly.continue,
|
||||||
stop: this.poly.stop,
|
stop: this.poly.stop,
|
||||||
|
},
|
||||||
|
[MODES.ROUTER]: {
|
||||||
|
start: this.routerSetStart,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.clickHandlers = {
|
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 => {
|
changeMode = mode => {
|
||||||
|
@ -52,6 +63,29 @@ export class Editor {
|
||||||
};
|
};
|
||||||
|
|
||||||
onClick = e => {
|
onClick = e => {
|
||||||
|
if (e.originalEvent.which === 3) return; // skip right click
|
||||||
if (this.clickHandlers[this.mode]) this.clickHandlers[this.mode](e);
|
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());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class Map {
|
||||||
constructor({ container }) {
|
constructor({ container }) {
|
||||||
this.map = L.map(container, { editable: true }).setView([55.0153275, 82.9071235], 13);
|
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: 'Независимое Велосообщество',
|
attribution: 'Независимое Велосообщество',
|
||||||
maxNativeZoom: 18,
|
maxNativeZoom: 18,
|
||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
|
|
100
src/modules/Router.js
Normal file
100
src/modules/Router.js
Normal 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 }]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,18 @@
|
||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
import 'leaflet-editable';
|
import 'leaflet-editable';
|
||||||
|
|
||||||
import { DomMarker } from '$utils/leafletDomMarkers';
|
import { DomMarker } from '$utils/DomMarker';
|
||||||
|
|
||||||
export class Sticker {
|
export class Sticker {
|
||||||
constructor({
|
constructor({
|
||||||
latlng, deleteSticker, map
|
latlng, deleteSticker, map, lockMapClicks
|
||||||
}) {
|
}) {
|
||||||
this.angle = 2.2;
|
this.angle = 2.2;
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
this.map = map;
|
this.map = map;
|
||||||
|
|
||||||
this.deleteSticker = deleteSticker;
|
this.deleteSticker = deleteSticker;
|
||||||
|
this.lockMapClicks = lockMapClicks;
|
||||||
|
|
||||||
this.element = document.createElement('div');
|
this.element = document.createElement('div');
|
||||||
this.stickerImage = document.createElement('div');
|
this.stickerImage = document.createElement('div');
|
||||||
|
@ -34,14 +35,12 @@ export class Sticker {
|
||||||
|
|
||||||
this.sticker = L.marker(latlng, { icon: marker });
|
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.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);
|
this.stickerDelete.addEventListener('click', this.onDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +54,8 @@ export class Sticker {
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
this.sticker.disableEdit();
|
this.sticker.disableEdit();
|
||||||
|
|
||||||
|
this.lockMapClicks(true);
|
||||||
|
|
||||||
window.addEventListener('mousemove', this.onDrag);
|
window.addEventListener('mousemove', this.onDrag);
|
||||||
window.addEventListener('mouseup', this.onDragStop);
|
window.addEventListener('mouseup', this.onDragStop);
|
||||||
};
|
};
|
||||||
|
@ -74,6 +75,8 @@ export class Sticker {
|
||||||
|
|
||||||
window.removeEventListener('mousemove', this.onDrag);
|
window.removeEventListener('mousemove', this.onDrag);
|
||||||
window.removeEventListener('mouseup', this.onDragStop);
|
window.removeEventListener('mouseup', this.onDragStop);
|
||||||
|
|
||||||
|
this.lockMapClicks(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
onDrag = e => {
|
onDrag = e => {
|
||||||
|
@ -82,7 +85,6 @@ export class Sticker {
|
||||||
};
|
};
|
||||||
|
|
||||||
estimateAngle = e => {
|
estimateAngle = e => {
|
||||||
console.log('est');
|
|
||||||
const { x, y } = this.element.getBoundingClientRect();
|
const { x, y } = this.element.getBoundingClientRect();
|
||||||
const { pageX, pageY } = e;
|
const { pageX, pageY } = e;
|
||||||
this.angle = Math.atan2((y - pageY), (x - pageX));
|
this.angle = Math.atan2((y - pageY), (x - pageX));
|
||||||
|
|
|
@ -2,10 +2,11 @@ import L from 'leaflet';
|
||||||
import { Sticker } from '$modules/Sticker';
|
import { Sticker } from '$modules/Sticker';
|
||||||
|
|
||||||
export class Stickers {
|
export class Stickers {
|
||||||
constructor({ map }) {
|
constructor({ map, lockMapClicks }) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.layer = L.layerGroup();
|
this.layer = L.layerGroup();
|
||||||
|
|
||||||
|
this.lockMapClicks = lockMapClicks;
|
||||||
this.stickers = [];
|
this.stickers = [];
|
||||||
|
|
||||||
this.layer.addTo(this.map);
|
this.layer.addTo(this.map);
|
||||||
|
@ -23,6 +24,7 @@ export class Stickers {
|
||||||
latlng,
|
latlng,
|
||||||
deleteSticker: this.deleteStickerByReference,
|
deleteSticker: this.deleteStickerByReference,
|
||||||
map: this.map,
|
map: this.map,
|
||||||
|
lockMapClicks: this.lockMapClicks,
|
||||||
});
|
});
|
||||||
this.stickers.push(sticker);
|
this.stickers.push(sticker);
|
||||||
|
|
||||||
|
|
|
@ -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`
|
const stickers = css`
|
||||||
.sticker-container {
|
.sticker-container {
|
||||||
outline: none;
|
outline: none;
|
||||||
|
@ -132,4 +158,5 @@ export const MapScreen = styled.div.attrs({ id: 'map' })`
|
||||||
|
|
||||||
${vertexMixin}
|
${vertexMixin}
|
||||||
${stickers}
|
${stickers}
|
||||||
|
${routerMixin}
|
||||||
`;
|
`;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue