D3.js d3力-节点被从链接中拖走,而不是运行
我需要制作一个具有可拖动功能的“粘滞力布局”,并尝试复制Mike Bostock at的示例。因为作者在D3V3中编写了这个程序,所以我必须将他的代码“升级”到D3v4。这意味着d3 force和d3 drag语句必须相应地更改。虽然原始示例中的逻辑流程很容易理解,但我仍然无法制作自己的版本(请参阅下面的代码)。问题:经过一定时间(2-3秒)后,节点会被拖走,但链接不会更新 我最初的想法是集中在拖动函数(.call(drag)),但后来我发现“tick”函数在上述时间之后不再运行(我是通过在tick函数中放入一个count变量获得的,然后是console.log)。到目前为止,我的头脑是空的,无法进一步探索 问题在哪里D3.js d3力-节点被从链接中拖走,而不是运行,d3.js,drag-and-drop,drag,d3-force-directed,D3.js,Drag And Drop,Drag,D3 Force Directed,我需要制作一个具有可拖动功能的“粘滞力布局”,并尝试复制Mike Bostock at的示例。因为作者在D3V3中编写了这个程序,所以我必须将他的代码“升级”到D3v4。这意味着d3 force和d3 drag语句必须相应地更改。虽然原始示例中的逻辑流程很容易理解,但我仍然无法制作自己的版本(请参阅下面的代码)。问题:经过一定时间(2-3秒)后,节点会被拖走,但链接不会更新 我最初的想法是集中在拖动函数(.call(drag)),但后来我发现“tick”函数在上述时间之后不再运行(我是通过在ti
var width = 960,
height = 500;
var simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody().strength(-100))
d3.forceX(width)
d3.forceY(height)
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var drag = d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
var link = svg.selectAll(".link")
var node = svg.selectAll(".node")
d3.json("graph.json", function (error, graph) {
if (error) throw error;
simulation.nodes(graph.nodes)
.force("link", d3.forceLink(graph.links))
.on("tick", tick);
link = link.data(graph.links)
.enter().append("line")
.attr("class", "link");
node = node.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 12)
.on("dblclick", dblclick)
.call(drag)
});
var count = 0;
function tick() {
count++;
console.log(count);
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("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; })
}
function dblclick(d) {
d3.select(this).classed("fixed", d.fixed = false);
// console.log("Is clicking");
}
function dragstarted(d) {
d3.select(this).classed("fixed", d.fixed = true);
console.log("Is dragging");
}
function dragged(d) {
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("active", false);
}
有两个因素导致此力定向图出现问题:
d.fixed
来修复节点d.fx
和d.fy
手动固定坐标的x和y值d.fixed
不再修复节点。对于您的代码,这将类似于:
function dragended(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
及
2:设置alpha衰减
这将导致图形冻结。在图形由于alpha衰减而稳定后,不再调用tick函数。此时,将在不更新链接的情况下进行拖动,从而导致节点和链接之间的连接断开
在d3v3中,默认情况下未定义阿尔法衰减,d3可能会返回到一个不计算阿尔法衰减或使用零作为阿尔法衰减因子(两者都会产生相同的结果)。在d3v4中,α衰减设置为非零值:
如果指定了“衰减”,则将alpha衰减率设置为指定值
数值在[0,1]范围内,并返回此模拟。如果衰变不是
指定时,返回当前alpha衰减率,,默认为
0.0228…=1-功率(0.001,1/300),其中0.001是默认的最小α
alpha衰减速率决定当前alpha的衰减速度
向所需目标α插值;自违约以来
目标alpha为零,默认情况下,此选项控制
模拟冷却。较高的衰减速率会使模拟趋于稳定
更快,但有陷入局部最小值的风险;低值
使模拟运行时间更长,但通常会收敛到
更好的布局使模拟永远以当前速度运行
alpha,将衰减率设置为零或者,设置目标alpha
大于最小alpha
因此,您可以使用:
var simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody().strength(-100))
.alphaDecay(0);
(或者,将alphaTarget设置为上面引用的文档中所述的适当值)
总而言之,这看起来像是。谢谢你启发我,安德鲁。从您的回答中,我了解了两点:(1)alpha衰减控制模拟冷却的速度,(2)衰减率为零时,模拟将永远以当前alpha(=默认值为0.0228)运行。
var simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody().strength(-100))
.alphaDecay(0);