Исправить положение узла в компоновке, направленной на усилие D3
Я хочу, чтобы некоторые узлы в моем силовом макете игнорировали силу и оставались в фиксированных положениях на основе атрибута узла, при этом все еще можно перетаскивать и оказывать отталкивание на другие узлы и поддерживать их линии связи. Я думал, что это будет так просто:
force.on("tick", function() {
vis.selectAll("g.node")
.attr("transform", function(d) {
return (d.someAttribute == true) ?
"translate(" + d.xcoordFromAttribute + "," + d.ycoordFromAttribute +")" :
"translate(" + d.x + "," + d.y + ")"
});
});
Я также попытался вручную установить атрибуты X и y узла на галочку, но затем ссылки продолжают всплывать туда, где узел был бы, если бы он был затронут сила.
очевидно, у меня есть основное непонимание того, как это должно работать, поэтому может ли кто-нибудь указать мне на пример, где некоторые узлы зафиксированы в своем положении (но все еще перетаскиваются), а остальные узлы плавают вокруг направленного на силу, и все ссылки все еще работают?
2 ответа:
Set
d.fixed
на нужных узлах в true, и инициализироватьd.x
иd.y
в нужное положение. Затем эти узлы все еще будут частью моделирования, и вы можете использовать обычный код отображения (например, установить атрибут преобразования); однако, поскольку они помечены как фиксированные, их можно перемещать только перетаскиванием, а не симуляцией.посмотреть разметки документация для получения более подробной информации, а также посмотреть, как корневой узел расположен в .
исправлены узлы в макете force для d3v4 и d4v5
в d3v3
d.fixed
исправит узлы вd.x
иd.y
; однако в d3v4/5 Этот метод больше не поддерживается. Элемент документация d3 гласит:для фиксации узла в заданном положении можно указать два дополнительных свойства:
fx - the node’s fixed x-position
fy - the node’s fixed y-position
в конце каждого тика, после применения любых сил, узел с определенным узлом.FX имеет узел.X сброс к этому значению и узлу.комплект vx к нулю; аналогично, узел с определенным узлом.FY имеет узел.г сброс это значение и узел.вы равным нулю. Чтобы открепить узел, который был ранее исправленный, установленный узел.fx и узел.FY к нулю, или удалите их свойства.
вы можете установить
fx
иfy
атрибуты для узлов force в источнике данных, или вы можете добавлять и удалятьfx
иfy
динамически значения. Этот фрагмент ниже устанавливает эти свойства в конце событий перетаскивания, просто перетащите узел, чтобы исправить его положение:var data ={ "nodes": [{"id": "A"},{"id": "B"},{"id": "C"},{"id":"D"}], "links": [{"source": "A", "target": "B"}, {"source": "B", "target": "C"}, {"source": "C", "target": "A"}, {"source": "D", "target": "A"}] } var height = 250; var width = 400; var svg = d3.select("body").append("svg") .attr("width",width) .attr("height",height); var simulation = d3.forceSimulation() .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(50)) .force("charge", d3.forceManyBody()) .force("center", d3.forceCenter(width / 2, height / 2)); var link = svg.append("g") .selectAll("line") .data(data.links) .enter().append("line") .attr("stroke","black"); var node = svg.append("g") .selectAll("circle") .data(data.nodes) .enter().append("circle") .attr("r", 5) .call(d3.drag() .on("drag", dragged) .on("end", dragended)); simulation .nodes(data.nodes) .on("tick", ticked) .alphaDecay(0); simulation.force("link") .links(data.links); function ticked() { 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 dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { d.fx = d3.event.x; d.fy = d3.event.y; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.min.js"></script>