d3.js中的简单图形布局?

时间:2018-05-01 20:29:24

标签: javascript d3.js

我想用 d3.js 这样绘制一个简单的图表

enter image description here

我无法在v5 API文档和Internet上找到图形布局。

所有示例都使用d3-force中的d3.force布局。虽然它看起来令人印象深刻,但我并不是在寻找带有物理模拟的图形布局。

是否有更简单的布局,或者是关闭物理时使用d3.force布局的最佳方法?

1 个答案:

答案 0 :(得分:1)

没有必要使用d3.forceSimulation,这最终只是提供的众多D3布局中的一种。如果您查看Mike Bostocks示例Force Directed Graph,那么您需要的修改如下:

  1. 定义一组nodes - 基本上是一组代表圆圈的事物
  2. 使用svg:circle
  3. .data(nodes)元素附加到DOM
  4. 定义了一组links
  5. 使用svg:line
  6. .data(links)元素附加到DOM

    这主要是使用D3进行纯DOM数据绑定,而不使用预先构建的布局。

    你可以真正复制任何力量示例 - 它在下面做的只是在下方设置xy位置。如果你已经有了这些,只需将你的圈子定位在这些点上。

    您可以从示例中删除与simulationticked事件相关的所有部分。

    以下是提供静态布局的示例:

    
    
    var svg = d3.select("svg"),
      width = +svg.attr("width"),
      height = +svg.attr("height");
    
    var color = d3.scaleOrdinal(d3.schemeCategory20);
    
    const layout = (graph) => {
      return new Promise((resolve) => {
        var simulation = d3
          .forceSimulation()
          .alphaMin(0.3)
          .force("link", d3.forceLink().id(function(d) {
            return d.id;
          }))
          .force("charge", d3.forceManyBody())
          .force("center", d3.forceCenter(width / 2, height / 2))
          .on("end", resolve(graph));
    
        simulation.nodes(graph.nodes);
        simulation.force("link").links(graph.links);
      });
    };
    
    const render = (graph) => {
    
      var link = d3.select("#target").append("g")
        .attr("class", "links")
        .selectAll("line")
        .data(graph.links)
        .enter().append("line")
        .attr("stroke-width", function(d) { return Math.sqrt(d.value); })
        .attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });
    
      var node = d3.select("#target").append("g")
        .attr("class", "nodes")
        .selectAll("circle")
        .data(graph.nodes)
        .enter().append("circle")
        .attr("r", 5)
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; })
        .attr("fill", function(d) { return color(d.group); });
    }
    
    
    d3.json("https://gist.githubusercontent.com/mbostock/4062045/raw/5916d145c8c048a6e3086915a6be464467391c62/miserables.json", function(error, graph) {
      if (error) throw error;
     
      layout(graph)
         .then((graph) => render(graph));
    });
    
    .links line {
      stroke: #999;
      stroke-opacity: 0.6;
    }
    
    .nodes circle {
      stroke: #fff;
      stroke-width: 1.5px;
    }
    
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="960" height="600">
       <g id="target" transform="translate(480, 300)">
       </g>
    </svg>
    &#13;
    &#13;
    &#13;

    修改

    要更改节点之间的距离,您需要更改播放中的某些力。文档真的很好 - 特别是你要改变的是https://github.com/d3/d3-force#many-body

    因此,请将charge力量修改为:

    .force("charge", d3.forceManyBody().strength(-charge))
    

    你需要定义电荷,稍微调整一下,直到力量为你提供良好的布局。