【问题标题】:D3 graph with svg nodes - How to move nodes to arbitrary positions带有 svg 节点的 D3 图 - 如何将节点移动到任意位置
【发布时间】:2013-10-12 11:02:48
【问题描述】:

我想做一个D3图,应该如下:

  1. 加载html页面时,在固定位置会有一个节点。让我们说左上角。我们称之为模板节点,这个节点是不可移动的。

  2. 当用户在模板节点上按下鼠标时,会在与模板节点相同的位置创建一个新节点,并且用户应该能够将新节点拖到他想要的位置。新节点应保持在用户移动到的位置。

  3. 用户应该可以随时移动节点。同样,该节点应保留在用户离开它的位置。

  4. 用户应该能够在任意两个节点之间绘制链接。让我们假设如果他从一个节点拖动到另一个节点而不按住 ctrl 键,则绘制一个链接,如果他在按住 control 键的同时拖动,则节点移动。

  5. 在两个节点之间绘制链接时,节点不应改变位置。

  6. 当两个节点被链接并通过拖动其中一个节点移动时,链接的大小和方向应根据需要更改。


我正在使用强制布局。

我能够创建一个模板节点,但它总是指向容器的中心——我认为这是因为容器的中心是重心。但不知道如何通过代码将其位置固定在左上角。

我可以创建链接和新节点。但是节点移动并且链接调整大小。可能是因为力布局试图使链接长度等于力布局中的链接距离。但我不知道如何使用链接距离函数?我什至不确定这是否真的有帮助。

那么我应该使用什么方法呢?有什么想法吗?

【问题讨论】:

  • 听起来你不想为此使用强制布局。
  • 感谢您的回复。这是我的第二个问题。我发布这个是因为我觉得这与我之前的问题有很大不同。我应该使用哪种布局?

标签: javascript svg d3.js force-layout


【解决方案1】:

对于强制布局,您可以将节点的 'fixed' 属性设置为 true,以防止其受到模拟的影响。之后,您应该可以手动设置它的位置。您可以选择在函数调用中执行此操作:

function pinNode(node) {
  node.fixed = true;
}

function unpinNode(node) {
  node.fixed = false;
}

我相信你可以通过这样的调用获得左上角的节点:pinNode(node, 0, 0)。只要节点的固定属性设置为 true,它就应该不受 sim 影响。您可能会发现文档中的这个 sn-p 很有帮助;它描述了固定属性如何受 force.drag 影响:

将行为绑定到节点以允许交互式拖动,或者使用 鼠标或触摸。将此与呼叫操作员结合使用 节点;例如,在初始化时说 node.call(force.drag)。 拖动事件在鼠标悬停时设置节点的固定属性,例如 只要鼠标在一个节点上,它就会停止移动。固定在 mouseover,而不是 mousedown,更容易捕捉移动 节点。当接收到 mousedown 事件时,以及随后的每个 mousemove 直到 mouseup,节点中心设置为当前鼠标 位置。此外,每次鼠标移动都会触发力的恢复 布局,重新加热模拟。如果要保留拖动的节点 拖动后固定,在dragstart上将fixed属性设置为true,如 在粘力布局示例中。

force.drag

另见此处:force layout nodes

如果您想使用链接距离函数,请在创建强制布局时包含它:

var force = d3.layout.force()
    .size(width, height)
    .linkStrength(0.5) // how much can link distance be overridedn by the simulation
    .linkDistance(function() {return /* some evaluation */;});

// ...

// You might need to defer the calculation of linkDistance until later,
// such as in update(), since nodes might not have the properties
// that you need to check until that point:

function update() {
  force
    .nodes(nodes)
    .links(links)
    .linkDistance(function(link) {
      // The function gets called for each link in the simulation.
      // Each link will be connected to two nodes, source and target, 
      // which may be useful in determining link distance.
      if (link.source.someProperty || link.target.somePropery) {
        return /* something */;
      } else {
        return /* something else */;
      }
    });
}

【讨论】:

  • 编辑了答案以包含对 linkDistance 的延迟计算,改为在 update() 中调用它。
  • 谢谢,但我仍然注意到解决问题。请参阅bl.ocks.org/rkirsling/5001347 当前,当用户按住 ctrl 键并拖动节点时,节点会移动。但它也会自行移动。自己的。为了实现以下目标,需要进行哪些代码更改?节点不应自行移动。只有当用户 ctrl 拖动它时它才会移动。当一个节点被创建时,它应该保留在它被创建的地方。当一个节点被用户移动时,它应该留在用户离开它的地方。
  • 当用户移动一个节点时,其他节点不应该改变它们的位置。当两个节点链接时,它们不应该改变位置。任何想法?谢谢。
  • pinNode() 中定位节点的部分肯定不会像我预期的那样工作,但如果一个节点被标记为“固定”,它肯定会停止移动并保持位置不变。但是我注意到的行为是,当拖动任何节点时,“固定”属性设置为零并且节点再次开始移动。我不确定为什么。如果我想出一个解决方案,我会修改我的答案。
  • 谢谢。正确修复很有用。我现在能够解决问题。看来我是新用户,没有声望点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
  • 2015-02-17
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多