- 所以我的代码的主要目的是生成一个序列图。我有3个列表项目是可拖动的。
- 我有一个svg区域,将呈现svg组件。
- 现在可以将任何列表项拖到该区域中,并且svg区域内会出现一个带有项名称及其生命线的矩形。
- 现在我想要的应用程序做的是,当有超过2个对象,我希望能够点击一个生命线,并将其连接到其他,就像连接2个对象。
下面是我的实现:
import React, { useState } from 'react';
const App = () => {
const [startX, setStartX] = useState(null);
const [startY, setStartY] = useState(null);
const [endX, setEndX] = useState(null);
const [endY, setEndY] = useState(null);
let dragOnGoing = false;
let y = null;
const SidebarItem = ({ name }) => {
const handleDragStart = (event) => {
event.dataTransfer.setData('text/plain', name);
};
return (
<li draggable onDragStart={handleDragStart}>
{name}
</li>
);
};
const SVGContainer = () => {
const [rectangles, setRectangles] = useState([]);
const handleDrop = (event) => {
event.preventDefault();
const itemName = event.dataTransfer.getData('text/plain');
const rect = event.target.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = 22;
setRectangles((prevRectangles) => [
...prevRectangles,
{ name: itemName, x, y },
]);
};
const handleDragOver = (event) => {
event.preventDefault();
};
const handleRectangleRightClick = (index) => {
setRectangles((prevRectangles) => {
const updatedRectangles = [...prevRectangles];
updatedRectangles.splice(index, 1);
return updatedRectangles;
});
};
const handleLineClick = (event) => {
if (!dragOnGoing) {
// setDragOnGoing(true);
setStartX(event.clientX);
setStartY(event.clientY);
y = event.clientY;
document.addEventListener("mousemove", handleMouseMove);
dragOnGoing = true;
} else {
document.removeEventListener("mousemove", handleMouseMove);
console.log("not dragging");
setEndX(event.clientX);
setEndY(y);
dragOnGoing = false;
return;
}
}
const handleMouseMove = (event) => {
setEndX(event.clientX);
setEndY(y);
};
return (
<svg
onDrop={handleDrop}
onDragOver={handleDragOver}
width="100vw"
height="500"
style={{ border: '1px solid black' }}
onContextMenu={(event) => event.preventDefault()} // Disable default right-click context menu
>
{rectangles.map((rectangle, index) => (
<g key={index}>
<rect
x={rectangle.x}
y={rectangle.y}
width="100"
height="50"
fill="blue"
onContextMenu={() => handleRectangleRightClick(index)} // Handle right-click on rectangle
/>
<text
x={rectangle.x + 10}
y={rectangle.y + 30}
fill="white"
fontWeight="bold"
>
{rectangle.name}
</text>
<line
style={{ cursor: 'pointer' }}
strokeWidth={3}
onClick={handleLineClick}
x1={rectangle.x + 50}
y1={rectangle.y + 50}
x2={rectangle.x + 50}
y2="500"
stroke="black"
/>
</g>
))}
<><line
x1={startX}
y1={startY}
x2={endX}
y2={endY}
stroke="black"
strokeWidth="2"
></line>
<polygon
// x={endX}
// y={endY}
points={`${endX},${endY + 5} ${endX},${endY - 5} ${endX >= startX ? endX + 5 : endX - 5},${endY}`}
fill="black"
stroke="black"
strokeWidth="2"
/>
</>
</svg>
);
};
return (
<div>
<ul>
<SidebarItem name="Item 1" />
<SidebarItem name="Item 2" />
<SidebarItem name="Item 3" />
</ul>
<SVGContainer />
</div>
);
};
export default App;
以下是目前正在发生的事情的视频:
https://imgur.com/a/h8JKJZ7
正如您所看到的,只要我单击该行,其他svg组件就会消失。但是onclick函数并不改变任何相关对象的状态。我无法理解这种行为。
1条答案
按热度按时间brgchamk1#
单击会导致重新呈现,但由于
<SVGContainer>
是在<App>
中定义的,因此当调用App()
时,SVGContainer
组件会被视为不同的组件,因为它是内存中的一个新变量,因此其状态会丢失。考虑在
App
组件函数之外定义子组件函数: