d3力导向布局在重新加热时扩展

时间:2015-09-01 01:57:56

标签: javascript d3.js

考虑任何d3力导向动画,例如:

http://bl.ocks.org/mbostock/1062288

加载该图表,让节点稳定下来,使它们不移动。将鼠标悬停在橙色节点上,让鼠标静止。点击,不做任何其他事情。您将看到所有节点向内移动一点,然后再扩展回正常。

我不喜欢那种不必要的动作,我需要将其移除。

我认为这与图表重新加热" (见https://github.com/mbostock/d3/wiki/Force-Layout ),将alpha参数设置为0.1。具体来说,我发现在以下任何一种情况发生后会立即发生不必要的移动。

  1. 将新节点添加到图表
  2. 从图表中删除节点
  3. force.drag()被召唤。
  4. 究竟是什么导致了这种"不必要的运动",以及如何禁用它? (不禁用节点拖动)

3 个答案:

答案 0 :(得分:3)

行为主要来自alpha。 d3中的alpha函数:

force.alpha = function(x) {
  if (!arguments.length) return alpha;
  x = +x;
  if (alpha) {
    if (x > 0) alpha = x; else alpha = 0;
  } else if (x > 0) {
    event.start({
      type: "start",
      alpha: alpha = x
    });
    d3.timer(force.tick);
  }
  return force;
};

因此,当调用alpha时,如果大于0

,它将启动tick事件

在tick事件中,在开始时,您可以看到导致“冻结”的截止事件。你提到过:

if ((alpha *= .99) < .0005) {
         event.end({
           type: "end",
           alpha: alpha = 0
         });
         return true;
       }

现在,如果我们看一下dragmove,它会调用resume函数:

function dragmove(d) {
      d.px = d3.event.x, d.py = d3.event.y;
      force.resume();
    } 

使用值0.1:

调用alpha函数
 force.resume = function() {
      return force.alpha(.1);
    };

要停止跳跃以及冻结0.0005,我不会发现自己可以使用任何公共功能。

我有一个示例fiddle,它从tick函数中删除了导致冻结的代码,并且还将resume函数更改为以较小的alpha开始。

我相信这会给你想要的结果,但当然,我不建议你自定义库。

也许有人知道如何覆盖tick函数而不必修改源代码。

答案 1 :(得分:0)

in

// Toggle children on click.
function click(d) {
  if (!d3.event.defaultPrevented) {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    update();
  }
}

您可以将更新移至仅打开的子项

// Toggle children on click.
function click(d) {
  if (!d3.event.defaultPrevented) {
    if (d.children) {
      d._children = d.children;
      d.children = null;
      update();
    } else {
      d.children = d._children;
      d._children = null;
    }

  }
}

所以没有子节点(橙色)的节点不会在点击时更新。

答案 2 :(得分:0)

通常,当force.resume()被触发时,alpha值会从0跳到0.1。通过更慢地缓解alpha,我们可以掩盖“不必要的运动”。

我仍然对其他想法和解决方案持开放态度。

旧功能:

force.resume = function() {
  return force.alpha(.1);
};

替换功能:

force.resume = function() {
  var alpha = force.alpha()
  if( alpha < 0.005 ){ alpha = 0.0055 }
  else if( alpha < 0.11 ){ alpha += 0.0006 }
  return force.alpha(alpha);
};