mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 02:56:41 +07:00
styled panels
This commit is contained in:
parent
7229a48297
commit
d17a7b6aef
24 changed files with 470 additions and 421 deletions
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -11923,6 +11923,11 @@
|
||||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"typeface-montserrat": {
|
||||||
|
"version": "0.0.54",
|
||||||
|
"resolved": "https://registry.npmjs.org/typeface-montserrat/-/typeface-montserrat-0.0.54.tgz",
|
||||||
|
"integrity": "sha512-Typhap0PWT299+Va0G/8ZtycHMXrH4gBWKfiW977KEBx5rXUUCa70gvqLx1fdA0WAo6bhSAQmo8uc+QFAmjPww=="
|
||||||
|
},
|
||||||
"ua-parser-js": {
|
"ua-parser-js": {
|
||||||
"version": "0.7.18",
|
"version": "0.7.18",
|
||||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz",
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz",
|
||||||
|
@ -12993,6 +12998,11 @@
|
||||||
"integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
|
"integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"wfk-montserrat": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wfk-montserrat/-/wfk-montserrat-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-XgRPn20Qp20BHs1UXyvMVQgblHSwl3bMhrNeXF921fqxIOT0ZPMynqWa60q5wU5RkRTxQfZsgv0Rt6prMSpvhQ=="
|
||||||
|
},
|
||||||
"whatwg-fetch": {
|
"whatwg-fetch": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
|
||||||
|
|
|
@ -63,7 +63,9 @@
|
||||||
"scrypt": "^6.0.3",
|
"scrypt": "^6.0.3",
|
||||||
"styled-components": "^3.2.6",
|
"styled-components": "^3.2.6",
|
||||||
"styled-theming": "^2.2.0",
|
"styled-theming": "^2.2.0",
|
||||||
"webpack-git-hash": "^1.0.2"
|
"typeface-montserrat": "0.0.54",
|
||||||
|
"webpack-git-hash": "^1.0.2",
|
||||||
|
"wfk-montserrat": "^1.0.0"
|
||||||
},
|
},
|
||||||
"flow-coverage-report": {
|
"flow-coverage-report": {
|
||||||
"includeGlob": [
|
"includeGlob": [
|
||||||
|
|
|
@ -11,7 +11,7 @@ export const Fills = () => (
|
||||||
|
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="activePathGradient" x1="-20%" x2="50%" y1="0%" y2="140%">
|
<linearGradient id="activePathGradient" x1="-20%" x2="50%" y1="0%" y2="140%">
|
||||||
<stop offset="0%" stopColor="#ff9900" />
|
<stop offset="0%" stopColor="#ff7700" />
|
||||||
<stop offset="100%" stopColor="#ff3344" />
|
<stop offset="100%" stopColor="#ff3344" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
14
src/components/panels/EditorDialog.jsx
Normal file
14
src/components/panels/EditorDialog.jsx
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { MODES } from '$constants/modes';
|
||||||
|
|
||||||
|
import { RouterHelper } from '$components/router/RouterHelper';
|
||||||
|
|
||||||
|
export const EditorDialog = ({ mode, routerPoints }) => {
|
||||||
|
const showDialog = (mode === MODES.ROUTER);
|
||||||
|
return (
|
||||||
|
showDialog &&
|
||||||
|
<div id="control-dialog">
|
||||||
|
{ mode === MODES.ROUTER && <RouterHelper routerPoints={routerPoints} /> }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -2,7 +2,8 @@ import React from 'react';
|
||||||
import { MODES } from '$constants/modes';
|
import { MODES } from '$constants/modes';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import { Icon } from '$components/Icon';
|
import { Icon } from '$components/panels/Icon';
|
||||||
|
import { EditorDialog } from '$components/panels/EditorDialog';
|
||||||
|
|
||||||
export class EditorPanel extends React.PureComponent {
|
export class EditorPanel extends React.PureComponent {
|
||||||
startPolyMode = () => this.props.editor.changeMode(MODES.POLY);
|
startPolyMode = () => this.props.editor.changeMode(MODES.POLY);
|
||||||
|
@ -14,35 +15,69 @@ export class EditorPanel extends React.PureComponent {
|
||||||
startShotterMode = () => this.props.editor.changeMode(MODES.SHOTTER);
|
startShotterMode = () => this.props.editor.changeMode(MODES.SHOTTER);
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { mode } = this.props;
|
const { mode, routerPoints } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="control-screen">
|
<div>
|
||||||
<button
|
|
||||||
className={classnames({ active: mode === MODES.ROUTER })}
|
|
||||||
onClick={this.startRouterMode}
|
|
||||||
>
|
|
||||||
<Icon icon="icon-router" />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={classnames({ active: mode === MODES.POLY })}
|
|
||||||
onClick={this.startPolyMode}
|
|
||||||
>
|
|
||||||
<Icon icon="icon-poly" />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={classnames({ active: mode === MODES.STICKERS })}
|
|
||||||
onClick={this.startStickerMode}
|
|
||||||
>
|
|
||||||
<Icon icon="icon-sticker" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
<EditorDialog
|
||||||
className={classnames({ active: mode === MODES.SHOTTER })}
|
mode={mode}
|
||||||
onClick={this.startShotterMode}
|
routerPoints={routerPoints}
|
||||||
>
|
/>
|
||||||
<Icon icon="icon-shooter" />
|
|
||||||
</button>
|
<div className="panel">
|
||||||
|
<div className="control-bar">
|
||||||
|
<button
|
||||||
|
onClick={this.startShotterMode}
|
||||||
|
>
|
||||||
|
<span>РЕДАКТОР</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="panel right">
|
||||||
|
<div className="control-bar">
|
||||||
|
<button
|
||||||
|
className={classnames({ active: mode === MODES.ROUTER })}
|
||||||
|
onClick={this.startRouterMode}
|
||||||
|
>
|
||||||
|
<Icon icon="icon-router" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={classnames({ active: mode === MODES.POLY })}
|
||||||
|
onClick={this.startPolyMode}
|
||||||
|
>
|
||||||
|
<Icon icon="icon-poly" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={classnames({ active: mode === MODES.STICKERS })}
|
||||||
|
onClick={this.startStickerMode}
|
||||||
|
>
|
||||||
|
<Icon icon="icon-sticker" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="control-sep" />
|
||||||
|
|
||||||
|
<div className="control-bar">
|
||||||
|
<button
|
||||||
|
className={classnames({ active: mode === MODES.SHOTTER })}
|
||||||
|
onClick={this.startShotterMode}
|
||||||
|
>
|
||||||
|
<Icon icon="icon-shooter" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className={classnames('highlighted', { active: mode === MODES.SHOTTER })}
|
||||||
|
onClick={this.startShotterMode}
|
||||||
|
>
|
||||||
|
<span>СХОРОНИТЬ</span>
|
||||||
|
<Icon icon="icon-shooter" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import sprite from '$sprites/icon.svg';
|
import sprite from '$sprites/icon.svg';
|
||||||
|
|
||||||
export const Icon = ({ icon, size = 32 }) => (
|
export const Icon = ({ icon, size = 32 }) => (
|
||||||
<svg width={size} height={size} viewBox="0 0 32 32" preserveAspectRatio="midXmidY meet">
|
<svg width={size} height={size} viewBox="0 0 32 32">
|
||||||
<use xlinkHref={`${sprite}#${icon}`} x={0} y={0} />
|
<use xlinkHref={`${sprite}#${icon}`} x={0} y={0} />
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
54
src/components/router/RouterHelper.jsx
Normal file
54
src/components/router/RouterHelper.jsx
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const noPoints = () => (
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstPoint = () => (
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const draggablePoints = () => (
|
||||||
|
<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>
|
||||||
|
<div className="button primary router-helper__button">
|
||||||
|
Применить
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const RouterHelper = ({ routerPoints }) => (
|
||||||
|
<div>
|
||||||
|
{ !routerPoints && noPoints() }
|
||||||
|
{ routerPoints === 1 && firstPoint() }
|
||||||
|
{ routerPoints >= 2 && draggablePoints() }
|
||||||
|
</div>
|
||||||
|
);
|
|
@ -7,37 +7,38 @@ import { Fills } from '$components/Fills';
|
||||||
export class App extends React.Component {
|
export class App extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
mode: 'none',
|
mode: 'none',
|
||||||
editor: null,
|
routerPoints: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const container = 'map';
|
|
||||||
const { mode } = this.state;
|
|
||||||
|
|
||||||
const editor = new Editor({
|
|
||||||
container,
|
|
||||||
mode,
|
|
||||||
setMode: this.setMode,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState({ editor })
|
|
||||||
}
|
|
||||||
|
|
||||||
setMode = mode => {
|
setMode = mode => {
|
||||||
this.setState({ mode });
|
this.setState({ mode });
|
||||||
};
|
};
|
||||||
|
setRouterPoints = routerPoints => {
|
||||||
|
this.setState({ routerPoints });
|
||||||
|
};
|
||||||
|
|
||||||
|
editor = new Editor({
|
||||||
|
container: 'map',
|
||||||
|
mode: this.state.mode,
|
||||||
|
setMode: this.setMode,
|
||||||
|
setRouterPoints: this.setRouterPoints,
|
||||||
|
});
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
state: { mode, editor },
|
editor,
|
||||||
|
state: { mode, routerPoints },
|
||||||
} = this;
|
} = this;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Fills />
|
<Fills />
|
||||||
<div id="map" />
|
<EditorPanel
|
||||||
<EditorPanel editor={editor} mode={mode} />
|
editor={editor}
|
||||||
|
mode={mode}
|
||||||
|
routerPoints={routerPoints}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,5 +11,7 @@
|
||||||
<meta content="/misc/vk_preview.png">
|
<meta content="/misc/vk_preview.png">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<section id="index"></section>
|
<section id="index"></section>
|
||||||
|
<div id="map" />
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -3,8 +3,7 @@ import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import { App } from '$containers/App';
|
import { App } from '$containers/App';
|
||||||
|
|
||||||
import '$styles/map.less';
|
import '$styles/main.less';
|
||||||
import '$styles/controls.less';
|
|
||||||
|
|
||||||
export const Index = () => (
|
export const Index = () => (
|
||||||
<App />
|
<App />
|
||||||
|
|
|
@ -9,7 +9,8 @@ export class Editor {
|
||||||
constructor({
|
constructor({
|
||||||
container,
|
container,
|
||||||
mode,
|
mode,
|
||||||
setMode
|
setMode,
|
||||||
|
setRouterPoints,
|
||||||
}) {
|
}) {
|
||||||
this.map = new Map({ container });
|
this.map = new Map({ container });
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ export class Editor {
|
||||||
|
|
||||||
this.poly = new Poly({ map, routerMoveStart, lockMapClicks });
|
this.poly = new Poly({ map, routerMoveStart, lockMapClicks });
|
||||||
this.stickers = new Stickers({ map, lockMapClicks });
|
this.stickers = new Stickers({ map, lockMapClicks });
|
||||||
this.router = new Router({ map, lockMapClicks });
|
this.router = new Router({ map, lockMapClicks, setRouterPoints });
|
||||||
this.shotter = new Shotter({ map });
|
this.shotter = new Shotter({ map });
|
||||||
|
|
||||||
this.setMode = setMode;
|
this.setMode = setMode;
|
||||||
|
@ -91,7 +92,7 @@ export class Editor {
|
||||||
|
|
||||||
if (!latlngs || !latlngs.length) return;
|
if (!latlngs || !latlngs.length) return;
|
||||||
|
|
||||||
this.router.startFrom(latlngs.pop());
|
this.router.startFrom(latlngs[latlngs.length - 1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
routerMoveStart = () => {
|
routerMoveStart = () => {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class Map {
|
||||||
constructor({ container }) {
|
constructor({ container }) {
|
||||||
this.map = map(container, { editable: true }).setView([55.0153275, 82.9071235], 13);
|
this.map = map(container, { editable: true }).setView([55.0153275, 82.9071235], 13);
|
||||||
|
|
||||||
this.tileLayer = tileLayer(providers.default, {
|
this.tileLayer = tileLayer(providers.dgis, {
|
||||||
attribution: 'Независимое Велосообщество',
|
attribution: 'Независимое Велосообщество',
|
||||||
maxNativeZoom: 18,
|
maxNativeZoom: 18,
|
||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { polyline } from "leaflet";
|
import { polyline } from "leaflet";
|
||||||
|
|
||||||
const polyStyle = { color: 'url(#activePathGradient)', weight: '5' };
|
const polyStyle = { color: 'url(#activePathGradient)', weight: '6' };
|
||||||
|
// const polyStyle = { color: '#ff3344', weight: '5' };
|
||||||
|
|
||||||
export class Poly {
|
export class Poly {
|
||||||
constructor({ map, routerMoveStart, lockMapClicks }) {
|
constructor({ map, routerMoveStart, lockMapClicks }) {
|
||||||
|
|
|
@ -4,11 +4,13 @@ import { CONFIG } from '$config';
|
||||||
import { DomMarker } from '$utils/DomMarker';
|
import { DomMarker } from '$utils/DomMarker';
|
||||||
|
|
||||||
export class Router {
|
export class Router {
|
||||||
constructor({ map, lockMapClicks }) {
|
constructor({ map, lockMapClicks, setRouterPoints }) {
|
||||||
const routeLine = r => Routing.line(r, {
|
const routeLine = r => Routing.line(r, {
|
||||||
styles: [
|
styles: [
|
||||||
{ color: 'white', opacity: 0.8, weight: 6 },
|
{ color: 'white', opacity: 0.8, weight: 6 },
|
||||||
{ color: '#4597d0', opacity: 1, weight: 4, dashArray: '15,10' }
|
{
|
||||||
|
color: '#4597d0', opacity: 1, weight: 4, dashArray: '15,10'
|
||||||
|
}
|
||||||
],
|
],
|
||||||
addWaypoints: true,
|
addWaypoints: true,
|
||||||
}).on('linetouched', this.lockPropagations);
|
}).on('linetouched', this.lockPropagations);
|
||||||
|
@ -30,14 +32,13 @@ export class Router {
|
||||||
routeWhileDragging: true,
|
routeWhileDragging: true,
|
||||||
}),
|
}),
|
||||||
routeWhileDragging: true
|
routeWhileDragging: true
|
||||||
});
|
}).on('waypointschanged', this.updateWaypointsCount);
|
||||||
// .on('waypointschanged', this.updateWaypointsByEvent);
|
|
||||||
|
|
||||||
this.router.addTo(map);
|
this.router.addTo(map);
|
||||||
|
|
||||||
this.waypoints = [];
|
this.waypoints = [];
|
||||||
this.lockMapClicks = lockMapClicks;
|
this.lockMapClicks = lockMapClicks;
|
||||||
|
this.setRouterPoints = setRouterPoints;
|
||||||
// this.router._line.on('mousedown', console.log);
|
// this.router._line.on('mousedown', console.log);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -46,22 +47,7 @@ export class Router {
|
||||||
console.log('push', waypoints);
|
console.log('push', waypoints);
|
||||||
this.router.setWaypoints([...waypoints, { lat, lng }]);
|
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 = () => {
|
createWaypointMarker = () => {
|
||||||
const element = document.createElement('div');
|
const element = document.createElement('div');
|
||||||
|
|
||||||
|
@ -119,4 +105,9 @@ export class Router {
|
||||||
|
|
||||||
this.router.setWaypoints(waypoints);
|
this.router.setWaypoints(waypoints);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateWaypointsCount = () => {
|
||||||
|
const waypoints = this.router.getWaypoints().filter(({ latLng }) => !!latLng);
|
||||||
|
this.setRouterPoints(waypoints.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,5 +34,6 @@
|
||||||
<g transform="translate(18 6)">
|
<g transform="translate(18 6)">
|
||||||
<path d="m0 0l-4.391.054c-1.418.531-2.34 1.756-3.176 3.102h-5.178c-.68.317-1.351.655-1.455 2.584v11.49c.17 1.001.58 1.765 1.455 2.06h22.537c.746-.044 1.288-.426 1.68-1.06v-13.517c-.185-1.643-.916-1.65-1.68-1.557h-6.62c-.326-1.26-1.91-2.247-3.172-3.156zm-2.122 5.289c3.227 0 5.87 2.626 5.87 5.846s-2.643 5.845-5.87 5.845c-3.227 0-5.869-2.626-5.869-5.845 0-3.22 2.642-5.846 5.87-5.846zm0 1.998a3.844 3.844 0 0 0-3.869 3.848 3.842 3.842 0 0 0 3.87 3.845 3.84 3.84 0 0 0 3.866-3.845 3.842 3.842 0 0 0-3.867-3.848z" />
|
<path d="m0 0l-4.391.054c-1.418.531-2.34 1.756-3.176 3.102h-5.178c-.68.317-1.351.655-1.455 2.584v11.49c.17 1.001.58 1.765 1.455 2.06h22.537c.746-.044 1.288-.426 1.68-1.06v-13.517c-.185-1.643-.916-1.65-1.68-1.557h-6.62c-.326-1.26-1.91-2.247-3.172-3.156zm-2.122 5.289c3.227 0 5.87 2.626 5.87 5.846s-2.643 5.845-5.87 5.845c-3.227 0-5.869-2.626-5.869-5.845 0-3.22 2.642-5.846 5.87-5.846zm0 1.998a3.844 3.844 0 0 0-3.869 3.848 3.842 3.842 0 0 0 3.87 3.845 3.84 3.84 0 0 0 3.866-3.845 3.842 3.842 0 0 0-3.867-3.848z" />
|
||||||
</g>
|
</g>
|
||||||
|
</g>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
35
src/styles/button.less
Normal file
35
src/styles/button.less
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
.button {
|
||||||
|
background: #444444;
|
||||||
|
padding: 4px 16px;
|
||||||
|
height: 18px;
|
||||||
|
line-height: 1em;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background: #3c78db;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
background: #ed2f3b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
.button {
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-radius: 4px 0 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0 4px 4px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
|
|
||||||
#control-screen {
|
|
||||||
position: fixed;
|
|
||||||
right: 10px;
|
|
||||||
bottom: 0px;
|
|
||||||
height: 48px;
|
|
||||||
min-width: 120px;
|
|
||||||
background: #333333;
|
|
||||||
z-index: 2;
|
|
||||||
color: white;
|
|
||||||
border-radius: 4px 4px 0 0;
|
|
||||||
padding: 0 4px 0 4px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
border: none;
|
|
||||||
background: transparent;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
padding: 8px;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
svg {
|
|
||||||
fill: url(#activeButtonGradient);
|
|
||||||
stroke: url(#activeButtonGradient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
fill: white;
|
|
||||||
stroke: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
export const ControlsScreen = styled.div`
|
|
||||||
position: fixed;
|
|
||||||
right: 10px;
|
|
||||||
bottom: 10px;
|
|
||||||
height: 48px;
|
|
||||||
min-width: 120px;
|
|
||||||
background: #333333;
|
|
||||||
border-radius: 2px;
|
|
||||||
z-index: 2;
|
|
||||||
color: white;
|
|
||||||
`;
|
|
26
src/styles/main.less
Normal file
26
src/styles/main.less
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
@import 'map.less';
|
||||||
|
@import 'panel.less';
|
||||||
|
@import 'router.less';
|
||||||
|
@import 'stickers.less';
|
||||||
|
@import 'button.less';
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gray {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.white {
|
||||||
|
color: white;
|
||||||
|
}
|
|
@ -38,139 +38,3 @@
|
||||||
.leaflet-control-container .leaflet-routing-container-hide {
|
.leaflet-control-container .leaflet-routing-container-hide {
|
||||||
display: none;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticker-container {
|
|
||||||
outline: none;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
content: ' ';
|
|
||||||
box-shadow: 0 0 10px 1px #ff3344;
|
|
||||||
background: #ff334422;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
left: -24px;
|
|
||||||
top: -24px;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 40px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 250ms, transform 500ms;
|
|
||||||
transform: scale(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &:active {
|
|
||||||
.sticker-delete {
|
|
||||||
transform: scale(1);
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticker-label {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
position: absolute;
|
|
||||||
background: white;
|
|
||||||
border-radius: 32px;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: ' ';
|
|
||||||
box-shadow: 0 0 0 1px #ff3344;
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
left: -16px;
|
|
||||||
top: -16px;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 40px;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticker-arrow {
|
|
||||||
position: absolute;
|
|
||||||
background: red;
|
|
||||||
transform-origin: 0 0;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: ' ';
|
|
||||||
background: #ff3344;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
transform-origin: 0 0;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticker-delete {
|
|
||||||
position: absolute;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
background: red;
|
|
||||||
border-radius: 24px;
|
|
||||||
transition: transform 500ms;
|
|
||||||
transform: scale(0);
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
transform: scale(1.2) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,162 +0,0 @@
|
||||||
import styled, { css } from 'styled-components';
|
|
||||||
|
|
||||||
const vertexMixin = css`
|
|
||||||
.leaflet-vertex-icon, .leaflet-middle-icon {
|
|
||||||
border-radius: 10px;
|
|
||||||
opacity :1;
|
|
||||||
border: none;
|
|
||||||
width: 16px !important;
|
|
||||||
height: 16px !important;margin-left:-8px !important;margin-top:-8px !important;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-vertex-icon::after, .leaflet-middle-icon::after {
|
|
||||||
content: ' ';
|
|
||||||
position:absolute;top:4px;left:4px;width:8px;height:8px;
|
|
||||||
background:white;border-radius: 8px;transform:scale(1);
|
|
||||||
transition:transform 150ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-vertex-icon:hover, .leaflet-middle-icon:hover {
|
|
||||||
opacity: 1 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-vertex-icon:hover::after, .leaflet-middle-icon:hover::after,
|
|
||||||
.leaflet-vertex-icon:active::after, .leaflet-middle-icon:active::after {
|
|
||||||
transform: scale(2);
|
|
||||||
box-shadow: #999 0 0 5px 2px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
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;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
::before {
|
|
||||||
content: ' ';
|
|
||||||
box-shadow: 0 0 10px 1px #ff3344;
|
|
||||||
background: #ff334422;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
left: -24px;
|
|
||||||
top: -24px;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 40px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 250ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
:hover {
|
|
||||||
.sticker-delete {
|
|
||||||
transform: scale(1);
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticker-label {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
position: absolute;
|
|
||||||
background: white;
|
|
||||||
border-radius: 32px;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
::after {
|
|
||||||
content: ' ';
|
|
||||||
box-shadow: 0 0 0 1px #ff3344;
|
|
||||||
width: 80px;
|
|
||||||
height: 80px;
|
|
||||||
left: ${24 - 40}px;
|
|
||||||
top: ${24 - 40}px;
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 40px;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticker-arrow {
|
|
||||||
position: absolute;
|
|
||||||
background: red;
|
|
||||||
transform-origin: 0 0;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
::after {
|
|
||||||
content: ' ';
|
|
||||||
background: #ff3344;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
transform-origin: 0 0;
|
|
||||||
transform: rotate(-45deg);
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sticker-delete {
|
|
||||||
position: absolute;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
background: red;
|
|
||||||
border-radius: 24px;
|
|
||||||
transition: transform 500ms;
|
|
||||||
transform: scale(0);
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
:hover {
|
|
||||||
transform: scale(1.2) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const MapScreen = styled.div.attrs({ id: 'map' })`
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
${vertexMixin}
|
|
||||||
${stickers}
|
|
||||||
${routerMixin}
|
|
||||||
`;
|
|
92
src/styles/panel.less
Normal file
92
src/styles/panel.less
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
.control-bar {
|
||||||
|
background: #333333;
|
||||||
|
border-radius: 3px;
|
||||||
|
display: flex;
|
||||||
|
box-shadow: rgba(0,0,0,0.3) 0 2px 0, inset rgba(255, 255, 255, 0.05) 1px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-sep {
|
||||||
|
height: 44px;
|
||||||
|
background: #222222;
|
||||||
|
width: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
position: fixed;
|
||||||
|
left: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
z-index: 3;
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
left: auto;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
padding: 8px;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
color: white;
|
||||||
|
align-items: center;
|
||||||
|
transition: background-color 500ms;
|
||||||
|
height: 48px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(100, 100, 100, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 200;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
svg {
|
||||||
|
fill: url(#activeButtonGradient);
|
||||||
|
stroke: url(#activeButtonGradient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.highlighted {
|
||||||
|
background: linear-gradient(150deg, #05a4ff, #7137c8);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: white;
|
||||||
|
stroke: white;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-separator {
|
||||||
|
height: 48px;
|
||||||
|
width: 4px;
|
||||||
|
background: #222222;
|
||||||
|
}
|
||||||
|
|
||||||
|
#control-dialog {
|
||||||
|
background: #222222;
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
z-index: 2;
|
||||||
|
color: white;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-bottom: 48px;
|
||||||
|
box-shadow: rgba(0,0,0,0.3) 0 2px 0, inset rgba(255, 255, 255, 0.05) 1px 1px;
|
||||||
|
}
|
36
src/styles/router.less
Normal file
36
src/styles/router.less
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.router-helper {
|
||||||
|
width: 500px;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: 200;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.router-helper__text {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.router-helper__buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
95
src/styles/stickers.less
Normal file
95
src/styles/stickers.less
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
.sticker-container {
|
||||||
|
outline: none;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: ' ';
|
||||||
|
box-shadow: 0 0 10px 1px #ff3344;
|
||||||
|
background: #ff334422;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
left: -24px;
|
||||||
|
top: -24px;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 40px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 250ms, transform 500ms;
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover, &:active {
|
||||||
|
.sticker-delete {
|
||||||
|
transform: scale(1);
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticker-label {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
position: absolute;
|
||||||
|
background: white;
|
||||||
|
border-radius: 32px;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ' ';
|
||||||
|
box-shadow: 0 0 0 1px #ff3344;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
left: -16px;
|
||||||
|
top: -16px;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 40px;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticker-arrow {
|
||||||
|
position: absolute;
|
||||||
|
background: red;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ' ';
|
||||||
|
background: #ff3344;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticker-delete {
|
||||||
|
position: absolute;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background: red;
|
||||||
|
border-radius: 24px;
|
||||||
|
transition: transform 500ms;
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.2) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-container .leaflet-routing-container-hide {
|
||||||
|
display: none;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue