diff --git a/src/components/Fills.tsx b/src/components/Fills.tsx
index d025755..70b511f 100644
--- a/src/components/Fills.tsx
+++ b/src/components/Fills.tsx
@@ -38,6 +38,10 @@ export const Fills = () => (
>
+
+
+
+
diff --git a/src/modules/InteractivePoly.ts b/src/modules/InteractivePoly.ts
index 04dbc7c..539dd74 100644
--- a/src/modules/InteractivePoly.ts
+++ b/src/modules/InteractivePoly.ts
@@ -595,4 +595,6 @@ export const InteractivePoly = Component;
editorenable
distancechange
+
+ latlngschange
*/
diff --git a/src/modules/Poly.ts b/src/modules/Poly.ts
index 4008be4..f7046f4 100644
--- a/src/modules/Poly.ts
+++ b/src/modules/Poly.ts
@@ -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 { simplify } from '$utils/simplify';
import { CLIENT } from '$config/frontend';
import { editor, Editor } from "$modules/Editor";
import { ILatLng } from "$modules/Stickers";
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 {
map: Map;
@@ -29,7 +32,8 @@ export class Poly {
})
.on('distancechange', this.onDistanceUpdate)
.on('allvertexhide', this.onVertexHide)
- .on('allvertexshow', this.onVertexShow);
+ .on('allvertexshow', this.onVertexShow)
+ .on('latlngschange', this.updateArrows);
this.poly.addTo(map);
this.editor = editor;
@@ -41,7 +45,7 @@ export class Poly {
this.triggerOnChange = triggerOnChange;
this.lockMapClicks = lockMapClicks;
- this.arrows.addTo(map);
+ this.arrowLayer.addTo(map);
}
onDistanceUpdate = (event) => {
@@ -52,6 +56,32 @@ export class Poly {
onVertexHide = (): void => this.editor.setMarkersShown(false);
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 => {
// if (this.editor.getMode() !== MODES.POLY) this.editor.setMode(MODES.POLY);
// };
@@ -133,7 +163,15 @@ export class Poly {
}
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'];
map: Props['map'];
diff --git a/src/styles/map.less b/src/styles/map.less
index ea2f153..b59f739 100644
--- a/src/styles/map.less
+++ b/src/styles/map.less
@@ -91,6 +91,14 @@
}
}
+.leaflet-arrow {
+ position: absolute;
+ left: -14px;
+ top: -14px;
+ width: 40px;
+ height: 40px;
+}
+
.touch-hinter-poly {
stroke: rgba(255, 50, 0, 0.1);
cursor: grab;
diff --git a/src/utils/arrow.ts b/src/utils/arrow.ts
new file mode 100644
index 0000000..9b20a14
--- /dev/null
+++ b/src/utils/arrow.ts
@@ -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: `
+
+
+
+ `,
+ className: 'leaflet-arrow-icon',
+ iconSize: [11, 11],
+ iconAnchor: [6, 6]
+ })
+});
+
+export const arrowClusterIcon = (): DivIcon => divIcon({
+ html: ``
+});
diff --git a/src/utils/geom.ts b/src/utils/geom.ts
index 7fb814e..103ea21 100644
--- a/src/utils/geom.ts
+++ b/src/utils/geom.ts
@@ -1,4 +1,4 @@
-import { LatLng, LatLngLiteral } from "leaflet";
+import { LatLng, LatLngLiteral, Point } from "leaflet";
interface ILatLng {
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 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));
// if C between A and B
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));