2

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

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

因此,如果我还没有找到解决方案,那么对于如何实现这一点有任何提示会很棒。

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

问题是如何从一个形状开始绘制箭头并跟随鼠标指向它的目标(可以是另一个节点组 => 到该组的连接或舞台的空白点 => 打开一个覆盖层,让用户选择另一个节点绘制或取消绘制)。

我希望这有点清楚明白。欲了解更多信息,请随时问我。

最好的问候, 多米尼克

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

4

1 回答 1

3

首先,为了简单起见,这里是关于如何用鼠标和 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有父节点的组。如果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 的所有子级都可拖动和不可拖动,但您可能希望通过比 select 更具体来限制它layer.children。我喜欢在这里使用的一个很好的技巧是将所有可拖动的组命名为“draggable_shapes”,然后用于var draggableArray = stage.get('.draggable_shapes') 选择所有允许拖动的组,然后您可以循环遍历该数组和setDraggable().

另一点需要注意的是,Line 的 X 和 Y 坐标计算起来会有点棘手,这取决于它是否有一个 Group 作为父级或一个 Layer。如果 Line 被分组,则 Line 的坐标将相对于Group位置,否则 Line 的坐标将相对于Stage(左上角)。

这将使您开始将一条线与两个不同的圆圈连接起来。如果您希望线条仅连接在圆圈的外缘上,则由您来执行坐标逻辑。

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

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

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

于 2013-07-02T14:34:29.647 回答