在力导向图中随机绘制节点

3
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <title>Force Layout Example 1</title>
    <style>

.node {
    fill: #ccc;
    stroke: #fff;
    stroke-width: 2px;
}

.link {
    stroke: #777;
    stroke-width: 2px;
}
.line {
    stroke: #777;
    stroke-width: 2px;
}

    </style>
</head>
<body>
    <script src='http://d3js.org/d3.v3.min.js'></script>
    <script>

var width = 640,
    height = 480;

var nodes = [
    { "x": 200, "y": 200 },
    { "x": 500,  "y":  300 },
  { "x": 500,  "y":  100 },
  //{ "x": 650,  "y":  100 },
];

//var nodes = [
  //  { "x": 200, "y": 200 },
    //            { "x": 500,  "y":  300 },
  //{ "x": 500,  "y":  100 },
//];
//var links = [
  //  { source: 0, target: 1 },
 // { source: 1, target: 2 },
//];

var links = [
    { source: 0, target: 1 },
  { source: 0, target: 2 },
  //{ source: 1, target: 3 },
];

var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height);


var force = d3.layout.force()
    .size([width, height])
    .nodes(nodes)
    .links(links);

force.linkDistance(75);

var link = svg.selectAll('.link')
    .data(links)
    .enter().append('line')
    .attr('class', 'link');

var node = svg.selectAll('.node')
          .data(nodes)
          .enter().append('rect')
          .attr('class', 'node');

var subnode = svg.selectAll('.subnode')
                 .data(nodes)
                 .enter().append('circle')
                 .attr('class', 'subnode');

var subnode2 = svg.selectAll('.subnode2')
              .data(nodes)
              .enter().append('circle')
              .attr('class', 'subnode2');


force.on('end', function() {
   node.attr("x", function(d) { return d.x; })
       .attr("y", function(d) { return d.y; })
       .attr("width", 50)
       .attr("height", 20);
   subnode.attr('r', width/250)
          .attr('cx', function(d) { return (d.x); })
          .attr('cy', function(d) { return d.y + 10; });

  subnode2.attr('r', width/250)
          .attr('cx', function(d) { return d.x+50; })
          .attr('cy', function(d) { return d.y + 10; });

  link.attr('x1', function(d) { return d.source.x; })
      .attr('y1', function(d) { return d.source.y+ 10; })
      .attr('x2', function(d) { return d.target.x+50; })
      .attr('y2', function(d) { return d.target.y+ 10; });

});

force.start();
var line;
function mousedown() {
    var m = d3.mouse(this);
  //alert(m[0]+"---"+m[1]);
    line = svg.append("line")
        .attr('x1', m[0])
        .attr('y1', m[1])
        .attr('x2', m[0])
        .attr('y2', m[1]);

    svg.on("mousemove", mousemove);
}

function mousemove() {

    var m = d3.mouse(this);
    line.attr('x2', m[0])
        .attr('y2', m[1]);
}

function mouseup() {
    svg.on("mousemove", null);
}
    </script>
</body>
</html>

上述解决方案会产生以下结果:
问题是我不明白为什么图是反向绘制的,而且在上面的代码中,我已经注释掉了一些节点和链接,如果您取消对它们的注释,则会有更多混乱,整个节点将以完全随机的顺序绘制,即增加更多节点和链接会导致更多混乱。
请查看JSBIN:http://jsbin.com/yuyolof/edit?html

请查看此链接 http://jsbin.com/bihosuvobi/edit?html,output 我稍微更改了节点以理解问题,节点在其相应的x和y定义处绘制,并遵循调整x和y的tick函数。对我来说,一切似乎都连接得很好(根据您提供的链接数据)。如果您需要静态图表,可能强制作用并不适合您的情况,或者您应该通过调整节点电荷、链接距离和alpha值来进行一些尝试。 - mkaran
我已经在每个节点和链接上贴了一些标签,以尝试澄清节点是如何连接和创建的。http://jsbin.com/kohiqohahu/1/edit?html,output 希望这可以帮到你! - mkaran
更改链接距离:http://jsbin.com/pexifosoqa/1/edit?: html,console,output - mkaran
@mkaran 在图表中,链接被绘制在错误的子节点之间,或者说它是可见的。我希望左侧节点(矩形)的右子节点(圆形)连接到左侧节点(矩形)的左子节点(圆形)。请参见图像https://i.imgsafe.org/34a92f3c64.png,其中连接了错误的子节点。 - Srinivas Gadilli
哦,现在我明白你的意思了。谢谢! - mkaran
1个回答

1

请查看这个jsbin http://jsbin.com/himutohimu/1/edit?html,css,output(我添加了一些额外信息以便更好地了解正在发生的情况)

您有两个具有相同节点数据的子节点。您正在将它们定位在“end”位置,如下所示:

   subnode.attr('r', width/250) // black nodes
          .attr('cx', function(d) { return d.x; })
          .attr('cy', function(d) { return d.y + 10; });

   subnode2.attr('r', width/250) // red nodes
          .attr('cx', function(d) { return d.x + 50; })
          .attr('cy', function(d) { return d.y + 10; });

我已经将节点着色以更好地理解其工作原理。
为了让你的线连接到一种子节点,你需要按照黑色节点或红色节点的x和y坐标进行连接:
  // x1 and y1 are the starting point of the line, so in order to follow the 
  // red nodes, we need to move accordingly with +50 for x and +10 for y.
  // the same goes for x2, y2 which are the coordinates for the end of the line
  link.attr('x1', function(d) { return d.source.x + 50; })
      .attr('y1', function(d) { return d.source.y + 10; })
      .attr('x2', function(d) { return d.target.x + 50; })
      .attr('y2', function(d) { return d.target.y + 10; });

 //Or if you need your lines to follow the black nodes/ dots then x1, y1 
 // and x2,y2 need to move accordingly to your subnode's x and y, 
 // so x as it is and y plus 10
 // it is one or the other
 link.attr('x1', function(d) { return d.source.x; })
     .attr('y1', function(d) { return d.source.y + 10; })
     .attr('x2', function(d) { return d.target.x; })
     .attr('y2', function(d) { return d.target.y + 10; });

所以,问题在于您想连接哪些节点(点),然后根据它们各自的x和y移动线条。
希望这可以帮助您!
祝你好运!
编辑:如何在更多节点上使用此功能:http://jsbin.com/nodaruwere/1/edit?html,output

我期望看到我问题中发布的图像的镜像。更像是左侧矩形的红点连接到右侧那些黑点上。 - Srinivas Gadilli
我的目标是创建类似于这个的东西:http://imgur.com/Wqgo96C。我的方法正确吗? - Srinivas Gadilli
1
喜欢jsplumb吗?我认为d3可能不是最合适的工具。或者至少不是力学布局。看一下这个:https://dev59.com/pWEh5IYBdhLWcg3wnEcc#35441959,也许还有这个https://bl.ocks.org/cjrd/6863459。您还可以尝试根据更靠近您想连接的点的点来定位线条的x和y,例如这样的内容http://jsbin.com/lomijusaxo/1/edit?html,output - mkaran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接