javascript d3.js transform force-layout

javascript - Reparar la posición del nodo en D3 Diseño orientado a la fuerza



d3.js transform (2)

Quiero que algunos de los nodos en mi diseño dirigido por la fuerza ignoren la fuerza y ​​permanezcan en posiciones fijas basadas en el atributo del nodo, mientras que aún se pueden arrastrar y ejercer repulsión en otros nodos y mantener sus líneas de enlace. Pensé que sería tan simple como esto:

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

También he intentado configurar manualmente los atributos x e y del nodo on-tick, pero luego los enlaces continúan flotando hacia donde estaría el nodo si fuera afectado por la fuerza.

Obviamente tengo un malentendido básico sobre cómo se supone que funciona esto, así que alguien podría señalarme un ejemplo en el que algunos nodos están fijos en su posición (pero aún se pueden arrastrar) y el resto de los nodos están flotando alrededor del estilo de la fuerza, y todos los enlaces siguen funcionando?


Establezca d.fixed en los nodos deseados en verdadero e inicialice dx y dy en la posición deseada. Estos nodos seguirán siendo parte de la simulación, y puede usar el código de visualización normal (por ejemplo, establecer un atributo de transformación); sin embargo, como están marcados como fijos, solo se pueden mover arrastrando y no mediante la simulación.

Consulte la documentación de diseño de fuerza para obtener más detalles y también vea cómo se posiciona el nodo raíz en este ejemplo .


Se corrigió el diseño de los nodos en vigor para d3v4 y d4v5

En d3v3 d.fixed arreglará los nodos en dx y dy ; sin embargo, en d3v4 / 5 este método ya no es compatible. La documentación de d3 establece:

Para arreglar un nodo en una posición determinada, puede especificar dos propiedades adicionales:

fx - the node''s fixed x-position

fy - the node''s fixed y-position

Al final de cada tic, después de la aplicación de cualquier fuerza, un nodo con un node.fx definido tiene reinicio node.x a este valor y node.vx establecido a cero; del mismo modo, un nodo con un node.fy definido tiene node.y restablecer a este valor y node.vy establecer a cero. Para deshacer la fijación de un nodo que se haya solucionado anteriormente, establezca node.fx y node.fy como null, o elimine estas propiedades.

Puede establecer los atributos fx y fy para los nodos de fuerza en su fuente de datos, o puede agregar y eliminar dinámicamente valores fx y fy . El siguiente fragmento establece estas propiedades al final de los eventos de arrastre, simplemente arrastre un nodo para corregir su posición:

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("start", dragstarted) .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 dragstarted(d) { d.fx = null; d.fy = null; } 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>