Moved drawing to use native konva events
This commit is contained in:
parent
cb8b66e55f
commit
0bec582116
@ -1,8 +1,9 @@
|
||||
import React, { useContext, useState, useCallback } from "react";
|
||||
import React, { useContext, useState, useEffect } from "react";
|
||||
import shortid from "shortid";
|
||||
import { Group, Line, Rect, Circle } from "react-konva";
|
||||
|
||||
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
||||
import MapStageContext from "../../contexts/MapStageContext";
|
||||
|
||||
import { compare as comparePoints } from "../../helpers/vector2";
|
||||
import {
|
||||
@ -12,9 +13,9 @@ import {
|
||||
simplifyPoints,
|
||||
getStrokeWidth,
|
||||
} from "../../helpers/drawing";
|
||||
import { getRelativePointerPositionNormalized } from "../../helpers/konva";
|
||||
|
||||
import colors from "../../helpers/colors";
|
||||
import useMapBrush from "../../helpers/useMapBrush";
|
||||
|
||||
function MapDrawing({
|
||||
shapes,
|
||||
@ -25,6 +26,7 @@ function MapDrawing({
|
||||
gridSize,
|
||||
}) {
|
||||
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
|
||||
const mapStageRef = useContext(MapStageContext);
|
||||
const [drawingShape, setDrawingShape] = useState(null);
|
||||
const [isBrushDown, setIsBrushDown] = useState(false);
|
||||
const [erasingShapes, setErasingShapes] = useState([]);
|
||||
@ -42,57 +44,53 @@ function MapDrawing({
|
||||
selectedToolSettings.type === "circle" ||
|
||||
selectedToolSettings.type === "triangle");
|
||||
|
||||
const handleBrushUp = useCallback(() => {
|
||||
setIsBrushDown(false);
|
||||
if (erasingShapes.length > 0) {
|
||||
onShapesRemove(erasingShapes.map((shape) => shape.id));
|
||||
setErasingShapes([]);
|
||||
useEffect(() => {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
}, [erasingShapes, onShapesRemove]);
|
||||
const mapStage = mapStageRef.current;
|
||||
|
||||
const handleShapeDraw = useCallback(
|
||||
(brushState, mapBrushPosition) => {
|
||||
function startShape() {
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
mapBrushPosition,
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
const commonShapeData = {
|
||||
color: selectedToolSettings && selectedToolSettings.color,
|
||||
blend: selectedToolSettings && selectedToolSettings.useBlending,
|
||||
id: shortid.generate(),
|
||||
};
|
||||
if (isBrush) {
|
||||
setDrawingShape({
|
||||
type: "path",
|
||||
pathType: selectedToolSettings.type === "brush" ? "stroke" : "fill",
|
||||
data: { points: [brushPosition] },
|
||||
strokeWidth: selectedToolSettings.type === "brush" ? 1 : 0,
|
||||
...commonShapeData,
|
||||
});
|
||||
} else if (isShape) {
|
||||
setDrawingShape({
|
||||
type: "shape",
|
||||
shapeType: selectedToolSettings.type,
|
||||
data: getDefaultShapeData(selectedToolSettings.type, brushPosition),
|
||||
strokeWidth: 0,
|
||||
...commonShapeData,
|
||||
});
|
||||
}
|
||||
setIsBrushDown(true);
|
||||
function getBrushPosition() {
|
||||
const mapImage = mapStage.findOne("#mapImage");
|
||||
return getBrushPositionForTool(
|
||||
getRelativePointerPositionNormalized(mapImage),
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
}
|
||||
|
||||
function handleBrushDown() {
|
||||
const brushPosition = getBrushPosition();
|
||||
const commonShapeData = {
|
||||
color: selectedToolSettings && selectedToolSettings.color,
|
||||
blend: selectedToolSettings && selectedToolSettings.useBlending,
|
||||
id: shortid.generate(),
|
||||
};
|
||||
if (isBrush) {
|
||||
setDrawingShape({
|
||||
type: "path",
|
||||
pathType: selectedToolSettings.type === "brush" ? "stroke" : "fill",
|
||||
data: { points: [brushPosition] },
|
||||
strokeWidth: selectedToolSettings.type === "brush" ? 1 : 0,
|
||||
...commonShapeData,
|
||||
});
|
||||
} else if (isShape) {
|
||||
setDrawingShape({
|
||||
type: "shape",
|
||||
shapeType: selectedToolSettings.type,
|
||||
data: getDefaultShapeData(selectedToolSettings.type, brushPosition),
|
||||
strokeWidth: 0,
|
||||
...commonShapeData,
|
||||
});
|
||||
}
|
||||
setIsBrushDown(true);
|
||||
}
|
||||
|
||||
function continueShape() {
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
mapBrushPosition,
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
function handleBrushMove() {
|
||||
const brushPosition = getBrushPosition();
|
||||
if (isBrushDown && drawingShape) {
|
||||
if (isBrush) {
|
||||
setDrawingShape((prevShape) => {
|
||||
const prevPoints = prevShape.data.points;
|
||||
@ -127,49 +125,51 @@ function MapDrawing({
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function endShape() {
|
||||
if (isBrush && drawingShape) {
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
onShapeAdd(drawingShape);
|
||||
}
|
||||
} else if (isShape && drawingShape) {
|
||||
function handleBrushUp() {
|
||||
if (isBrush && drawingShape) {
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
onShapeAdd(drawingShape);
|
||||
}
|
||||
setDrawingShape(null);
|
||||
handleBrushUp();
|
||||
} else if (isShape && drawingShape) {
|
||||
onShapeAdd(drawingShape);
|
||||
}
|
||||
|
||||
switch (brushState) {
|
||||
case "first":
|
||||
startShape();
|
||||
return;
|
||||
case "drawing":
|
||||
continueShape();
|
||||
return;
|
||||
case "last":
|
||||
endShape();
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
if (erasingShapes.length > 0) {
|
||||
onShapesRemove(erasingShapes.map((shape) => shape.id));
|
||||
setErasingShapes([]);
|
||||
}
|
||||
},
|
||||
[
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
stageScale,
|
||||
onShapeAdd,
|
||||
shapes,
|
||||
drawingShape,
|
||||
handleBrushUp,
|
||||
isBrush,
|
||||
isShape,
|
||||
]
|
||||
);
|
||||
|
||||
// Move away from this as it is too slow to respond
|
||||
useMapBrush(isEditing, handleShapeDraw);
|
||||
setDrawingShape(null);
|
||||
setIsBrushDown(false);
|
||||
}
|
||||
|
||||
mapStage.on("mousedown touchstart", handleBrushDown);
|
||||
mapStage.on("mousemove touchmove", handleBrushMove);
|
||||
mapStage.on("mouseup touchend", handleBrushUp);
|
||||
|
||||
return () => {
|
||||
mapStage.off("mousedown touchstart", handleBrushDown);
|
||||
mapStage.off("mousemove touchmove", handleBrushMove);
|
||||
mapStage.off("mouseup touchend", handleBrushUp);
|
||||
};
|
||||
}, [
|
||||
drawingShape,
|
||||
erasingShapes,
|
||||
gridSize,
|
||||
isBrush,
|
||||
isBrushDown,
|
||||
isEditing,
|
||||
isShape,
|
||||
mapStageRef,
|
||||
onShapeAdd,
|
||||
onShapesRemove,
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
shapes,
|
||||
stageScale,
|
||||
]);
|
||||
|
||||
function handleShapeOver(shape, isDown) {
|
||||
if (shouldHover && isDown) {
|
||||
|
@ -1,71 +0,0 @@
|
||||
import { useContext, useRef, useEffect } from "react";
|
||||
|
||||
import MapInteractionContext from "../contexts/MapInteractionContext";
|
||||
|
||||
import { compare } from "./vector2";
|
||||
|
||||
import usePrevious from "./usePrevious";
|
||||
|
||||
/**
|
||||
* @callback onBrushUpdate
|
||||
* @param {string} drawState "first" | "drawing" | "last"
|
||||
* @param {Object} brushPosition the normalized x and y coordinates of the brush on the map
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper to get the maps drag position as it changes
|
||||
* @param {boolean} shouldUpdate
|
||||
* @param {onBrushUpdate} onBrushUpdate
|
||||
*/
|
||||
function useMapBrush(shouldUpdate, onBrushUpdate) {
|
||||
const { stageDragState, mapDragPositionRef } = useContext(
|
||||
MapInteractionContext
|
||||
);
|
||||
|
||||
const requestRef = useRef();
|
||||
const previousDragState = usePrevious(stageDragState);
|
||||
const previousBrushPositionRef = useRef(mapDragPositionRef.current);
|
||||
|
||||
useEffect(() => {
|
||||
function updateBrush(forceUpdate) {
|
||||
const drawState =
|
||||
stageDragState === "dragging" ? "drawing" : stageDragState;
|
||||
const brushPosition = mapDragPositionRef.current;
|
||||
const previousBrushPostition = previousBrushPositionRef.current;
|
||||
// Only update brush when it has moved
|
||||
if (
|
||||
!compare(brushPosition, previousBrushPostition, 0.0001) ||
|
||||
forceUpdate
|
||||
) {
|
||||
onBrushUpdate(drawState, brushPosition);
|
||||
previousBrushPositionRef.current = brushPosition;
|
||||
}
|
||||
}
|
||||
|
||||
function animate() {
|
||||
if (!shouldUpdate) {
|
||||
return;
|
||||
}
|
||||
requestRef.current = requestAnimationFrame(animate);
|
||||
updateBrush(false);
|
||||
}
|
||||
|
||||
requestRef.current = requestAnimationFrame(animate);
|
||||
|
||||
if (stageDragState !== previousDragState && shouldUpdate) {
|
||||
updateBrush(true);
|
||||
}
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(requestRef.current);
|
||||
};
|
||||
}, [
|
||||
shouldUpdate,
|
||||
onBrushUpdate,
|
||||
stageDragState,
|
||||
mapDragPositionRef,
|
||||
previousDragState,
|
||||
]);
|
||||
}
|
||||
|
||||
export default useMapBrush;
|
Loading…
Reference in New Issue
Block a user