考虑任何d3力导向动画,例如:
http://bl.ocks.org/mbostock/1062288
加载该图表,让节点稳定下来,使它们不移动。将鼠标悬停在橙色节点上,让鼠标静止。点击,不做任何其他事情。您将看到所有节点向内移动一点,然后再扩展回正常。
我不喜欢那种不必要的动作,我需要将其移除。
我认为这与图表重新加热" (见https://github.com/mbostock/d3/wiki/Force-Layout ),将alpha参数设置为0.1。具体来说,我发现在以下任何一种情况发生后会立即发生不必要的移动。
force.drag()
被召唤。究竟是什么导致了这种"不必要的运动",以及如何禁用它? (不禁用节点拖动)
答案 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);
};