mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 02:56:41 +07:00
initial commit
This commit is contained in:
commit
4a2a343e41
11 changed files with 13640 additions and 0 deletions
12
.babelrc
Executable file
12
.babelrc
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"presets": ["env", "react","stage-2"],
|
||||||
|
"plugins": [
|
||||||
|
"ramda",
|
||||||
|
"lodash",
|
||||||
|
"react-hot-loader/babel",
|
||||||
|
["transform-runtime", {
|
||||||
|
"polyfill": false,
|
||||||
|
"regenerator": true
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
73
.eslintrc
Executable file
73
.eslintrc
Executable file
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"extends": "airbnb",
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
"plugins": [
|
||||||
|
"react",
|
||||||
|
"jsx-a11y",
|
||||||
|
"import",
|
||||||
|
"jest"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"quotes": 1,
|
||||||
|
"comma-dangle": 0,
|
||||||
|
"no-restricted-syntax": 1,
|
||||||
|
"new-cap": 1,
|
||||||
|
"no-continue": 1,
|
||||||
|
"no-underscore-dangle": 1,
|
||||||
|
"global-require": 1,
|
||||||
|
"react/no-multi-comp": 1,
|
||||||
|
"react/jsx-filename-extension": 0,
|
||||||
|
"camelcase": 1,
|
||||||
|
"import/no-unresolved": 1,
|
||||||
|
"import/prefer-default-export": 0,
|
||||||
|
"import/extensions": 1,
|
||||||
|
"no-return-assign": 1,
|
||||||
|
"max-len": 1,
|
||||||
|
"jsx-a11y/no-static-element-interactions": 0,
|
||||||
|
"jsx-a11y/click-events-have-key-events": 0,
|
||||||
|
"jsx-a11y/interactive-supports-focus": 0,
|
||||||
|
"arrow-parens": 0,
|
||||||
|
"jsx-a11y/no-autofocus": 0,
|
||||||
|
"react/jsx-closing-tag-location": 0,
|
||||||
|
"prefer-promise-reject-errors": 0,
|
||||||
|
"jsx-a11y/mouse-events-have-key-events": 0
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"document": false,
|
||||||
|
"window": false,
|
||||||
|
"HTMLInputElement": false,
|
||||||
|
"HTMLDivElement": false,
|
||||||
|
"Headers": false,
|
||||||
|
"FormData": false,
|
||||||
|
"WebSocket": true,
|
||||||
|
"Element": true,
|
||||||
|
"localStorage": true,
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"jest/globals": true
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"import/resolver": {
|
||||||
|
"webpack": {
|
||||||
|
"webpack.config.js": {
|
||||||
|
"resolve": {
|
||||||
|
"alias": {
|
||||||
|
"$components": "src/components",
|
||||||
|
"$containers": "src/containers",
|
||||||
|
"$constants": "src/constants",
|
||||||
|
"$sprites": "src/sprites",
|
||||||
|
"$config": "src/config",
|
||||||
|
"$styles": "src/styles",
|
||||||
|
"$redux": "src/redux",
|
||||||
|
"$utils": "src/utils"
|
||||||
|
},
|
||||||
|
|
||||||
|
"extensions": [".js", ".jsx", ".scss"],
|
||||||
|
|
||||||
|
"modules": ["src", "node_modules"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
.flowconfig
Normal file
23
.flowconfig
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[options]
|
||||||
|
module.system.node.resolve_dirname=node_modules
|
||||||
|
module.system.node.resolve_dirname=src
|
||||||
|
module.name_mapper='^$redux/\([-a-zA-Z0-9$_/]+\)$' -> '<PROJECT_ROOT>/src/redux/\1'
|
||||||
|
module.name_mapper='^components\/\(.*\)$' ->'<PROJECT_ROOT>/src/components/\1'
|
||||||
|
module.name_mapper='^containers\/\(.*\)$' ->'<PROJECT_ROOT>/src/containers/\1'
|
||||||
|
module.name_mapper='^constants\/\(.*\)$' ->'<PROJECT_ROOT>/src/constants/\1'
|
||||||
|
module.name_mapper='^sprites\/\(.*\)$' ->'<PROJECT_ROOT>/src/sprites/\1'
|
||||||
|
module.name_mapper='^config\/\(.*\)$' ->'<PROJECT_ROOT>/src/config/\1'
|
||||||
|
module.name_mapper='^styles\/\(.*\)$' ->'<PROJECT_ROOT>/src/styles/\1'
|
||||||
|
module.name_mapper='^utils\/\(.*\)$' ->'<PROJECT_ROOT>/src/utils/\1'
|
||||||
|
|
||||||
|
[ignore]
|
||||||
|
.*/node_modules
|
||||||
|
.*/node_modules/styled-components/.*
|
||||||
|
|
||||||
|
[include]
|
||||||
|
public
|
||||||
|
../node_modules/
|
||||||
|
|
||||||
|
[libs]
|
||||||
|
flow-libs/
|
||||||
|
|
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/node_modules
|
||||||
|
/dist
|
||||||
|
/npm-debug.log
|
||||||
|
/.idea
|
||||||
|
/coverage
|
||||||
|
/coverage/*
|
||||||
|
/flow-coverage
|
||||||
|
/flow-coverage/*
|
||||||
|
.vscode
|
||||||
|
.DS_Store
|
||||||
|
yarn-error.log
|
||||||
|
.awcache
|
||||||
|
|
||||||
|
# Bundle
|
||||||
|
*.js.map
|
12973
package-lock.json
generated
Normal file
12973
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
69
package.json
Normal file
69
package.json
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
{
|
||||||
|
"name": "orchid_map",
|
||||||
|
"sideEffects": false,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "Beta Map",
|
||||||
|
"main": "./src/js/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "NODE_ENV=development webpack-dev-server --mode development --hot --open --inline --progress"
|
||||||
|
},
|
||||||
|
"author": "Grigory Chervoplyas",
|
||||||
|
"license": "ISC",
|
||||||
|
"keywords": [],
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.0.0-beta.54",
|
||||||
|
"@babel/preset-env": "^7.0.0-beta.54",
|
||||||
|
"babel-core": "^6.26.0",
|
||||||
|
"babel-eslint": "^8.2.3",
|
||||||
|
"babel-loader": "^7.1.4",
|
||||||
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
|
"babel-preset-env": "^1.6.1",
|
||||||
|
"babel-preset-react": "^6.24.1",
|
||||||
|
"babel-preset-stage-2": "^6.24.1",
|
||||||
|
"css-loader": "^0.28.11",
|
||||||
|
"eslint": "^4.19.1",
|
||||||
|
"eslint-config-airbnb": "^16.1.0",
|
||||||
|
"eslint-import-resolver-babel-module": "^4.0.0",
|
||||||
|
"eslint-import-resolver-webpack": "^0.9.0",
|
||||||
|
"eslint-loader": "^2.0.0",
|
||||||
|
"eslint-plugin-babel": "^5.0.0",
|
||||||
|
"eslint-plugin-flowtype": "^2.46.2",
|
||||||
|
"eslint-plugin-import": "^2.11.0",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.0.3",
|
||||||
|
"eslint-plugin-react": "^7.7.0",
|
||||||
|
"file-loader": "^1.1.11",
|
||||||
|
"flow-bin": "^0.73.0",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"identity-obj-proxy": "^3.0.0",
|
||||||
|
"style-loader": "^0.21.0",
|
||||||
|
"webpack": "^4.6.0",
|
||||||
|
"webpack-cli": "^2.0.15",
|
||||||
|
"webpack-dev-server": "^3.1.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.18.0",
|
||||||
|
"babel-runtime": "^6.26.0",
|
||||||
|
"clean-webpack-plugin": "^0.1.9",
|
||||||
|
"history": "^4.7.2",
|
||||||
|
"leaflet": "^1.3.3",
|
||||||
|
"react": "^16.3.2",
|
||||||
|
"react-dom": "^16.3.2",
|
||||||
|
"react-hot-loader": "^4.1.1",
|
||||||
|
"regenerator-runtime": "^0.11.1",
|
||||||
|
"scrypt": "^6.0.3",
|
||||||
|
"styled-components": "^3.2.6",
|
||||||
|
"styled-theming": "^2.2.0",
|
||||||
|
"webpack-git-hash": "^1.0.2"
|
||||||
|
},
|
||||||
|
"flow-coverage-report": {
|
||||||
|
"includeGlob": [
|
||||||
|
"src/**/*.js",
|
||||||
|
"src/**/*.jsx"
|
||||||
|
],
|
||||||
|
"type": [
|
||||||
|
"text",
|
||||||
|
"html",
|
||||||
|
"json"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
12
src/containers/App.jsx
Normal file
12
src/containers/App.jsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Map } from "$containers/Map";
|
||||||
|
|
||||||
|
export class App extends React.Component {
|
||||||
|
render(){
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
29
src/index.js
Normal file
29
src/index.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
import { App } from '$containers/App';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
|
import { ConnectedRouter } from 'react-router-redux';
|
||||||
|
import { PersistGate } from 'redux-persist/integration/react';
|
||||||
|
|
||||||
|
// import { configs } from '$constants/moment';
|
||||||
|
import configureStore, { history } from '$redux/store';
|
||||||
|
|
||||||
|
const { store, persistor } = configureStore();
|
||||||
|
|
||||||
|
// import './js/common';
|
||||||
|
// import './js/script';
|
||||||
|
import './css/style.css';
|
||||||
|
|
||||||
|
export const Index = () => (
|
||||||
|
<Provider store={store}>
|
||||||
|
<PersistGate loading={null} persistor={persistor}>
|
||||||
|
<ConnectedRouter history={history}>
|
||||||
|
<App />
|
||||||
|
</ConnectedRouter>
|
||||||
|
</PersistGate>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
|
||||||
|
ReactDOM.render(<Index />, document.getElementById('index'));
|
82
src/parts/map.js
Normal file
82
src/parts/map.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import L from "leaflet";
|
||||||
|
|
||||||
|
import 'leaflet-editable';
|
||||||
|
import 'leaflet.markercluster';
|
||||||
|
import 'leaflet.markercluster.webpack';
|
||||||
|
import 'leaflet-geometryutil';
|
||||||
|
|
||||||
|
import { mapStyles } from "$constants/mapStyles";
|
||||||
|
|
||||||
|
import { stickers } from "$constants/stickers";
|
||||||
|
|
||||||
|
import { updateMarks } from "$utils/updater";
|
||||||
|
import { bindPolyEvents, preparePoly } from "$utils/poly";
|
||||||
|
|
||||||
|
// В этой штуке мы храним точки и выноски, их связки и всё такое
|
||||||
|
const point_array = {
|
||||||
|
points: L.layerGroup(),
|
||||||
|
vectors: L.layerGroup(),
|
||||||
|
handles: L.layerGroup(),
|
||||||
|
pairs: {},
|
||||||
|
point_to_id: {},
|
||||||
|
id_to_point: {},
|
||||||
|
savedata: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const points = L.layerGroup();
|
||||||
|
|
||||||
|
let mode = "none";
|
||||||
|
let current_map_style = 'default';
|
||||||
|
|
||||||
|
// Интересные места;
|
||||||
|
// const places_layer;
|
||||||
|
|
||||||
|
export const map = L.map('map', {
|
||||||
|
editable: true,
|
||||||
|
layers: [ points, point_array.points, point_array.vectors, stickers.layers ]
|
||||||
|
}).setView([55.0153275, 82.9071235], 13);
|
||||||
|
|
||||||
|
map.editTools.skipMiddleMarkers = true;
|
||||||
|
|
||||||
|
// Слой с интересными местами
|
||||||
|
// const places_layer = L.markerClusterGroup({maxClusterRadius: 20});
|
||||||
|
|
||||||
|
// const poly = preparePoly(map); // начинаем новую полилинию
|
||||||
|
|
||||||
|
// const updateOverlays = () => updateMarks({ map, poly, km_marks });
|
||||||
|
const updateOverlays = e => console.log();
|
||||||
|
|
||||||
|
const prepareMapLayer = provider => {
|
||||||
|
L.tileLayer(provider, {
|
||||||
|
attribution: 'Независимое Велосообщество',
|
||||||
|
maxNativeZoom: 18,
|
||||||
|
maxZoom: 18,
|
||||||
|
//minZoom: 11
|
||||||
|
}).addTo(map);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindMapEvents = () => {
|
||||||
|
|
||||||
|
// при масштабировании карты масштабировать стрелки
|
||||||
|
// map.on('zoom', function (e) {
|
||||||
|
// $('.arr_mark > div').css('transform', 'scale(' + (map.getZoom()/13) + ')');
|
||||||
|
// });
|
||||||
|
|
||||||
|
map.on('click', updateOverlays);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setMode = variant => {
|
||||||
|
mode = variant;
|
||||||
|
};
|
||||||
|
|
||||||
|
// prepareMap();
|
||||||
|
|
||||||
|
export const prepareMap = () => {
|
||||||
|
// Эта функция создаёт саму карту и наносит на неё маршруты в самом начале работы
|
||||||
|
// создаём объект с картой
|
||||||
|
map.doubleClickZoom.disable();
|
||||||
|
prepareMapLayer(mapStyles[current_map_style]);
|
||||||
|
|
||||||
|
bindMapEvents();
|
||||||
|
// bindPolyEvents({ poly, map, updateOverlays, clearKmMarks });
|
||||||
|
};
|
228
src/parts/poly.js
Normal file
228
src/parts/poly.js
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
import L from "leaflet";
|
||||||
|
import { map } from "$utils/map";
|
||||||
|
import { findDistance, middle_latlng } from "../js/common";
|
||||||
|
|
||||||
|
let poly = null;
|
||||||
|
export const km_marks = L.layerGroup();
|
||||||
|
|
||||||
|
// const updateOverlays = () => updateMarks({ map, poly, km_marks });
|
||||||
|
|
||||||
|
const getRouteArray = poly => poly.toGeoJSON().geometry.coordinates;
|
||||||
|
|
||||||
|
|
||||||
|
export const writeReduxData = ({ e, updatePolyCoords }) => {
|
||||||
|
const route = getRouteArray(poly);
|
||||||
|
const latlngs = route.map(([lng, lat]) => ({lat, lng}));
|
||||||
|
|
||||||
|
updatePolyCoords({ latlngs });
|
||||||
|
};
|
||||||
|
|
||||||
|
const endMarker = ({ end_latlng, length }) => L.marker(
|
||||||
|
[end_latlng[1], end_latlng[0]],
|
||||||
|
{
|
||||||
|
icon: L.divIcon(
|
||||||
|
{
|
||||||
|
html: `${length} км`,
|
||||||
|
className: 'end_mark'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const startMarker = ({ start_latlng, map }) => L.marker(
|
||||||
|
[start_latlng[1], start_latlng[0]],
|
||||||
|
{
|
||||||
|
icon: L.divIcon({
|
||||||
|
html: `<div style="transform: scale(${(map.getZoom() / 13)});"><div class="arr_start"></div></div>`,
|
||||||
|
className: 'arr_mark'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const updateMarks = () => {
|
||||||
|
km_marks.clearLayers();
|
||||||
|
const route = getRouteArray(poly);
|
||||||
|
const latlngs = poly.getLatLngs();
|
||||||
|
let start_latlng;
|
||||||
|
let end_latlng;
|
||||||
|
let i;
|
||||||
|
let rotation;
|
||||||
|
let middle;
|
||||||
|
let distance;
|
||||||
|
|
||||||
|
if (route.length > 0) {
|
||||||
|
start_latlng = route[0];
|
||||||
|
end_latlng = route[route.length - 1];
|
||||||
|
km_marks.addLayer(startMarker({ start_latlng, map }));
|
||||||
|
if (route.length > 1) {
|
||||||
|
const segs = L.GeometryUtil.accumulatedLengths(poly);
|
||||||
|
const length = Math.round(segs[segs.length - 1] / 1000);
|
||||||
|
// end mark
|
||||||
|
km_marks.addLayer(endMarker({ end_latlng, length }));
|
||||||
|
|
||||||
|
//and also length to panel:
|
||||||
|
// $('#text_route_length').text(length + 'км');
|
||||||
|
|
||||||
|
for (i = 1; i < latlngs.length; i += 1) {
|
||||||
|
rotation = L.GeometryUtil.bearing(latlngs[i - 1], latlngs[i]);
|
||||||
|
middle = middle_latlng(latlngs[i], latlngs[i - 1]);
|
||||||
|
distance = findDistance(latlngs[i - 1].lat, latlngs[i - 1].lng, latlngs[i].lat, latlngs[i].lng);
|
||||||
|
|
||||||
|
if (distance > 1) {
|
||||||
|
km_marks.addLayer(L.marker([middle.lat, middle.lng], { icon: L.divIcon({ html: '<div style="transform: scale(' + (map.getZoom() / 13) + ');"><img src="misc/arr.png" style="transform: translateX(-4px) translateY(-4px) rotate(' + (270 + rotation) + 'deg);"></div>', className: 'arr_mark' }) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// $('#text_route_length').text('0 км');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// updatePolyCoords({ latlngs: route });
|
||||||
|
// local_store_data();
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearKmMarks = () => km_marks.clearLayers();
|
||||||
|
|
||||||
|
const insertVertex = ({ e, updatePolyCoords }) => {
|
||||||
|
// Добавляет редактирующую ручку по щелчку
|
||||||
|
// если щелчок по кривой, а не по ручке И если ломаная в режиме редактирования. Иначе - перейти к редактированию
|
||||||
|
if (e.originalEvent.target.tagName === 'path' && poly.editor._enabled) {
|
||||||
|
// если щелкнуть по кривой во время редактирования, editable не должно рисовать новую точку
|
||||||
|
if (e.type === 'editable:drawing:click') e.cancel();
|
||||||
|
|
||||||
|
let latlngs = poly.getLatLngs(); // набор точек ломанной
|
||||||
|
let best = 10000;
|
||||||
|
let pos = []; // переменные для определения принадлежности точки отрезку на ломанной
|
||||||
|
|
||||||
|
for(let i=0; i<latlngs.length-1; i++) {
|
||||||
|
// Дальше определяем, лежит ли точка на отрезке ломаной перебором этих отрезков
|
||||||
|
const x = e.latlng['lat'];
|
||||||
|
const x1 = latlngs[i]['lat'];
|
||||||
|
const x2 = latlngs[i+1]['lat'];
|
||||||
|
const y = e.latlng['lng'];
|
||||||
|
const y1 = latlngs[i]['lng'];
|
||||||
|
const y2 = latlngs[i+1]['lng'];
|
||||||
|
|
||||||
|
// эта странная конструкция определяет, лежит ли вообще точка между двумя соседями на отрезке
|
||||||
|
if ((
|
||||||
|
(x1<x2 && (x>x1 && x<x2))
|
||||||
|
||
|
||||||
|
(x1>x2 && (x<x1 && x>x2))
|
||||||
|
||
|
||||||
|
(x1 === x2 && Math.abs(x-x1)>0.001)
|
||||||
|
) && (
|
||||||
|
(y1<y2 && (y>y1 && y<y2))
|
||||||
|
||
|
||||||
|
(y1>y2 && (y<y1 && y>y2))
|
||||||
|
||
|
||||||
|
(y1 === y2 && Math.abs(y-y1)>0.001)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// если да, то проверяем, далеко ли точка от самого отрезка между двумя точками
|
||||||
|
let dx1 = x2 - x1;
|
||||||
|
let dy1 = y2 - y1;
|
||||||
|
let dx = x - x1;
|
||||||
|
let dy = y - y1;
|
||||||
|
let result = Math.abs((dx1 * dy) - (dx * dy1));
|
||||||
|
if (result < best) {
|
||||||
|
// это - не очень-то точная функция. Но по клику она определяет, по какому отрезку мы кликнули
|
||||||
|
best = result;
|
||||||
|
pos = [i, i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// если точка найдена, добавляем её в отрезок
|
||||||
|
if (pos.length>1) {
|
||||||
|
poly.editor.disable();
|
||||||
|
latlngs.splice(pos[1],0,e.latlng);
|
||||||
|
poly.setLatLngs(latlngs);
|
||||||
|
poly.editor.initVertexMarkers();
|
||||||
|
poly.editor.enable();
|
||||||
|
poly.editor.continueForward();
|
||||||
|
|
||||||
|
writeReduxData({ e, updatePolyCoords });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Рисование! Очистим буфер отмен :-)
|
||||||
|
// redoBuffer = [];
|
||||||
|
// если ломаная не в режиме редактирования или если мы, всё-таки, кликнули по ручке, просто активируем редактор
|
||||||
|
// route_state('active');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const bindPolyEvents = ({ updatePolyCoords }) => {
|
||||||
|
// Если на карте что-то меняется, пересчитать километражи
|
||||||
|
map.editTools.addEventListener('editable:drawing:mouseup', updateMarks);
|
||||||
|
map.editTools.addEventListener('editable:vertex:dragend', updateMarks);
|
||||||
|
|
||||||
|
map.editTools.addEventListener('editable:vertex:dragend', e => writeReduxData({ e, updatePolyCoords }));
|
||||||
|
map.editTools.addEventListener('editable:vertex:new', e => writeReduxData({ e, updatePolyCoords }));
|
||||||
|
map.editTools.addEventListener('editable:vertex:deleted', e => writeReduxData({ e, updatePolyCoords }));
|
||||||
|
|
||||||
|
// Продолжить рисование после удаления точки
|
||||||
|
map.editTools.addEventListener('editable:vertex:deleted', e => {
|
||||||
|
poly.editor.continueForward();
|
||||||
|
updateMarks();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Добавлять точек в полилинию по щелчку
|
||||||
|
map.editTools.addEventListener('editable:drawing:click', e => insertVertex({ e, updatePolyCoords }));
|
||||||
|
map.editTools.addEventListener('editable:drawing:clicked', () => updateMarks({ updatePolyCoords }));
|
||||||
|
|
||||||
|
// Это для точек. При перетаскивании конца указателя тащим точку
|
||||||
|
// map.editTools.addEventListener('editable:vertex:drag', on_vertex_drag);
|
||||||
|
|
||||||
|
// при перетаскивании ручек убирать все отметки километров
|
||||||
|
map.editTools.addEventListener('editable:vertex:dragstart', clearKmMarks);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updatePoly = (latlngs) => {
|
||||||
|
// const route = latlngs.map(([lat, lng]) => new L.latLng(lat, lng));
|
||||||
|
if (!latlngs || latlngs.length < 2) return;
|
||||||
|
|
||||||
|
poly.setLatLngs(createLatLngs(latlngs));
|
||||||
|
poly.addTo(map);
|
||||||
|
poly.setStyle({ color: '#ff3333', weight: '5' });
|
||||||
|
poly.editor.options.skipMiddleMarkers = true;
|
||||||
|
poly.editor.disable().enable();
|
||||||
|
poly.editor.continueForward();
|
||||||
|
//
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createLatLngs = latlngs => latlngs.map(({ lat, lng }) => new L.LatLng(lat, lng));
|
||||||
|
|
||||||
|
const createPoly = () => {
|
||||||
|
const result = map.editTools.startPolyline();
|
||||||
|
|
||||||
|
result.editor.enable();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const restorePoly = latlngs => {
|
||||||
|
const result = L.polyline(createLatLngs(latlngs), {color: 'red'}).addTo(map);
|
||||||
|
|
||||||
|
result.enableEdit().continueForward();
|
||||||
|
result.editor.options.skipMiddleMarkers = true;
|
||||||
|
|
||||||
|
result.editor.reset();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const preparePoly = ({ updatePolyCoords, latlngs }) => {
|
||||||
|
map.addLayer(km_marks);
|
||||||
|
|
||||||
|
poly = (latlngs && latlngs.length)
|
||||||
|
? restorePoly(latlngs)
|
||||||
|
: createPoly();
|
||||||
|
|
||||||
|
updateMarks();
|
||||||
|
|
||||||
|
poly.setStyle({ color: '#ff3333', weight: '5' });
|
||||||
|
|
||||||
|
bindPolyEvents({ updatePolyCoords });
|
||||||
|
|
||||||
|
return poly;
|
||||||
|
};
|
||||||
|
|
124
webpack.config.js
Normal file
124
webpack.config.js
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
// import webpack from 'webpack';
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||||
|
// const FlowWebpackPlugin = require('flow-webpack-plugin');
|
||||||
|
const { version } = require('./package.json');
|
||||||
|
|
||||||
|
const WebpackGitHash = require('webpack-git-hash');
|
||||||
|
const { join } = require('path');
|
||||||
|
|
||||||
|
|
||||||
|
/* Plugins */
|
||||||
|
|
||||||
|
const htmlPlugin = new HtmlWebPackPlugin({
|
||||||
|
template: './src/index.html',
|
||||||
|
filename: './index.html',
|
||||||
|
title: 'Ether Corners',
|
||||||
|
hash: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const isDevelopment = process.env.NODE_ENV !== 'production';
|
||||||
|
const devtool = isDevelopment ? 'cheap-module-eval-source-map' : 'source-map';
|
||||||
|
|
||||||
|
// const flowPlugin = new FlowWebpackPlugin();
|
||||||
|
|
||||||
|
const gitPlugin = new WebpackGitHash();
|
||||||
|
|
||||||
|
|
||||||
|
/* Resolve */
|
||||||
|
|
||||||
|
const resolve = {
|
||||||
|
alias: {
|
||||||
|
$components: join(__dirname, 'src/components'),
|
||||||
|
$containers: join(__dirname, 'src/containers'),
|
||||||
|
$constants: join(__dirname, 'src/constants'),
|
||||||
|
$sprites: join(__dirname, 'src/sprites'),
|
||||||
|
$config: join(__dirname, 'src/config'),
|
||||||
|
$styles: join(__dirname, 'src/styles'),
|
||||||
|
$redux: join(__dirname, 'src/redux'),
|
||||||
|
$utils: join(__dirname, 'src/utils'),
|
||||||
|
},
|
||||||
|
|
||||||
|
extensions: ['*', '.js', '.jsx', '.json']
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Configuration */
|
||||||
|
|
||||||
|
module.exports = () => {
|
||||||
|
/* Export */
|
||||||
|
const plugins = [
|
||||||
|
htmlPlugin,
|
||||||
|
// flowPlugin,
|
||||||
|
gitPlugin,
|
||||||
|
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
use: [
|
||||||
|
{ loader: 'style-loader' },
|
||||||
|
{ loader: 'css-loader' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(eot|ttf|woff|woff2|otf)$/,
|
||||||
|
use: {
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
name: '[name].[ext]',
|
||||||
|
outputPath: 'fonts/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png)$/,
|
||||||
|
use: {
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
devtool,
|
||||||
|
resolve,
|
||||||
|
plugins,
|
||||||
|
entry: {
|
||||||
|
// loader: './src/loader.js',
|
||||||
|
app: './src/index.js',
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: '[name].bundle.[githash].js',
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
splitChunks: {
|
||||||
|
cacheGroups: {
|
||||||
|
commons: {
|
||||||
|
name: 'commons',
|
||||||
|
chunks: 'initial',
|
||||||
|
minChunks: 2,
|
||||||
|
minSize: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
historyApiFallback: true,
|
||||||
|
port: 8000,
|
||||||
|
contentBase: 'dist',
|
||||||
|
publicPath: '/',
|
||||||
|
hot: true,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue