使用 ReactJS 单击时在 2 个元素之间画线 [关闭]

Draw line between 2 elements on click using ReactJS [closed]

提问人:Marwan Elsayed 提问时间:11/18/2023 最后编辑:Marwan Elsayed 更新时间:11/18/2023 访问量:50

问:


想改进这个问题吗?更新问题,使其仅通过编辑这篇文章来关注一个问题。

6小时前关闭。

I have this images i want the user to match between them not necessaries to match the right ones then after clicking the check button he see the result if he match it right or no, Using React this the Code i already got the button i clicked first then the button i clicked second to match between them but i cant handle how to draw the line between them

我有这些图像,我希望用户在它们之间匹配,而不一定匹配正确的图像,然后在单击检查按钮后,他会看到匹配正确或不匹配的结果。使用 React 我需要帮助来了解它背后的逻辑。

这是代码,我已经得到了我首先单击的按钮,然后是我单击的第二个按钮以在它们之间匹配,但我无法处理如何在它们之间划线

反应JS

评论

0赞 Heretic Monkey 11/18/2023
请阅读 How to Ask 并意识到 Stack Overflow 将有助于解决构建软件时遇到的编程问题。目前尚不清楚这个问题在问什么,但如果你想要标题问题的答案,了解 HTML 的结构和你拥有的现有 React 代码会有所帮助。
0赞 Marwan Elsayed 11/18/2023
我认为我的问题很清楚,我想将左侧的图像与右侧的图像进行匹配,用户通过单击每个图像进行选择,然后画一条线
0赞 Heretic Monkey 11/18/2023
轮到你了。这个问题可能会被关闭,因为这里什么都没有。你要求人们从头开始构建应用程序。
0赞 Marwan Elsayed 11/18/2023
我上传了代码
0赞 Heretic Monkey 11/18/2023
请不要上传代码/数据/错误的图像。

答:

-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
它可以帮助你谢谢你