From d9f83425f6b9f835a4fac061d4ea7be4eb9a6dbb Mon Sep 17 00:00:00 2001 From: muerwre Date: Mon, 27 Aug 2018 15:28:13 +0700 Subject: [PATCH] made poly arrows via svg markers --- src/components/Fills.jsx | 30 ++++++++++++++++++--- src/components/panels/EditorPanel.jsx | 10 +++---- src/modules/Poly.js | 39 +++++++++++++++++++++++++-- src/utils/geom.js | 29 ++++++++++++++++++++ 4 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 src/utils/geom.js diff --git a/src/components/Fills.jsx b/src/components/Fills.jsx index 084c79b..80d9189 100644 --- a/src/components/Fills.jsx +++ b/src/components/Fills.jsx @@ -3,17 +3,41 @@ import React from 'react'; export const Fills = () => ( + - - + + + + + + + + + -) +); diff --git a/src/components/panels/EditorPanel.jsx b/src/components/panels/EditorPanel.jsx index 624fefc..14a101f 100644 --- a/src/components/panels/EditorPanel.jsx +++ b/src/components/panels/EditorPanel.jsx @@ -51,11 +51,11 @@ export class EditorPanel extends React.PureComponent {
- {totalDistance} км - - { - {toHours(estimateTime)} - } + {totalDistance} км + + { + {toHours(estimateTime)} + }
diff --git a/src/modules/Poly.js b/src/modules/Poly.js index d5574bc..f5f987e 100644 --- a/src/modules/Poly.js +++ b/src/modules/Poly.js @@ -1,8 +1,13 @@ import L from 'leaflet'; import 'leaflet-geometryutil'; import { simplify } from '$utils/simplify'; +import { findDistance, middleCoord } from '$utils/geom'; -const polyStyle = { color: 'url(#activePathGradient)', weight: '6' }; +const polyStyle = { + color: 'url(#activePathGradient)', + weight: '6', + markerMid: 'url(#arrow)' +}; // const polyStyle = { color: '#ff3344', weight: '5' }; export class Poly { @@ -10,24 +15,54 @@ export class Poly { 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(); + + this.arrows = new L.LayerGroup().addTo(map); } + drawArrows = () => { + this.arrows.clearLayers(); + + const { latlngs } = this; + + if (!latlngs || latlngs.length <= 1) return; + + latlngs.map((latlng, i) => { + if (i === 0) return; + const mid = middleCoord(latlngs[i], latlngs[i - 1]); + const dist = findDistance(latlngs[i - 1].lat, latlngs[i - 1].lng, latlngs[i].lat, latlngs[i].lng); + + if (dist > 1.5) { + const slide = new L.Polyline( + [ + latlngs[i - 1], + [mid.lat, mid.lng] + ], + { color: 'none', weight: '5' } + ).addTo(this.arrows); + slide._path.setAttribute('marker-end', 'url(#long-arrow)'); + } + }); + }; + updateMarks = () => { 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; + const kilometers = (meters && meters.toFixed(1)) || 0; this.setTotalDist(kilometers); this.routerMoveStart(); + this.drawArrows(); }; bindEvents = () => { diff --git a/src/utils/geom.js b/src/utils/geom.js new file mode 100644 index 0000000..9fb48b6 --- /dev/null +++ b/src/utils/geom.js @@ -0,0 +1,29 @@ +export const middleCoord = (l1, l2) => ({ + lat: (l2.lat + ((l1.lat - l2.lat) / 2)), + lng: (l2.lng + ((l1.lng - l2.lng) / 2)) +}); + +export const deg2rad = deg => deg * Math.PI / 180; + +export const findDistance = (t1, n1, t2, n2) => { + // convert coordinates to radians + const lat1 = deg2rad(t1); + const lon1 = deg2rad(n1); + const lat2 = deg2rad(t2); + const lon2 = deg2rad(n2); + + // find the differences between the coordinates + const dlat = lat2 - lat1; + const dlon = lon2 - lon1; + + // here's the heavy lifting + const a = (Math.sin(dlat / 2) ** 2) + + (Math.cos(lat1) * Math.cos(lat2) * (Math.sin(dlon / 2) ** 2)); + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // great circle distance in radians + // const dm = c * 3961; // great circle distance in miles + const dk = c * 6373; // great circle distance in km + + // round the results down to the nearest 1/1000 + // const mi = round(dm); + return (Math.round(dk * 1000) / 1000); +};