mirror of
https://github.com/muerwre/orchidmap-front.git
synced 2025-04-25 02:56:41 +07:00
drawing arrows
This commit is contained in:
parent
f8d16d150a
commit
3f2e2ba856
7 changed files with 65 additions and 14 deletions
|
@ -76,7 +76,6 @@ class Component extends React.Component<IMapListDialogProps, IMapListDialogState
|
|||
});
|
||||
|
||||
stopEditing = (): void => {
|
||||
console.log('stop it!');
|
||||
this.setState({ editor_target: null });
|
||||
};
|
||||
|
||||
|
|
|
@ -14,10 +14,6 @@
|
|||
todo polyline editing only in manual mode (or by click)
|
||||
todo selecting logo on crop
|
||||
|
||||
done public maps
|
||||
done editing map on map list
|
||||
done setting map public on map list
|
||||
|
||||
todo network operations notify
|
||||
done delayed notify (delay(2000).then(showLoadingMsg))
|
||||
todo network error notifications
|
||||
|
@ -28,6 +24,10 @@
|
|||
|
||||
## DONE
|
||||
|
||||
done public maps
|
||||
done editing map on map list
|
||||
done setting map public on map list
|
||||
|
||||
done routing spinner
|
||||
done maybe: stickers clusterization?
|
||||
done moving out the screen makes stickers editable again
|
||||
|
|
|
@ -41,6 +41,7 @@ import { MODES } from '$constants/modes';
|
|||
import { DEFAULT_USER } from '$constants/auth';
|
||||
import { TIPS } from '$constants/tips';
|
||||
import {
|
||||
composeArrows,
|
||||
composeImages,
|
||||
composePoly, composeStickers, downloadCanvas,
|
||||
fetchImages,
|
||||
|
@ -362,6 +363,7 @@ function* getRenderData() {
|
|||
|
||||
yield composeImages({ geometry, images, ctx });
|
||||
yield composePoly({ points, ctx });
|
||||
yield composeArrows({ points, ctx });
|
||||
yield composeStickers({ stickers, ctx });
|
||||
|
||||
yield put(setRenderer({ info: 'Готово', progress: 1 }));
|
||||
|
|
5
src/sprites/arrow.svg
Normal file
5
src/sprites/arrow.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg width="48" height="48" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="path-arrow" transform="scale(2) translate(5 -2)">
|
||||
<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>
|
||||
</svg>
|
After Width: | Height: | Size: 297 B |
|
@ -1,5 +1,8 @@
|
|||
import { divIcon, LatLngLiteral, Marker, marker, DivIcon } from "leaflet";
|
||||
|
||||
const arrow_image = require('$sprites/arrow.svg');
|
||||
|
||||
// <use xlink:href="#path-arrow" transform="scale(2) translate(5 -2)"/>
|
||||
export const createArrow = (latlng: LatLngLiteral, angle: number): Marker => marker(latlng, {
|
||||
draggable: false,
|
||||
interactive: false,
|
||||
|
@ -7,7 +10,7 @@ export const createArrow = (latlng: LatLngLiteral, angle: number): Marker => mar
|
|||
html: `
|
||||
<div class="leaflet-arrow" style="transform: rotate(${angle}deg);">
|
||||
<svg width="48" height="48" preserveAspectRatio="xMidYMid">
|
||||
<use xlink:href="#path-arrow" transform="scale(2) translate(5 -2)"/>
|
||||
<image xlink:href="${arrow_image}" x="0" y="0" width="48" height="48"/>
|
||||
</svg>
|
||||
</div>
|
||||
`,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { LatLng, LatLngLiteral, Point, PointExpression } from "leaflet";
|
||||
import { LatLng, LatLngLiteral, point, Point, PointExpression } from "leaflet";
|
||||
|
||||
interface ILatLng {
|
||||
lat: number,
|
||||
|
@ -10,9 +10,18 @@ export const middleCoord = (l1: ILatLng, l2: ILatLng): ILatLng => ({
|
|||
lng: (l2.lng + ((l1.lng - l2.lng) / 2))
|
||||
});
|
||||
|
||||
export const middleCoordPx = (p1: Point, p2: Point): Point => point({
|
||||
x: (p1.x + ((p2.x - p1.x) / 2)),
|
||||
y: (p1.y + ((p2.y - p1.y) / 2))
|
||||
});
|
||||
|
||||
export const deg2rad = (deg: number): number => ((deg * Math.PI) / 180);
|
||||
export const rad2deg = (rad: number): number => ((rad / Math.PI) * 180);
|
||||
|
||||
export const findDistancePx = (p1: Point, p2: Point): number => {
|
||||
return Math.sqrt(((p1.x - p2.x) ** 2) + ((p1.y - p2.y) ** 2));
|
||||
};
|
||||
|
||||
export const findDistance = (t1: number, n1: number, t2: number, n2: number): number => {
|
||||
// convert coordinates to radians
|
||||
const lat1 = deg2rad(t1);
|
||||
|
|
|
@ -6,11 +6,8 @@ import { STICKERS } from '$constants/stickers';
|
|||
import { ILatLng } from "$modules/Stickers";
|
||||
import { IStickerDump } from "$modules/Sticker";
|
||||
import { IRootState } from "$redux/user/reducer";
|
||||
|
||||
export interface IMapPoint {
|
||||
x: number,
|
||||
y: number,
|
||||
}
|
||||
import { angleBetweenPoints, angleBetweenPointsRad, findDistancePx, middleCoordPx } from "$utils/geom";
|
||||
import { Point } from "leaflet";
|
||||
|
||||
export interface ITilePlacement {
|
||||
minX: number,
|
||||
|
@ -86,7 +83,7 @@ export const getTilePlacement = (): ITilePlacement => {
|
|||
};
|
||||
};
|
||||
|
||||
export const getPolyPlacement = (): IMapPoint[] => (
|
||||
export const getPolyPlacement = (): Point[] => (
|
||||
(!editor.poly.poly || !editor.poly.poly.getLatLngs() || editor.poly.poly.getLatLngs().length <= 0)
|
||||
? []
|
||||
: editor.poly.poly.getLatLngs().map((latlng) => ({ ...editor.map.map.latLngToContainerPoint(latlng) }))
|
||||
|
@ -148,7 +145,7 @@ export const composeImages = (
|
|||
});
|
||||
};
|
||||
|
||||
export const composePoly = ({ points, ctx }: { points: IMapPoint[], ctx: CanvasRenderingContext2D }): void => {
|
||||
export const composePoly = ({ points, ctx }: { points: Point[], ctx: CanvasRenderingContext2D }): void => {
|
||||
if (editor.poly.isEmpty) return;
|
||||
|
||||
let minX = points[0].x;
|
||||
|
@ -183,6 +180,42 @@ export const composePoly = ({ points, ctx }: { points: IMapPoint[], ctx: CanvasR
|
|||
ctx.closePath();
|
||||
};
|
||||
|
||||
export const composeArrows = async ({ points, ctx }: { points: Point[], ctx: CanvasRenderingContext2D }): Promise<boolean[]> => {
|
||||
const image = await imageFetcher(require('$sprites/arrow.svg'));
|
||||
|
||||
const distances = points.map((point, i) => (
|
||||
(points[i + 1] && findDistancePx(points[i], points[i + 1])) || 0
|
||||
));
|
||||
|
||||
// we want to annotate at least 5 arrows
|
||||
const min_arrows = (distances.length >= 5 ? 5 : distances.length - 1);
|
||||
const min_distance = distances.sort((a, b) => (b - a))[min_arrows];
|
||||
|
||||
return points.map((point, i) => {
|
||||
if (!points[i + 1]) return false;
|
||||
|
||||
const distance = findDistancePx(points[i], points[i + 1]);
|
||||
const angle = angleBetweenPointsRad(points[i], points[i + 1]);
|
||||
|
||||
if (distance < min_distance && distance < 100) return false;
|
||||
|
||||
const middle = middleCoordPx(points[i], points[i + 1]);
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(middle.x, middle.y);
|
||||
ctx.rotate((Math.PI * 0.5) - angle);
|
||||
ctx.translate(-middle.x, -middle.y);
|
||||
|
||||
ctx.moveTo(middle.x, middle.y);
|
||||
|
||||
ctx.drawImage(image, middle.x - 24, middle.y - 24, 48, 48);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
const measureText = (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
text: string,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue