Остановите перемещение других узлов при перетаскивании одного узла в D3 forceSimulation

Я сделал D3 принудительно ориентированный граф d3.forceSimulation() и прикрепил функцию перетаскивания. При нажатии на один узел я не хочу, чтобы другие узлы двигались соответственно. Теперь я могу остановить перетаскиваемый узел, установив d.fx а также d.fy в дальнейшем:

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

Можно ли заморозить все остальные узлы при перетаскивании одного узла?

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/

Вот решение, которое позволяет гибко манипулировать силами моделирования во время перетаскивания:

      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(), когда перетаскивание начинается и заканчивается соответственно. (Адаптировано из этого наблюдаемого )

      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);
Другие вопросы по тегам