带有箭头的 React-konva 双连接对象
React-konva double connected objects with arrow
我正在尝试通过允许两个节点(Circle
class 的形状)被双重引用(A 通过 [=11= 连接到 B)来扩展 Connected Objects 演示] 并且 B 通过 Arrow2
) 连接到 A)。我使用 react-konva
包。
我已经在 Code Sandbox 上实现了一个具有一些基本功能的演示。
在第 5
、6
行你会找到节点信息,在第 21
行有一个高阶组件,它根据起始节点和结束节点位置。
在默认示例中,箭头按预期工作。如果您尝试将 redNode.x
的值设置为 300
,则箭头重叠。当 blueNode.x
等于 -100
时也会发生同样的情况。这与我计算箭头的方式有关(我怀疑行 38
上的方程式)。
另请注意,当 redNode.x
移动到值 300
时,两个箭头相互接近(这也发生在其他值上),这是我不希望发生的事情。我希望当两个节点改变位置并且不重叠或相互接近时,箭头具有相同的形状。不幸的是,我缺乏数学并不能帮助我解决问题。我还尝试使用 quadraticCurveTo
方法创建自定义形状但没有成功。
在此先感谢您的帮助。我感谢所有解决方案。
制作曲线的方法有很多种。这是我试图让它变得更好的尝试:
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
我正在尝试通过允许两个节点(Circle
class 的形状)被双重引用(A 通过 [=11= 连接到 B)来扩展 Connected Objects 演示] 并且 B 通过 Arrow2
) 连接到 A)。我使用 react-konva
包。
我已经在 Code Sandbox 上实现了一个具有一些基本功能的演示。
在第 5
、6
行你会找到节点信息,在第 21
行有一个高阶组件,它根据起始节点和结束节点位置。
在默认示例中,箭头按预期工作。如果您尝试将 redNode.x
的值设置为 300
,则箭头重叠。当 blueNode.x
等于 -100
时也会发生同样的情况。这与我计算箭头的方式有关(我怀疑行 38
上的方程式)。
另请注意,当 redNode.x
移动到值 300
时,两个箭头相互接近(这也发生在其他值上),这是我不希望发生的事情。我希望当两个节点改变位置并且不重叠或相互接近时,箭头具有相同的形状。不幸的是,我缺乏数学并不能帮助我解决问题。我还尝试使用 quadraticCurveTo
方法创建自定义形状但没有成功。
在此先感谢您的帮助。我感谢所有解决方案。
制作曲线的方法有很多种。这是我试图让它变得更好的尝试:
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