panning :D
This commit is contained in:
parent
45963eafdb
commit
5c62a71ebd
@ -4,14 +4,18 @@ import Rect from "./rect";
|
|||||||
import Node from "./node";
|
import Node from "./node";
|
||||||
|
|
||||||
export default function Canvas(props) {
|
export default function Canvas(props) {
|
||||||
const [dragging, setDragging] = useState(false);
|
const [dragging, setDragging] = useState(-1);
|
||||||
const [offset, setOffset] = useState({ x: 0, y: 0 });
|
const [offset, setOffset] = useState({ x: 0, y: 0 });
|
||||||
const [links, setLinks] = useState([]);
|
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 canvas = useRef(null);
|
||||||
|
|
||||||
const handleMouseDown = (event, id) => {
|
const handleMouseDownRect = (e, id) => {
|
||||||
const { clientX, clientY } = event;
|
const { clientX, clientY } = e;
|
||||||
const rectangle = props.rectangles.find((rect) => rect.id === id);
|
const rectangle = props.rectangles.find((rect) => rect.id === id);
|
||||||
setOffset({
|
setOffset({
|
||||||
x: clientX - rectangle.x,
|
x: clientX - rectangle.x,
|
||||||
@ -20,65 +24,96 @@ export default function Canvas(props) {
|
|||||||
setDragging(id);
|
setDragging(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseMove = (event) => {
|
const handleMouseMove = (e) => {
|
||||||
if (dragging === false) return;
|
if (dragging < 0 && panning) {
|
||||||
const { clientX, clientY } = event;
|
const dx = e.clientX - panOffset.x;
|
||||||
const updatedRectangles = props.rectangles.map((rect) => {
|
const dy = e.clientY - panOffset.y;
|
||||||
if (rect.id === dragging) {
|
setPanOffset({ x: e.clientX, y: e.clientY });
|
||||||
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);
|
const updatedRectangles = props.rectangles.map((rect) => ({
|
||||||
return updatedRect;
|
...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 = () => {
|
const handleMouseUp = () => {
|
||||||
setDragging(false);
|
setDragging(-1);
|
||||||
|
setPanning(false);
|
||||||
|
setCursor("default");
|
||||||
};
|
};
|
||||||
|
|
||||||
const [, drop] = useDrop(
|
const [, drop] = useDrop(
|
||||||
@ -110,14 +145,14 @@ export default function Canvas(props) {
|
|||||||
}),
|
}),
|
||||||
[props.rectangles]
|
[props.rectangles]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={drop} className="flex-grow" id="canvas">
|
<div ref={drop} className="flex-grow" id="canvas">
|
||||||
<div ref={canvas} className="w-full h-screen">
|
<div ref={canvas} className="w-full h-screen">
|
||||||
<svg
|
<svg
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
|
onMouseDown={handleMouseDown}
|
||||||
onMouseUp={handleMouseUp}
|
onMouseUp={handleMouseUp}
|
||||||
style={{ width: "100%", height: "100%" }}
|
style={{ width: "100%", height: "100%", cursor: cursor }}
|
||||||
>
|
>
|
||||||
{props.rectangles.map((rectangle) => (
|
{props.rectangles.map((rectangle) => (
|
||||||
<Rect
|
<Rect
|
||||||
@ -128,9 +163,10 @@ export default function Canvas(props) {
|
|||||||
label={rectangle.label}
|
label={rectangle.label}
|
||||||
width={rectangle.width}
|
width={rectangle.width}
|
||||||
height={rectangle.height}
|
height={rectangle.height}
|
||||||
|
setOnRect={setOnRect}
|
||||||
links={links}
|
links={links}
|
||||||
setLinks={setLinks}
|
setLinks={setLinks}
|
||||||
onMouseDown={(event) => handleMouseDown(event, rectangle.id)}
|
onMouseDown={(e) => handleMouseDownRect(e, rectangle.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{links.map(
|
{links.map(
|
||||||
|
@ -18,9 +18,11 @@ const Rect = (props) => {
|
|||||||
onMouseDown={props.onMouseDown}
|
onMouseDown={props.onMouseDown}
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
setIsHovered(true);
|
setIsHovered(true);
|
||||||
|
props.setOnRect(true);
|
||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
setIsHovered(false);
|
setIsHovered(false);
|
||||||
|
props.setOnRect(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
Loading…
Reference in New Issue
Block a user