diff --git a/src/components/draw_area.jsx b/src/components/draw_area.jsx index 12e71b5..31d5fa6 100644 --- a/src/components/draw_area.jsx +++ b/src/components/draw_area.jsx @@ -4,14 +4,18 @@ import Rect from "./rect"; import Node from "./node"; export default function Canvas(props) { - const [dragging, setDragging] = useState(false); + const [dragging, setDragging] = useState(-1); const [offset, setOffset] = useState({ x: 0, y: 0 }); const [links, setLinks] = useState([]); + const [onRect, setOnRect] = useState(false); + const [panning, setPanning] = useState(false); + const [panOffset, setPanOffset] = useState({ x: 0, y: 0 }); + const [cursor, setCursor] = useState("default"); const canvas = useRef(null); - const handleMouseDown = (event, id) => { - const { clientX, clientY } = event; + const handleMouseDownRect = (e, id) => { + const { clientX, clientY } = e; const rectangle = props.rectangles.find((rect) => rect.id === id); setOffset({ x: clientX - rectangle.x, @@ -20,65 +24,96 @@ export default function Canvas(props) { setDragging(id); }; - const handleMouseMove = (event) => { - if (dragging === false) return; - const { clientX, clientY } = event; - const updatedRectangles = props.rectangles.map((rect) => { - if (rect.id === dragging) { - const updatedRect = { - ...rect, - x: clientX - offset.x, - y: clientY - offset.y, - }; - const updatedLinks = links.map((link) => { - let updatedLink = link; - if (link.rect === updatedRect.id) { - switch (link.node) { - case Node.TOP: - updatedLink = { - ...link, - x: updatedRect.x + updatedRect.width / 2, - y: updatedRect.y, - }; - break; - case Node.BOTTOM: - updatedLink = { - ...link, - x: updatedRect.x + updatedRect.width / 2, - y: updatedRect.y + updatedRect.height, - }; - break; - case Node.LEFT: - updatedLink = { - ...link, - x: updatedRect.x, - y: updatedRect.y + updatedRect.height / 2, - }; - break; - case Node.RIGHT: - updatedLink = { - ...link, - x: updatedRect.x + updatedRect.width, - y: updatedRect.y + updatedRect.height / 2, - }; - break; - default: - break; - } - } - return updatedLink; - }); + const handleMouseMove = (e) => { + if (dragging < 0 && panning) { + const dx = e.clientX - panOffset.x; + const dy = e.clientY - panOffset.y; + setPanOffset({ x: e.clientX, y: e.clientY }); - setLinks(updatedLinks); - return updatedRect; + const updatedRectangles = props.rectangles.map((rect) => ({ + ...rect, + x: rect.x + dx, + y: rect.y + dy, + })); + props.setRectangles(updatedRectangles); + + const updatedLinks = links.map((link) => ({ + ...link, + x: link.x + dx, + y: link.y + dy, + })); + setLinks(updatedLinks); + } else if (dragging >= 0) { + const { clientX, clientY } = e; + const updatedRectangles = props.rectangles.map((rect) => { + if (rect.id === dragging) { + const updatedRect = { + ...rect, + x: clientX - offset.x, + y: clientY - offset.y, + }; + const updatedLinks = links.map((link) => { + let updatedLink = link; + if (link.rect === updatedRect.id) { + switch (link.node) { + case Node.TOP: + updatedLink = { + ...link, + x: updatedRect.x + updatedRect.width / 2, + y: updatedRect.y, + }; + break; + case Node.BOTTOM: + updatedLink = { + ...link, + x: updatedRect.x + updatedRect.width / 2, + y: updatedRect.y + updatedRect.height, + }; + break; + case Node.LEFT: + updatedLink = { + ...link, + x: updatedRect.x, + y: updatedRect.y + updatedRect.height / 2, + }; + break; + case Node.RIGHT: + updatedLink = { + ...link, + x: updatedRect.x + updatedRect.width, + y: updatedRect.y + updatedRect.height / 2, + }; + break; + default: + break; + } + } + return updatedLink; + }); + + setLinks(updatedLinks); + return updatedRect; + } + return rect; + }); + props.setRectangles(updatedRectangles); + } + }; + + const handleMouseDown = (e) => { + if (dragging < 0) { + if (!onRect) { + setPanning(true); + setPanOffset({ x: e.clientX, y: e.clientY }); + setCursor("grabbing"); } - return rect; - }); - props.setRectangles(updatedRectangles); + } }; const handleMouseUp = () => { - setDragging(false); + setDragging(-1); + setPanning(false); + setCursor("default"); }; const [, drop] = useDrop( @@ -110,14 +145,14 @@ export default function Canvas(props) { }), [props.rectangles] ); - return (
{props.rectangles.map((rectangle) => ( handleMouseDown(event, rectangle.id)} + onMouseDown={(e) => handleMouseDownRect(e, rectangle.id)} /> ))} {links.map( diff --git a/src/components/rect.jsx b/src/components/rect.jsx index 95e4dff..de77fa7 100644 --- a/src/components/rect.jsx +++ b/src/components/rect.jsx @@ -18,9 +18,11 @@ const Rect = (props) => { onMouseDown={props.onMouseDown} onMouseEnter={() => { setIsHovered(true); + props.setOnRect(true); }} onMouseLeave={() => { setIsHovered(false); + props.setOnRect(false); }} >