提问人:Marwan Elsayed 提问时间:11/18/2023 最后编辑:Marwan Elsayed 更新时间:11/18/2023 访问量:50
使用 ReactJS 单击时在 2 个元素之间画线 [关闭]
Draw line between 2 elements on click using ReactJS [closed]
问:
我有这些图像,我希望用户在它们之间匹配,而不一定匹配正确的图像,然后在单击检查按钮后,他会看到匹配正确或不匹配的结果。使用 React 我需要帮助来了解它背后的逻辑。
这是代码,我已经得到了我首先单击的按钮,然后是我单击的第二个按钮以在它们之间匹配,但我无法处理如何在它们之间划线
答:
-2赞
joswxc
11/18/2023
#1
根据你的开发方式,你可以遵循这个例子并轻松实现它。
import { useEffect, useState } from "react";
import "./styles.scss";
export default function App() {
const [lines, setLines] = useState([
{ from: "topLeft", to: "centerLeft" },
{ from: "bottomCenter", to: "centerRight" }
]);
return (
<div className="App">
<SVGGrid
lines={lines}
addNewLine={(newLine) => setLines((lines) => [...lines, newLine])}
removeLineByIndex={(lineIdx) =>
setLines([...lines.slice(0, lineIdx), ...lines.slice(lineIdx + 1)])
}
/>
</div>
);
}
export function SVGGrid({
addNewLine = () => console.log("User did not provide line handler"),
removeLineByIndex = () => console.log("No deletion logic provided"),
deselectOnNewLine = true,
padding = defaultSizingOptions.padding,
lines = []
}) {
const [svgSize, setSVGSize] = useState(() => getSVGSize(padding));
const [newLineSource, setNewLineSource] = useState(null);
useEffect(() => {
const resizeListener = () => setSVGSize(getSVGSize(padding));
window.addEventListener("resize", resizeListener);
return window.removeEventListener("resize", () => resizeListener);
}, [padding]);
const circleRadius = 5;
const circlePositions = [
{ id: "topLeft", pos: [10, 10] },
{ id: "topRight", pos: [90, 10] },
{ id: "centerLeft", pos: [10, 50] },
{ id: "centerRight", pos: [90, 50] },
{ id: "bottomLeft", pos: [10, 90] },
{ id: "bottomRight", pos: [90, 90] }
];
const getCirclePositionById = (id) =>
circlePositions.find((cPos) => cPos.id === id)?.pos;
const handleBackgroundClick = (e) => {
setNewLineSource(null);
};
const handleCircleClick = (e, circleId) => {
e.preventDefault();
e.stopPropagation();
if (newLineSource && circleId !== newLineSource) {
addNewLine({ from: newLineSource, to: circleId });
if (deselectOnNewLine) {
setNewLineSource(null);
}
} else if (!newLineSource) {
setNewLineSource(circleId);
} else {
setNewLineSource(null);
}
};
return (
<svg
viewBox="0 0 100 100"
width={svgSize}
height={svgSize}
onClick={handleBackgroundClick}
>
{/* draw fixed circles */}
{circlePositions.map(({ id, pos }) => (
<circle
id={`SVGGrid-circle-${id}`}
className={[
"SVGGrid-circle",
id === newLineSource && "SVGGrid-circle-active"
]
.filter(Boolean)
.join(" ")}
onClick={(e) => handleCircleClick(e, id)}
cx={pos[0]}
cy={pos[1]}
r={circleRadius}
/>
))}
{lines.map((line, idx) => {
const sourcePos = getCirclePositionById(line.from);
const targetPos = getCirclePositionById(line.to);
if (!sourcePos || !targetPos) {
console.error("Invalid source line, probably:", {
line,
sourcePos,
targetPos
});
return null;
}
return (
<line
className="SVGGrid-line"
onClick={(e) => removeLineByIndex(idx)}
x1={sourcePos[0]}
y1={sourcePos[1]}
x2={targetPos[0]}
y2={targetPos[1]}
/>
);
})}
</svg>
);
}
const defaultSizingOptions = {
padding: 30,
maxSize: 400
};
const getSVGSize = (padding) => Math.min(400, window.innerWidth - 2 * padding);
评论
0赞
Marwan Elsayed
11/18/2023
它可以帮助你谢谢你
评论