KineticJS:在两个形状之间绘制箭头

KineticJS: Draw Arrow between two shapes

本文关键字:之间 绘制 两个 KineticJS      更新时间:2023-09-26

因此,我想在kineticjs的帮助下创建一个有限状态机可视化工具/编辑器,但我遇到了以下场景:

我有两个"节点",比方说圆形对象(用标签分组),它们可以在我的舞台上拖动。现在我不想点击一个圆圈,按住鼠标移动它,在两个形状之间添加一个连接(为了简化起见,是一个箭头)。

因此,如果能对如何实现这一点有任何提示,那就太好了,因为我还没有找到解决方案。

指定它:节点本身应该保持可拖动状态。我的想法是:添加一个半径稍小的黑色圆圈和一个白色圆圈,将它们分组。然后在dragstart白色圆圈->拖动节点,在dragsstart黑色圆圈->绘制箭头。

问题是如何从一个形状开始绘制箭头,并跟随鼠标到达其目标(可以是另一个节点组=>到此组的连接,也可以是阶段的空白点=>打开一个覆盖,用户可以选择另一个要绘制或取消绘制的节点)。

我希望这能让人明白一些。欲了解更多信息,请随时询问我。

谨致问候,多米尼克

附言:这种行为似乎与lucidchart(dot.com)在创建图表时使用的行为完全一样,所以也许你能从他们的演示中更好地理解我想要实现的目标:https://www.lucidchart.com/demo。

首先,为了简单起见,这里有一个关于如何用鼠标和KineticJS绘制基本直线的技巧:http://jsfiddle.net/projeqht/fF3hh/

假设你在舞台上已经有两个圆圈,你需要画一条线来连接它们。

我们可以使用e.targetNode来选择每个事件上的节点(mousedown、mouseup),例如:

layer.on("mousedown", function (e) {
  var nodeDown = e.targetNode;
}
layer.on("mouseup", function (e) {
  var nodeUp = e.targetNode;
}

我们需要检查nodeDown的父对象是否是Kinetic。Group其他对象。

  1. 如果目标节点nodeDown有一个Kinetic.Group作为父节点,我们可以使用该Group来存储新行和第二个目标节点nodeUp
  2. 如果目标节点nodeUp没有Kinetic.Group作为父节点,我们需要查看nodeUp是否有Group作为父节点。如果nodeUp有一个Kinetic.Group作为父节点,那么我们可以使用该Group来存储新行和第一个目标节点nodeDown
  3. 如果nodeDownnodeUp都没有父对象的组,那么我们需要为它们创建一个新组,并将所有3个形状(2个圆和一条线)添加到该新组中

使用本教程可以学习如何将形状从一组移动到另一组:http://www.html5canvastutorials.com/kineticjs/html5-canvas-move-shape-to-another-container-with-kineticjs/

此外,如果将形状从一个组移动到另一个组,则可能需要remove()destroy()作为不再需要的额外组。

绘制直线时,必须禁用拖动形状,以便使用鼠标进行拖动和绘制。你可以通过做类似的事情来做到这一点:

function stopDrag() {
  for (var i=0; i<layer.children.length; i++) {
    layer.children[i].setDraggable(false);
  }
}
function startDrag() {
  for (var i=0; i<layer.children.length; i++) {
      layer.children[i].setDraggable(true);
  }
}

这将使层的所有子级都可以拖动和不可拖动,但您可能希望通过比选择layer.children更具体的方式来限制这一点。我喜欢在这里使用的一个很好的技巧是将所有可拖动的组命名为"draggable_shapes",然后使用var draggableArray = stage.get('.draggable_shapes')选择所有允许拖动的组,然后可以循环遍历该数组和setDraggable()

另一点需要注意的是,线的X和Y坐标计算起来有点棘手,这取决于它是将组作为父对象还是将层作为父对象。如果对测线进行分组,则测线的坐标将相对于位置,否则测线坐标将相对于阶段(左上角)。

这将使您开始连接具有两个不同圆的直线。如果你想让直线只连接在圆的外缘,那就由你来做坐标逻辑了。

也许您可能想在每个圆后面添加一个透明矩形(属性opacity: 0),这样在鼠标按下矩形时,您将调用drawLine()开始绘制一条线。否则,如果用户单击圆圈,它将拖动组。至少它具有与清醒图表应用程序类似的功能。

自定义命中函数(http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-custom-hit-function-tutorial/)这可能是一种更干净的方法,但我不是100%使用自定义点击功能,其他人可能更清楚。

如果你需要进一步的帮助,请告诉我。祝你好运