2012-05-01 19 views
56

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

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 tratado de establecer manualmente x del nodo y atributos Y ACT-tick, pero entonces los enlaces continuará flotando a donde el nodo sería si fue afectado por la fuerza.

Obviamente, tengo un malentendido básico sobre cómo se supone que funciona esto, así que podría alguien señalarme un ejemplo donde 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 de la fuerza como dirigido, y todos los enlaces siguen funcionando?

Respuesta

69

Establezca d.fixed en los nodos deseados en verdadero e inicialice d.x y d.y en la posición deseada. Estos nodos seguirán formando 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 force layout para obtener más detalles, y también vea cómo el nodo raíz se coloca en this example.

8

nodos d3v4 fijas en el diseño fuerza

En d3v3 d.fixed fijará nodos en d.x y d.y; sin embargo, en d3v4 este método ya no es compatible. Los d3v4 documentation estados:

para fijar un nodo en una posición dada, se puede especificar dos propiedades adicionales:

fx - the node’s fixed x-position

fy - the node’s fixed y-position

Al final de cada garrapata, después de la aplicación de cualquier fuerza, un nodo con un node.fx definido tiene node.x restablecer a este valor y node.vx establecer a cero; Del mismo modo, un nodo con un node.fy definido tiene node.y restablecer a este valor y node.vy establecer en cero. Para desactivar un nodo que fue previamente corregido, configure node.fx y node.fy para anular, o elimine estas propiedades .

Puede establecer fx y fy atributos de los nodos de la fuerza en el origen de datos, o puede agregar y quitar fx y fy valores de forma dinámica. El fragmento a continuación establece estas propiedades al final de los eventos de arrastre, arrastre un nodo para fijar 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); 
 

 
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.x = d3.event.x; 
 
    d.y = 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>

Cuestiones relacionadas