Added measure tool
This commit is contained in:
142
src/components/map/MapMeasure.js
Normal file
142
src/components/map/MapMeasure.js
Normal file
@@ -0,0 +1,142 @@
|
||||
import React, { useContext, useState, useEffect } from "react";
|
||||
import { Group, Line, Text, Label, Tag } from "react-konva";
|
||||
|
||||
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
||||
import MapStageContext from "../../contexts/MapStageContext";
|
||||
|
||||
import {
|
||||
getBrushPositionForTool,
|
||||
getDefaultShapeData,
|
||||
getUpdatedShapeData,
|
||||
getStrokeWidth,
|
||||
} from "../../helpers/drawing";
|
||||
import { getRelativePointerPositionNormalized } from "../../helpers/konva";
|
||||
import * as Vector2 from "../../helpers/vector2";
|
||||
|
||||
function MapMeasure({ selectedToolSettings, active, gridSize }) {
|
||||
const { stageScale, mapWidth, mapHeight, interactionEmitter } = useContext(
|
||||
MapInteractionContext
|
||||
);
|
||||
const mapStageRef = useContext(MapStageContext);
|
||||
const [drawingShapeData, setDrawingShapeData] = useState(null);
|
||||
const [isBrushDown, setIsBrushDown] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
const mapStage = mapStageRef.current;
|
||||
|
||||
function getBrushPosition() {
|
||||
const mapImage = mapStage.findOne("#mapImage");
|
||||
return getBrushPositionForTool(
|
||||
getRelativePointerPositionNormalized(mapImage),
|
||||
"drawing",
|
||||
{ type: "line" },
|
||||
gridSize,
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
function handleBrushDown() {
|
||||
const brushPosition = getBrushPosition();
|
||||
const { points } = getDefaultShapeData("line", brushPosition);
|
||||
const length = 0;
|
||||
setDrawingShapeData({ length, points });
|
||||
setIsBrushDown(true);
|
||||
}
|
||||
|
||||
function handleBrushMove() {
|
||||
const brushPosition = getBrushPosition();
|
||||
if (isBrushDown && drawingShapeData) {
|
||||
const { points } = getUpdatedShapeData(
|
||||
"line",
|
||||
drawingShapeData,
|
||||
brushPosition,
|
||||
gridSize
|
||||
);
|
||||
const length = Vector2.distance(
|
||||
Vector2.divide(points[0], gridSize),
|
||||
Vector2.divide(points[1], gridSize),
|
||||
selectedToolSettings.type
|
||||
);
|
||||
setDrawingShapeData({
|
||||
length,
|
||||
points,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleBrushUp() {
|
||||
setDrawingShapeData(null);
|
||||
setIsBrushDown(false);
|
||||
}
|
||||
|
||||
interactionEmitter.on("dragStart", handleBrushDown);
|
||||
interactionEmitter.on("drag", handleBrushMove);
|
||||
interactionEmitter.on("dragEnd", handleBrushUp);
|
||||
|
||||
return () => {
|
||||
interactionEmitter.off("dragStart", handleBrushDown);
|
||||
interactionEmitter.off("drag", handleBrushMove);
|
||||
interactionEmitter.off("dragEnd", handleBrushUp);
|
||||
};
|
||||
}, [
|
||||
drawingShapeData,
|
||||
gridSize,
|
||||
isBrushDown,
|
||||
mapStageRef,
|
||||
interactionEmitter,
|
||||
active,
|
||||
selectedToolSettings,
|
||||
]);
|
||||
|
||||
function renderShape(shapeData) {
|
||||
const linePoints = shapeData.points.reduce(
|
||||
(acc, point) => [...acc, point.x * mapWidth, point.y * mapHeight],
|
||||
[]
|
||||
);
|
||||
|
||||
const lineCenter = Vector2.multiply(
|
||||
Vector2.divide(Vector2.add(shapeData.points[0], shapeData.points[1]), 2),
|
||||
{ x: mapWidth, y: mapHeight }
|
||||
);
|
||||
|
||||
return (
|
||||
<Group>
|
||||
<Line
|
||||
points={linePoints}
|
||||
strokeWidth={getStrokeWidth(1.5, gridSize, mapWidth, mapHeight)}
|
||||
stroke="hsla(230, 25%, 18%, 0.8)"
|
||||
lineCap="round"
|
||||
/>
|
||||
<Line
|
||||
points={linePoints}
|
||||
strokeWidth={getStrokeWidth(0.25, gridSize, mapWidth, mapHeight)}
|
||||
stroke="white"
|
||||
lineCap="round"
|
||||
/>
|
||||
<Label
|
||||
x={lineCenter.x}
|
||||
y={lineCenter.y}
|
||||
offsetX={26}
|
||||
offsetY={26}
|
||||
scaleX={1 / stageScale}
|
||||
scaleY={1 / stageScale}
|
||||
>
|
||||
<Tag fill="hsla(230, 25%, 18%, 0.8)" cornerRadius={4} />
|
||||
<Text
|
||||
text={shapeData.length.toFixed(2)}
|
||||
fill="white"
|
||||
fontSize={24}
|
||||
padding={4}
|
||||
/>
|
||||
</Label>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
return <Group>{drawingShapeData && renderShape(drawingShapeData)}</Group>;
|
||||
}
|
||||
|
||||
export default MapMeasure;
|
||||
Reference in New Issue
Block a user