diff --git a/src/components/draw_area.jsx b/src/components/draw_area.jsx index cb19e99..5e3e121 100644 --- a/src/components/draw_area.jsx +++ b/src/components/draw_area.jsx @@ -1,10 +1,12 @@ import React, { useRef, useState } from "react"; import { useDrop } from "react-dnd"; import Rect from "./rect"; +import Node from "./node"; export default function Canvas(props) { const [dragging, setDragging] = useState(false); const [offset, setOffset] = useState({ x: 0, y: 0 }); + const [links, setLinks] = useState([]); const canvas = useRef(null); @@ -23,11 +25,52 @@ export default function Canvas(props) { const { clientX, clientY } = event; const updatedRectangles = props.rectangles.map((rect) => { if (rect.id === dragging) { - return { + 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; }); @@ -84,9 +127,27 @@ export default function Canvas(props) { label={rectangle.label} width={rectangle.width} height={rectangle.height} + links={links} + setLinks={setLinks} onMouseDown={(event) => handleMouseDown(event, rectangle.id)} /> ))} + {links.map( + (link, index) => + links.length >= 2 && + index % 2 === 0 && + index + 1 < links.length && ( + + ) + )} diff --git a/src/components/node.js b/src/components/node.js new file mode 100644 index 0000000..6aa33f5 --- /dev/null +++ b/src/components/node.js @@ -0,0 +1,9 @@ +const Node = { + NONE: "NONE", + TOP: "TOP", + LEFT: "LEFT", + RIGHT: "RIGHT", + BOTTOM: "BOTTOM", +}; + +export default Node; diff --git a/src/components/rect.jsx b/src/components/rect.jsx index ecd87da..96a5b6f 100644 --- a/src/components/rect.jsx +++ b/src/components/rect.jsx @@ -1,7 +1,11 @@ -import React from "react"; +import { React, useState } from "react"; +import Node from "./node"; import { Button } from "@arco-design/web-react"; const Rect = (props) => { + const [isHovered, setIsHovered] = useState(false); + const [node, setNode] = useState(Node.NONE); + return ( { y={props.y} width={props.width} height={props.height} - style={{ fill: "blue", cursor: "move" }} + style={{ cursor: "move" }} onMouseDown={props.onMouseDown} + onMouseEnter={() => { + setIsHovered(true); + }} + onMouseLeave={() => { + setIsHovered(false); + }} > -
+
{props.label}
e.preventDefault()}> @@ -23,6 +36,82 @@ const Rect = (props) => {
+ { + setNode(Node.TOP); + props.setLinks([ + ...props.links, + { + rect: props.id, + node: Node.TOP, + x: props.x + props.width / 2, + y: props.y, + }, + ]); + }} + style={{ fill: node === Node.TOP ? "green" : "black" }} + /> + { + setNode(Node.LEFT); + props.setLinks([ + ...props.links, + { + rect: `${props.id}`, + node: Node.LEFT, + x: props.x, + y: props.y + props.height / 2, + }, + ]); + }} + style={{ fill: node === Node.LEFT ? "green" : "black" }} + /> + { + setNode(Node.RIGHT); + props.setLinks([ + ...props.links, + { + rect: props.id, + node: Node.RIGHT, + x: props.x + props.width, + y: props.y + props.height / 2, + }, + ]); + }} + style={{ fill: node === Node.RIGHT ? "green" : "black" }} + /> + { + setNode(Node.BOTTOM); + props.setLinks([ + ...props.links, + { + rect: props.id, + node: Node.BOTTOM, + x: props.x + props.width / 2, + y: props.y + props.height, + }, + ]); + }} + style={{ fill: node === Node.BOTTOM ? "green" : "black" }} + /> ); };