Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
D3.js d3力-节点被从链接中拖走,而不是运行_D3.js_Drag And Drop_Drag_D3 Force Directed - Fatal编程技术网

D3.js d3力-节点被从链接中拖走,而不是运行

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

我需要制作一个具有可拖动功能的“粘滞力布局”,并尝试复制Mike Bostock at的示例。因为作者在D3V3中编写了这个程序,所以我必须将他的代码“升级”到D3v4。这意味着d3 force和d3 drag语句必须相应地更改。虽然原始示例中的逻辑流程很容易理解,但我仍然无法制作自己的版本(请参阅下面的代码)。问题:经过一定时间(2-3秒)后,节点会被拖走,但链接不会更新

我最初的想法是集中在拖动函数(.call(drag)),但后来我发现“tick”函数在上述时间之后不再运行(我是通过在tick函数中放入一个count变量获得的,然后是console.log)。到目前为止,我的头脑是空的,无法进一步探索

问题在哪里

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);
}

有两个因素导致此力定向图出现问题:

  • d3v4不使用
    d.fixed
    来修复节点
  • d3v4没有与d3v3相同的默认alpha衰减
  • 1:固定节点

    虽然您没有明确注意到这一点,但在2-3秒内,图形会更新链接数据,拖动后节点仍会移动

    这是因为,与d3v3相反,您需要使用
    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);