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 shortid from "shortid";
|
||||||
import { Group, Line, Rect, Circle } from "react-konva";
|
import { Group, Line, Rect, Circle } from "react-konva";
|
||||||
|
|
||||||
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
||||||
|
import MapStageContext from "../../contexts/MapStageContext";
|
||||||
|
|
||||||
import { compare as comparePoints } from "../../helpers/vector2";
|
import { compare as comparePoints } from "../../helpers/vector2";
|
||||||
import {
|
import {
|
||||||
@ -12,9 +13,9 @@ import {
|
|||||||
simplifyPoints,
|
simplifyPoints,
|
||||||
getStrokeWidth,
|
getStrokeWidth,
|
||||||
} from "../../helpers/drawing";
|
} from "../../helpers/drawing";
|
||||||
|
import { getRelativePointerPositionNormalized } from "../../helpers/konva";
|
||||||
|
|
||||||
import colors from "../../helpers/colors";
|
import colors from "../../helpers/colors";
|
||||||
import useMapBrush from "../../helpers/useMapBrush";
|
|
||||||
|
|
||||||
function MapDrawing({
|
function MapDrawing({
|
||||||
shapes,
|
shapes,
|
||||||
@ -25,6 +26,7 @@ function MapDrawing({
|
|||||||
gridSize,
|
gridSize,
|
||||||
}) {
|
}) {
|
||||||
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
|
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
|
||||||
|
const mapStageRef = useContext(MapStageContext);
|
||||||
const [drawingShape, setDrawingShape] = useState(null);
|
const [drawingShape, setDrawingShape] = useState(null);
|
||||||
const [isBrushDown, setIsBrushDown] = useState(false);
|
const [isBrushDown, setIsBrushDown] = useState(false);
|
||||||
const [erasingShapes, setErasingShapes] = useState([]);
|
const [erasingShapes, setErasingShapes] = useState([]);
|
||||||
@ -42,24 +44,25 @@ function MapDrawing({
|
|||||||
selectedToolSettings.type === "circle" ||
|
selectedToolSettings.type === "circle" ||
|
||||||
selectedToolSettings.type === "triangle");
|
selectedToolSettings.type === "triangle");
|
||||||
|
|
||||||
const handleBrushUp = useCallback(() => {
|
useEffect(() => {
|
||||||
setIsBrushDown(false);
|
if (!isEditing) {
|
||||||
if (erasingShapes.length > 0) {
|
return;
|
||||||
onShapesRemove(erasingShapes.map((shape) => shape.id));
|
|
||||||
setErasingShapes([]);
|
|
||||||
}
|
}
|
||||||
}, [erasingShapes, onShapesRemove]);
|
const mapStage = mapStageRef.current;
|
||||||
|
|
||||||
const handleShapeDraw = useCallback(
|
function getBrushPosition() {
|
||||||
(brushState, mapBrushPosition) => {
|
const mapImage = mapStage.findOne("#mapImage");
|
||||||
function startShape() {
|
return getBrushPositionForTool(
|
||||||
const brushPosition = getBrushPositionForTool(
|
getRelativePointerPositionNormalized(mapImage),
|
||||||
mapBrushPosition,
|
|
||||||
selectedToolId,
|
selectedToolId,
|
||||||
selectedToolSettings,
|
selectedToolSettings,
|
||||||
gridSize,
|
gridSize,
|
||||||
shapes
|
shapes
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBrushDown() {
|
||||||
|
const brushPosition = getBrushPosition();
|
||||||
const commonShapeData = {
|
const commonShapeData = {
|
||||||
color: selectedToolSettings && selectedToolSettings.color,
|
color: selectedToolSettings && selectedToolSettings.color,
|
||||||
blend: selectedToolSettings && selectedToolSettings.useBlending,
|
blend: selectedToolSettings && selectedToolSettings.useBlending,
|
||||||
@ -85,14 +88,9 @@ function MapDrawing({
|
|||||||
setIsBrushDown(true);
|
setIsBrushDown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function continueShape() {
|
function handleBrushMove() {
|
||||||
const brushPosition = getBrushPositionForTool(
|
const brushPosition = getBrushPosition();
|
||||||
mapBrushPosition,
|
if (isBrushDown && drawingShape) {
|
||||||
selectedToolId,
|
|
||||||
selectedToolSettings,
|
|
||||||
gridSize,
|
|
||||||
shapes
|
|
||||||
);
|
|
||||||
if (isBrush) {
|
if (isBrush) {
|
||||||
setDrawingShape((prevShape) => {
|
setDrawingShape((prevShape) => {
|
||||||
const prevPoints = prevShape.data.points;
|
const prevPoints = prevShape.data.points;
|
||||||
@ -127,8 +125,9 @@ function MapDrawing({
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function endShape() {
|
function handleBrushUp() {
|
||||||
if (isBrush && drawingShape) {
|
if (isBrush && drawingShape) {
|
||||||
if (drawingShape.data.points.length > 1) {
|
if (drawingShape.data.points.length > 1) {
|
||||||
onShapeAdd(drawingShape);
|
onShapeAdd(drawingShape);
|
||||||
@ -136,40 +135,41 @@ function MapDrawing({
|
|||||||
} else if (isShape && drawingShape) {
|
} else if (isShape && drawingShape) {
|
||||||
onShapeAdd(drawingShape);
|
onShapeAdd(drawingShape);
|
||||||
}
|
}
|
||||||
setDrawingShape(null);
|
|
||||||
handleBrushUp();
|
if (erasingShapes.length > 0) {
|
||||||
|
onShapesRemove(erasingShapes.map((shape) => shape.id));
|
||||||
|
setErasingShapes([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (brushState) {
|
setDrawingShape(null);
|
||||||
case "first":
|
setIsBrushDown(false);
|
||||||
startShape();
|
|
||||||
return;
|
|
||||||
case "drawing":
|
|
||||||
continueShape();
|
|
||||||
return;
|
|
||||||
case "last":
|
|
||||||
endShape();
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
[
|
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,
|
selectedToolId,
|
||||||
selectedToolSettings,
|
selectedToolSettings,
|
||||||
gridSize,
|
|
||||||
stageScale,
|
|
||||||
onShapeAdd,
|
|
||||||
shapes,
|
shapes,
|
||||||
drawingShape,
|
stageScale,
|
||||||
handleBrushUp,
|
]);
|
||||||
isBrush,
|
|
||||||
isShape,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Move away from this as it is too slow to respond
|
|
||||||
useMapBrush(isEditing, handleShapeDraw);
|
|
||||||
|
|
||||||
function handleShapeOver(shape, isDown) {
|
function handleShapeOver(shape, isDown) {
|
||||||
if (shouldHover && 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