React-konva 带箭头的双连接对象

Posted

技术标签:

【中文标题】React-konva 带箭头的双连接对象【英文标题】:React-konva double connected objects with arrow 【发布时间】:2019-12-29 01:07:00 【问题描述】:

我正在尝试通过允许双重引用两个节点(Circle 类的形状)来扩展 Connected Objects 演示(A 使用 Arrow1 连接到 B,B 使用 Arrow2 连接到 A)。我使用react-konva 包。

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

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

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

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

提前感谢您的帮助。我感谢所有的解决方案。

【问题讨论】:

【参考方案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

【讨论】:

这太棒了!我想问你是如何学会计算这些公式的。这与三角学有关,但你能给我推荐一些适合初学者的书吗?类似于“html canvas 的实用三角函数”之类的东西。写一篇博文也是个好主意! 我不知道任何书(可能有一些)。但是这本书/帖子的想法很酷,会考虑到我。只需要学习“无聊”的数学。

以上是关于React-konva 带箭头的双连接对象的主要内容,如果未能解决你的问题,请参考以下文章

MySQL BEFORE DELETE触发器具有双连接和条件

使用 NHibernate 的双连接有序树映射

5G核心网技术基础自学系列 | 双连接

双连接查询需要 540 秒才能运行 - 我怎样才能加快速度?

如何在双连接关系之后在 Django 中执行查询(或:如何绕过 Django 对多对多“通过”模型的限制?)

[4G/5G/6G专题基础-160]: 5G双链接与MCG/SCG/PCell/PSCell/SCell