1

我试图通过允许两个节点(类的形状)被双重引用(A 连接到 B with和 B 连接到 A with )来扩展Connected Objects演示。我使用包。CircleArrow1Arrow2react-konva

我已经在Code Sandbox上实现了一个带有一些基本功能的演示。

在线56你会找到节点信息,在线21有一个高阶组件,它根据起始节点和结束节点的位置创建箭头。

在默认示例中,箭头按预期工作。如果您尝试将值设置redNode.x300箭头重叠。当blueNode.x等于时也会发生同样的情况-100。这与我计算箭头的方式有关(我怀疑线上的方程38)。

另请注意,随着redNode.x移动到 value 300,两个箭头彼此接近(这也发生在其他值上),这是我不希望发生的事情。当两个节点改变位置并且不重叠或相互接近时,我希望箭头具有相同的形状。不幸的是,我缺乏数学并不能帮助我解决问题。我还尝试使用quadraticCurveTo方法创建自定义形状但没有成功。

在此先感谢您的帮助。我感谢所有的解决方案。

4

1 回答 1

1

有很多方法可以制作曲线。这是我试图让它变得更好的尝试:

import React from "react";
import ReactDOM from "react-dom";
import { Stage, Layer, Circle, Arrow, Text } from "react-konva";

const BLUE_DEFAULTS = {
  x: 100,
  y: 100,
  fill: "blue",
  width: 30,
  height: 30,
  draggable: true
};

const RED_DEFAULTS = {
  x: 100,
  y: 300,
  fill: "red",
  width: 30,
  height: 30,
  draggable: true
};

const Edge = ({ node1, node2 }) => {
  const dx = node1.x - node2.x;
  const dy = node1.y - node2.y;
  let angle = Math.atan2(-dy, dx);

  const radius = 20;
  const curvePower = 30;

  const arrowStart = {
    x: node2.x + -radius * Math.cos(angle + Math.PI),
    y: node2.y + radius * Math.sin(angle + Math.PI)
  };

  const arrowEnd = {
    x: node1.x + -radius * Math.cos(angle),
    y: node1.y + radius * Math.sin(angle)
  };

  const arrowCurve = {
    x:
      (arrowStart.x + arrowEnd.x) / 2 +
      curvePower * Math.cos(angle + Math.PI / 2),
    y:
      (arrowStart.y + arrowEnd.y) / 2 +
      curvePower * Math.sin(angle - Math.PI / 2)
  };

  return (
    <Arrow
      tension={0.2}
      points={[
        arrowStart.x,
        arrowStart.y,
        arrowCurve.x,
        arrowCurve.y,
        arrowEnd.x,
        arrowEnd.y
      ]}
      stroke="#000"
      fill="#000"
      strokeWidth={3}
      pointerWidth={6}
    />
  );
};

const App = () => {
  const [blueNode, updateBlueNode] = React.useState(BLUE_DEFAULTS);
  const [redNode, updateRedNode] = React.useState(RED_DEFAULTS);

  return (
    <Stage width={window.innerWidth} height={window.innerHeight}>
      <Layer>
        <Text text="Drag any node to see connections change" />
        <Edge node1={blueNode} node2={redNode} />
        <Edge node1={redNode} node2={blueNode} />
        <Circle
          {...blueNode}
          onDragMove={e => {
            updateBlueNode({ ...blueNode, ...e.target.position() });
          }}
        />
        <Circle
          {...redNode}
          onDragMove={e => {
            updateRedNode({ ...redNode, ...e.target.position() });
          }}
        />
      </Layer>
    </Stage>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

演示:https ://codesandbox.io/s/react-konva-double-connected-objects-m5g22

于 2019-08-26T00:40:58.073 回答