在强制布局 D3.js 中保持节点之间的动态链接距离

Maintain a dynamic link distance among nodes in force layout D3.js

本文关键字:之间 节点 动态 距离 链接 布局 D3 js      更新时间:2023-09-26

我正在解析json字符串中每个链接的链接距离。

 {
  "nodes" : [ {
    "name" : "cricket",
    "category" : "main",
    "id" : 0
  }, {
    "name" : "record1",
    "category" : "twitter",
    "id" : 1
  }, {
    "name" : "record2",
    "category" : "web",
    "id" : 2
  }],
  "links" : [ {
    "source" : 0,
    "target" : 1,
    "linkDistance" : 13.17538
  }, {
    "source" : 0,
    "target" : 2,
    "linkDistance" : 13.17538
  } ]
}

在javascript中,链接距离是一个函数。

var force = d3.layout.force()
     .gravity(0.3)
     .charge(0)
     .size([width,height])
     .nodes(jsonstring.nodes)
     .links(jsonstring.links)
     .linkDistance(function (d) {
           return d.linkDistance;
     })
     .start();

但是节点没有在给定的链接距离内绘制。电荷值为 0。有没有人知道在通过 json 解析时如何保持动态链接距离?

每次编辑d.linkDistance时,都需要再次调用

force.linkDistance(function (d) {
       return d.linkDistance;
 })

以使修改生效。

还要记住,链接距离在d3中只是非常弱的强制,因此根据我的经验,编辑链接距离无论如何都不会对图形布局产生很大影响。您始终可以尝试使用force.linkStrength(10)或更高的值来增加距离的重要性,但这可能不足以获得精确的正确值。


要尝试的东西:

  • 找到图形的生成树(这给出了一个边的列表,即"骨架"st

  • 运行以下命令以强制边缘长度正确:

    force.on('tick', function() {
       //consider all edges of a spanning tree, from root to leaves
       //using links directly instead of st would yield strange results, but depending on your data it might work well enough
       st.forEach(function(d) {
           //compute link coordinates  
           var dx = d.target.x - d.source.x; 
           var dy = d.target.y - d.source.y;
           //ratio desired length / actual length
           var r = d.linkDistance / Math.sqrt(dx*dx+dy*dy) 
           //add r=Math.sqrt(r) for something smoother (but less constrained)
           //move target to desired length
           d.target.x = d.source.x + dx * r; 
           d.target.y = d.source.y + dy * r;
       })
    })
    

它会严重降低力布局的自然流动(也许r=Math.sqrt(r)会少一点,但仍然如此),如果你使用它,它会弄乱节点拖动,但它应该在可能的情况下强制一些弧长。