修改 d3 的力布局“退火”时间表

Posted

技术标签:

【中文标题】修改 d3 的力布局“退火”时间表【英文标题】:modifying d3's force layout "annealling" schedule 【发布时间】:2014-12-25 15:04:56 【问题描述】:

我有一个 d3 力布局图,即工作得很好,但它经常过早地“卡住”。例如,节点正在朝着一个好的位置摇晃,如果“碰撞”它们(向它们的位置注入一点随机性并再次start(),它们最终到达那里。如果我减少friction,问题也会变得更糟,因为用户觉得太疯狂了。

我看到force.js source code 中提到了“退火”(ala 模拟退火),而暴露的alpha 参数是一个关键因素。我想知道是否有人想出如何直接管理一般退火计划(无需修补force.js!)?

【问题讨论】:

不确定我是否理解您的问题。修改任何未公开的内容都需要更改源代码。 如果图表太大或毛茸茸而无法一次很好地布局,我可能会尝试随着时间的推移添加节点并在每次添加时重新开始布局。如果有一个逻辑,比如节点的时间或类型组件,那就更好了。 @Lars,对不起,我不清楚。 alpha 似乎是唯一暴露的参数,但我只能用它做这么多。我在问是否有某种方法可以以 d3-ic 方式完成更一般的冷却计划,还是我需要做一个本地补丁? @Andrew,我希望这是一个由用户修改的图形可视化工具,在一个固定的图形上。 @rikb force.alpha() 方法允许您将 alpha 设置为您想要的任何值,因此您可以尝试从 "tick" 处理程序中调整它。在您链接到的源代码的第 60 行,alpha 得到如下调整:alpha *= .99(直到它降低到 0.005 以下)。因此,从理论上讲,如果您在每个刻度上设置alpha *= 1/.995,布局将需要大约两倍的时间来解决。也许…… 嗨@meetamit。对,我的tick() 函数中有一个myAlpha *= annealDecay; force.alpha( myAlpha ); hack,它对一些人有帮助。我还在重新启动之前向节点位置添加噪音,... 【参考方案1】:

答案的核心是@meetamit 的评论(加速alpha 的衰减)。您还可以在布局低于阈值时停止调用布局,还可以通过向节点/链接移动添加过渡来处理“抖动”。

animationStep = 200;
force.on('tick', function() 
    node.transition().ease('linear').duration(animationStep)
        .attr('transform', function(d)  
             //your node transitions here 
        );
    var alpha = force.alpha();
    force.stop();
    setTimeout(function() 
      if (!alpha > 0.001) 
        force.alpha(alpha * 0.9);
      
    , animationStep);
  ;
  force.on('tick', tick);

【讨论】:

我认为 OP 实际上正在寻找一种 减速 的方法,但无论如何,管理 alpha 的最简单方法是将 force.alpha(force.alpha()/0.99*myDecay) 放在 @ 的末尾987654323@回调。这会反转布局应用的衰减(即 0.99),并用您自己的几何衰减率替换它。

以上是关于修改 d3 的力布局“退火”时间表的主要内容,如果未能解决你的问题,请参考以下文章

修复 D3 强制定向布局中的节点位置

D3.js 网络图使用力导向布局和矩形节点

解释 d3 定心力

基于模拟退火的FPGA布局方法

D3树垂直分离

有没有办法放大 D3 力布局图?