added arrows

This commit is contained in:
muerwre 2019-02-26 17:18:45 +07:00
parent dfb4d3b98f
commit 968c871c11
6 changed files with 83 additions and 7 deletions

View file

@ -38,6 +38,10 @@ export const Fills = () => (
> >
<path d="m 2.625,3.375 h 7.5 L 10.28125,1.609375 13.5,4.25 10.484375,6.921875 10.171875,5.15625 2.625,5.125 Z" fill="#ff3344" fillRule="evenodd" /> <path d="m 2.625,3.375 h 7.5 L 10.28125,1.609375 13.5,4.25 10.484375,6.921875 10.171875,5.15625 2.625,5.125 Z" fill="#ff3344" fillRule="evenodd" />
</marker> </marker>
<g id="path-arrow">
<path d="m 2.625,3.375 h 7.5 L 10.28125,1.609375 13.5,4.25 10.484375,6.921875 10.171875,5.15625 2.625,5.125 Z" fill="#ff3344" fillRule="evenodd" />
</g>
</defs> </defs>
<image xlinkHref={require('$sprites/stickers/stickers-base.svg')} width={0} height={0} /> <image xlinkHref={require('$sprites/stickers/stickers-base.svg')} width={0} height={0} />
</svg> </svg>

View file

@ -595,4 +595,6 @@ export const InteractivePoly = Component;
editorenable editorenable
distancechange distancechange
latlngschange
*/ */

View file

@ -1,11 +1,14 @@
import { Map, LayerGroup, LatLng } from 'leaflet'; import { Map, LayerGroup, LatLng, LatLngLiteral, LeafletEventHandlerFn, marker, divIcon, Marker } from 'leaflet';
import { EditablePolyline } from '$utils/EditablePolyline'; import { EditablePolyline } from '$utils/EditablePolyline';
import { simplify } from '$utils/simplify'; import { simplify } from '$utils/simplify';
import { CLIENT } from '$config/frontend'; import { CLIENT } from '$config/frontend';
import { editor, Editor } from "$modules/Editor"; import { editor, Editor } from "$modules/Editor";
import { ILatLng } from "$modules/Stickers"; import { ILatLng } from "$modules/Stickers";
import { InteractivePoly } from "$modules/InteractivePoly"; import { InteractivePoly } from "$modules/InteractivePoly";
import { clusterIcon } from "$utils/clusterIcon";
import { MarkerClusterGroup } from 'leaflet.markercluster/dist/leaflet.markercluster-src.js';
import { angleBetweenPoints, dist2, distToSegment, middleCoord } from "$utils/geom";
import { arrowClusterIcon, createArrow } from "$utils/arrow";
interface Props { interface Props {
map: Map; map: Map;
@ -29,7 +32,8 @@ export class Poly {
}) })
.on('distancechange', this.onDistanceUpdate) .on('distancechange', this.onDistanceUpdate)
.on('allvertexhide', this.onVertexHide) .on('allvertexhide', this.onVertexHide)
.on('allvertexshow', this.onVertexShow); .on('allvertexshow', this.onVertexShow)
.on('latlngschange', this.updateArrows);
this.poly.addTo(map); this.poly.addTo(map);
this.editor = editor; this.editor = editor;
@ -41,7 +45,7 @@ export class Poly {
this.triggerOnChange = triggerOnChange; this.triggerOnChange = triggerOnChange;
this.lockMapClicks = lockMapClicks; this.lockMapClicks = lockMapClicks;
this.arrows.addTo(map); this.arrowLayer.addTo(map);
} }
onDistanceUpdate = (event) => { onDistanceUpdate = (event) => {
@ -52,6 +56,32 @@ export class Poly {
onVertexHide = (): void => this.editor.setMarkersShown(false); onVertexHide = (): void => this.editor.setMarkersShown(false);
onVertexShow = (): void => this.editor.setMarkersShown(true); onVertexShow = (): void => this.editor.setMarkersShown(true);
updateArrows = event => {
const { latlngs } = event;
this.arrowLayer.clearLayers();
if (latlngs.length === 0) return;
const midpoints = latlngs.reduce((res, latlng, i) => (
latlngs[i + 1] && dist2(latlngs[i], latlngs[i + 1]) > 0.00005
? [
...res,
{
latlng: middleCoord(latlngs[i], latlngs[i + 1]),
angle: angleBetweenPoints(
this.map.latLngToContainerPoint(latlngs[i]),
this.map.latLngToContainerPoint(latlngs[i + 1])
),
}
]
: res
), []);
midpoints.forEach(({ latlng, angle }) => (
this.arrowLayer.addLayer(createArrow(latlng, angle))
));
};
// setModeOnDrawing = (): void => { // setModeOnDrawing = (): void => {
// if (this.editor.getMode() !== MODES.POLY) this.editor.setMode(MODES.POLY); // if (this.editor.getMode() !== MODES.POLY) this.editor.setMode(MODES.POLY);
// }; // };
@ -133,7 +163,15 @@ export class Poly {
} }
poly: EditablePolyline; poly: EditablePolyline;
arrows: LayerGroup = new LayerGroup(); arrowLayer: MarkerClusterGroup = new MarkerClusterGroup({
spiderfyOnMaxZoom: false,
showCoverageOnHover: false,
zoomToBoundsOnClick: false,
animate: false,
maxClusterRadius: 100,
// disableClusteringAtZoom: 13,
iconCreateFunction: arrowClusterIcon,
});
editor: Props['editor']; editor: Props['editor'];
map: Props['map']; map: Props['map'];

View file

@ -91,6 +91,14 @@
} }
} }
.leaflet-arrow {
position: absolute;
left: -14px;
top: -14px;
width: 40px;
height: 40px;
}
.touch-hinter-poly { .touch-hinter-poly {
stroke: rgba(255, 50, 0, 0.1); stroke: rgba(255, 50, 0, 0.1);
cursor: grab; cursor: grab;

22
src/utils/arrow.ts Normal file
View file

@ -0,0 +1,22 @@
import { divIcon, LatLngLiteral, Marker, marker, DivIcon } from "leaflet";
export const createArrow = (latlng: LatLngLiteral, angle: number): Marker => marker(latlng, {
draggable: false,
interactive: false,
icon: divIcon({
html: `
<div class="leaflet-arrow" style="transform: rotate(${angle}deg);">
<svg width="40" height="40" preserveAspectRatio="xMidYMid">
<use xlink:href="#path-arrow" transform="scale(2)"/>
</svg>
</div>
`,
className: 'leaflet-arrow-icon',
iconSize: [11, 11],
iconAnchor: [6, 6]
})
});
export const arrowClusterIcon = (): DivIcon => divIcon({
html: `<div class="leaflet-arrow-cluster"></div>`
});

View file

@ -1,4 +1,4 @@
import { LatLng, LatLngLiteral } from "leaflet"; import { LatLng, LatLngLiteral, Point } from "leaflet";
interface ILatLng { interface ILatLng {
lat: number, lat: number,
@ -58,7 +58,7 @@ export const pointInArea = (A: LatLng, B: LatLng, C: LatLng, radius: number = 0.
); );
const dist2 = (A: LatLngLiteral, B: LatLngLiteral): number => (((A.lat - B.lat) ** 2) + ((A.lng - B.lng) ** 2)); export const dist2 = (A: LatLngLiteral, B: LatLngLiteral): number => (((A.lat - B.lat) ** 2) + ((A.lng - B.lng) ** 2));
const distToSegmentSquared = (A: LatLng, B: LatLng, C: LatLng): number => { const distToSegmentSquared = (A: LatLng, B: LatLng, C: LatLng): number => {
const l2 = dist2(A, B); const l2 = dist2(A, B);
@ -83,3 +83,5 @@ const distToSegmentSquared = (A: LatLng, B: LatLng, C: LatLng): number => {
export const distToSegment = (A: LatLng, B: LatLng, C: LatLng): number => Math.sqrt(distToSegmentSquared(A, B, C)); export const distToSegment = (A: LatLng, B: LatLng, C: LatLng): number => Math.sqrt(distToSegmentSquared(A, B, C));
// if C between A and B // if C between A and B
export const pointBetweenPoints = (A: LatLng, B: LatLng, C: LatLng): boolean => (distToSegment(A, B, C) < 0.01); export const pointBetweenPoints = (A: LatLng, B: LatLng, C: LatLng): boolean => (distToSegment(A, B, C) < 0.01);
export const angleBetweenPoints = (A: Point, B: Point): number => parseFloat(((Math.atan2(B.y - A.y, B.x - A.x))* 180 / Math.PI).toFixed(6));