2

我制作了一个 D3 强制有向图d3.forceSimulation()并附加了拖动功能。单击一个节点时,我不希望其他节点相应移动。d.fx现在我可以通过设置and来冻结被拖动的节点d.fy,如下所示:

function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = d.x;
    d.fy = d.y;
}

拖动一个节点时是否可以冻结所有其他节点?

4

2 回答 2

2

感谢@rioV8 的提示!我试图在拖动一个节点时修复其他节点。

node.call(d3.drag()
    .on('start', dragstarted)
    .on('drag', dragged)
    .on('end', dragended))

function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
    fix_nodes(d);
}

// Preventing other nodes from moving while dragging one node
function fix_nodes(this_node) {
    node.each(function(d){
        if (this_node != d){
            d.fx = d.x;
            d.fy = d.y;
        }
    });
}

演示在这里:https ://jsfiddle.net/casbie/21dvjcgn/

于 2019-02-01T02:25:27.337 回答
0

这是一个允许在拖动过程中灵活操纵模拟力的解决方案:

let tempForces = {};

const modifyForces = (simulation) => {
    tempForces = {};
    // For example, I want to temporarily remove the "link" and "charge" forces during dragging.
    (["link", "charge"]).forEach((forceName) => {
        tempForces[forceName] = simulation.force(forceName);
        simulation.force(forceName, null);
    });
    // You may modify your forces here. Store them to 'tempForces' if you'd like to restore them after dragging.
};

const restoreForces = (simulation) => {
    for (let [name, force] of Object.entries(tempForces)) {
        simulation.force(name, force);
    }
    tempForces = {};
};

然后分别在拖动开始和结束时调用 modifyForces() 和 restoreForces()。(改编自这个observable

const start = function(event) {
    modifyForces(simulation); // Modifying
    if (!event.active) {
        simulation.alphaTarget(0.1).restart();
    }
    event.subject.fx = event.subject.x;
    event.subject.fy = event.subject.y;
};

const drag = function (event) {
    event.subject.fx = event.x;
    event.subject.fy = event.y;
};

const end = function (event) {
    restoreForces(simulation); // Restoring
    if (!event.active) {
        simulation.alphaTarget(0);
    }
    event.subject.fx = null;
    event.subject.fy = null;
};

const dragBehavior = d3.drag()
    .on("start", start)
    .on("drag", drag)
    .on("end", end);

node.call(dragBehavior);
于 2022-01-07T10:52:10.887 回答