首页 > 解决方案 > 避免长网络中的缠结,D3 力图

问题描述

我正在使用 D3 力图并试图找到一种方法使网络更加“线性”并在网络生成时避免“缠结”,尤其是在长网络上。

缠结的例子

缠结的例子

没有缠结,更好但不理想

没有缠结,更好

理想的结果,网络从左到右 理想,从左到右

不起作用的解决方案:

我在 VizHub 上构建的示例文件很简单,虽然增加收费似乎适用于小型网络,但即使收费非常高,20-50 个项目也会缠结。

我试图根据网络的已知“粗略”等级顺序来播种节点起始位置的位置。但是,on(tick) 操作会立即忽略并覆盖它。我可能做错了什么,可能需要在代码中的不同点进行播种,但我找不到很好的示例或文档。

我还尝试锚定了一些点(不太理想),但链接忽略了种子节点的位置。同样,很可能我做得不对,这可能是我的问题,但我也找不到锚定的好例子。

 node.attr("transform", function (d) {  
        return "translate(" + d.x_seed + "," + d.y_seed + ")";})

在 on("tick",...) 禁用时播种

在此处输入图像描述

我最迟只能使用 D3 版本 3.5.17,所以我不能使用一些更现代的强制工具(如 forceY)来帮助“扁平化”网络。

关于获得“理想”结果的好方法的任何想法?播种,锚定,还是别的?

标签: d3.js

解决方案


我已经部分回答了我的问题。这些现在已集成到VizHub示例中。

如何播种加载位置。

  for (var i = 0; i < nodesData.length; i++){
    var t = nodesData[i];
    var x_seed = t.rank*width/totalNodes
    t.x_seed = x_seed;
    t.x = x_seed;
    var y_seed = var y_seed = height/2 + Math.random()*height/20 - height/40; // randomize y starting location a little to prevent nodes getting stuck in line
    t.y_seed = y_seed;
    t.y = y_seed;
  }

锚定第一个、最后一个和中间节点:

force.on("tick", function () {
      link
        .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;});
      node
        .attr("transform", function (d) {
            if(d.rank == totalNodes || d.rank == 1 || d.rank == Math.floor(totalNodes/2)){
              d.x = d.x_seed
                  d.y = d.y_seed
            }
            return "translate(" + d.x + "," + d.y + ")";
      });
   });


推荐阅读