简体   繁体   English

带有SVG节点的D3图-如何将节点移动到任意位置

[英]D3 graph with svg nodes - How to move nodes to arbitrary positions

I want to make a D3 graph, which should be as follows: 我要制作一个D3图,应如下所示:

  1. When the html page is loaded, there will be a single node at a fixed location. 加载html页面时,在固定位置将只有一个节点。 Let us say top left. 让我们说左上方。 Let us call it template node and this node is non-movable. 让我们将其称为模板节点,并且该节点是不可移动的。

  2. When the user does mouse down on the template node, a new node is created at the same location as the template node and the user should be able to drag the new node to where he wants. 当用户在模板节点上向下移动鼠标时,将在与模板节点相同的位置创建一个新节点,并且用户应能够将新节点拖到所需位置。 The new node should remain exactly where the user moves it to. 新节点应准确保留在用户将其移动到的位置。

  3. At any time user should be able to move a node. 用户随时都可以移动节点。 Again the node should remain where the user leaves it. 同样,该节点应保留在用户离开的位置。

  4. User should be able to draw link between any two nodes. 用户应该能够在任何两个节点之间绘制链接。 Let us assume that if he drags from one node to another without holding down ctrl key, then a link is drawn and if he drags while holding down the control key, then the node moves. 让我们假设,如果他在不按住ctrl键的情况下从一个节点拖动到另一节点,则绘制了一个链接;如果在按住Control键的同时拖动,则该节点移动了。

  5. When a link is drawn between two nodes, then the nodes should not change positions. 当在两个节点之间绘制链接时,则这些节点不应更改位置。

  6. When two nodes are linked and one of them is moved by dragging it, then the link should change in size and orientation as needed. 当两个节点被链接并且其中一个节点通过拖动移动时,该链接应根据需要更改大小和方向。


I am using force layout. 我正在使用强制布局。

I am able to create a template node but it always goes to the center of the container - I think it is because the center of the container is the center of gravity. 我能够创建一个模板节点,但是它总是到达容器的中心-我认为这是因为容器的中心是重心。 But not sure how to fix its position to the top left through code. 但是不确定如何通过代码将其位置固定在左上方。

I can create links and new nodes. 我可以创建链接和新节点。 But the nodes move and links resize. 但是节点移动并且链接重新调整大小。 May be it is because force layout tries to make link lengths equal to the link distance in the force layout. 可能是因为力布局试图使链接长度等于力布局中的链接距离。 But I do not know how to use a function for link distance? 但是我不知道如何使用函数来实现链接距离? I am even not sure if that will really help. 我什至不确定这是否真的有帮助。

So what method should I use? 那我应该用什么方法呢? Any idea? 任何想法?

For force layout, you can set the 'fixed' property of a node to true in order to prevent it from being affected by the simulation. 对于强制布局,可以将节点的“固定”属性设置为true,以防止其受到仿真的影响。 After that, you should be able to set it's position manually. 之后,您应该可以手动设置其位置。 You might choose to do this in a function call: 您可以选择在函数调用中执行此操作:

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

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

I believe you could get a node to the upper left corner with a call like this: pinNode(node, 0, 0) . 我相信可以通过这样的调用将节点移到左上角: pinNode(node, 0, 0) As long as the node has its fixed property set to true, it should remain unaffected by the sim. 只要节点的固定属性设置为true,它就不会受到sim的影响。 You might find this snippet from the documentation helpful; 您可能会从文档中发现此片段很有帮助; it describes how the fixed property is affected by force.drag: 它描述了受force.drag影响固定属性的方式:

Bind a behavior to nodes to allow interactive dragging, either using the mouse or touch. 将行为绑定到节点以允许使用鼠标或触摸进行交互式拖动。 Use this in conjunction with the call operator on the nodes; 与节点上的调用运算符结合使用; for example, say node.call(force.drag) on initialization. 例如,在初始化时说出node.call(force.drag)。 The drag event sets the fixed attribute of nodes on mouseover, such that as soon as the mouse is over a node, it stops moving. 拖动事件会在鼠标悬停时设置节点的固定属性,这样,一旦鼠标悬停在节点上,鼠标就会停止移动。 Fixing on mouseover, rather than on mousedown, makes it easier to catch moving nodes. 固定在鼠标悬停而不是鼠标悬停上,可以更轻松地捕获移动的节点。 When a mousedown event is received, and on each subsequent mousemove until mouseup, the node center is set to the current mouse position. 接收到mousedown事件时,以及随后的每次mousemove直到mouseup,节点中心都将设置为当前鼠标位置。 In addition, each mousemove triggers a resume of the force layout, reheating the simulation. 此外,每次移动鼠标都会触发力布局的恢复,从而重新模拟。 If you want dragged nodes to remain fixed after dragging, set the fixed attribute to true on dragstart, as in the sticky force layout example. 如果要在拖动后使被拖动的节点保持固定,请像在粘滞力布局示例中一样,在dragstart上将fixed属性设置为true。

force.drag force.drag

Also see here: force layout nodes 另请参见此处: 强制布局节点

If you want to use a function for link distance, include it when you create the force layout: 如果要使用函数来链接距离,请在创建力布局时将其包括在内:

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 */;
      }
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM