Остановите перемещение других узлов при перетаскивании одного узла в 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);