1

我是 d3.js 的新手。我试图创建一个具有 5 个节点的静态架构,并根据偏好将它们相互链接,节点应该像这样组织:

在此处输入图像描述

一开始我设置节点的位置,然后创建链接。但是,当节点链接时,架构会发生变化,结果如下所示:

在此处输入图像描述

这是我的代码:

    var width = 640,
        height = 400;


    var nodes = [
              { x:   60, y: 0, id: 0},
              { x:   150, y: height/4, id: 1},
              { x:   220, y: height/4, id: 2},
              { x:   340, y: height/4, id: 3},
              { x:   420, y: height/2, id: 4},
              { x:   480, y: height/2, id: 5}
    ];

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

    var graph = d3.select('#graph');

    var svg = graph.append('svg')
                   .attr('width', width)
                   .attr('height', height);

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

    force.linkDistance(width/2);

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

     var div = d3.select("body").append("div")
                 .attr("class", "tooltip")
                 .style("opacity", 1e-6);

      var node = svg.selectAll('.node')
              .data(nodes)
              .enter().append("circle")
              .attr("cx", d=> d.x)
              .attr("cy", d=> d.y)
              .attr('class', 'node')
              .on("mouseover", function(d){ 
                              d3.select(this)
                                  .transition()
                                  .duration(500)
                                  .style("cursor", "pointer")
                                  div
                                    .transition()  
                                    .duration(300)
                                    .style("opacity", "1")                           
                                    .style("display", "block")  
                                    console.log("label", d.label);
                                  div
                                    .html("IP: " +  d.label + " x: " + d.x + " y: " + d.y)
                                    .style("left", (d3.event.pageX ) + "px")
                                    .style("top", (d3.event.pageY) + "px");

                                })
              .on("mouseout", mouseout);


       function mouseout() {
          div.transition()
             .duration(300)
             .style("opacity", "0")
        }

       console.log("wait...");
       force.on('end', function() {

             node.attr('r', width/25)
                 .attr('cx', function(d) { return d.x; })
                 .attr('cy', function(d) { return d.y; });

             link.attr('x1', function(d) { console.log("LINE x1-> ", d.source.x); return d.source.x; })
                 .attr('y1', function(d) { console.log("LINE y1-> ", d.source.y); return d.source.y; })
                 .attr('x2', function(d) { console.log("LINE x2-> ", d.source.x); return d.target.x; })
                 .attr('y2', function(d) { console.log("LINE y2-> ", d.source.y); return d.target.y; })
                 .attr("stroke-width", 2)
                 .attr("stroke","black");
       });

       force.start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="graph"></div>

请你帮助我好吗?先感谢您。

4

1 回答 1

1

力布局提供了一些优势,这些优势源于其作为自组织布局的性质:

  • 它自动放置节点和链接,避免手动定位潜在的数千个元素
  • 它根据分配的力将节点和链接组织到理想的间距和布局

您有分配位置的节点,上面列出的两个优点不适用。您已经手动完成了第一项,第二项会干扰并覆盖您手动设置的位置。

我们可以固定节点位置,但是如果我们对所有节点都这样做,它就违背了力布局的目的:通过模拟力来定位节点。

相反,如果您有所有节点的位置,我们可以跳过强制并根据数据附加所有内容。下面的代码片段首先放置链接(因此它们位于节点后面),使用包含在d.source/中的索引d.target来访问nodes数组中的特定节点并获取适当的 x 或 y 坐标。节点正常定位。

尽管屏幕截图使用了图像(正如您在上一个问题中使用的那样),但您似乎已经调整了代码以在您的问题中使用圆圈,我将在这里只使用圆圈。根据您给出的坐标,一些线重叠。我修改了第一个节点,使 y 值不为 0(这会将半个圆推离 svg)

var width = 640,
    height = 400;
    
var nodes = [
          { x:   60, y: height/8, id: 0},
          { x:   150, y: height/4, id: 1},
          { x:   220, y: height/4, id: 2},
          { x:   340, y: height/4, id: 3},
          { x:   420, y: height/2, id: 4},
          { x:   480, y: height/2, id: 5}
];

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

var graph = d3.select('#graph');

var svg = graph.append('svg')
               .attr('width', width)
               .attr('height', height);
       
// append links:
svg.selectAll()
  .data(links)
  .enter()
  .append("line")
  .attr("x1", function(d) { return nodes[d.source].x; })
  .attr("y1", function(d) { return nodes[d.source].y; })
  .attr("x2", function(d) { return nodes[d.target].x; })
  .attr("y2", function(d) { return nodes[d.target].y; })
  .attr("stroke-width", 2)
  .attr("stroke","black");
  
// append nodes:
svg.selectAll()
  .data(nodes)
  .enter()
  .append("circle")
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; })
  .attr("r", 8);
  
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="graph"></div>

于 2018-07-07T19:24:56.660 回答