2012-07-23 11 views
12

Estoy cargando json de la base de datos y creando un archivo json que carga bien. Ahora no sé qué pasos dar para hacer que los nodos respondan en un gráfico dirigido por la fuerza. Necesito eliminar y agregar nuevos nodos y sus enlaces.Adición y eliminación de nodos en D3js Force Graph

force.nodes(json.nodes) 
    .links(json.links) 
    .start(); 

initNodes(json); 

¿Cómo puedo hacer esto más dinámico o actualizarlo sin restablecer toda la visualización?

He visto esta pregunta un par de veces sin respuesta, así que espero que alguien pueda publicar y dar una guía.

Respuesta

7

Se puede ver un ejemplo de cómo añadir nuevos nodos y relaciones aquí: http://bl.ocks.org/2432083

Deshacerse de nodos y las relaciones es un poco más complicado, pero se puede ver el proceso aquí: http://bl.ocks.org/1095795

+2

gracias pero yo esperaba que alguien pueda describir el proceso también – BlitzCrank

+0

La parte importante es guardar el valor devuelto por el método .data en var (por ejemplo, x) y llamar a x.exit(). remove() al final del método. –

14

Adición los nodos/enlaces a mi gráfico de fuerza D3 fueron muy confusos hasta que entendí mejor cómo estaba agregando el conjunto inicial de nodos.

Suponiendo una <g> es lo que desea utilizar para sus nodos:

// Select the element where you'd like to create the force layout 
var el = d3.select("#svg"); 

// This should not select anything 
el.selectAll("g") 

// Because it's being compared to the data in force.nodes() 
    .data(force.nodes()) 

// Calling `.enter()` below returns the difference in nodes between 
// the current selection and force.nodes(). At this point, there are 
// no nodes in the selection, so `.enter()` should return 
// all of the nodes in force.nodes() 
    .enter() 

// Create the nodes 
    .append("g") 
    .attr("id", d.name) 
    .classed("manipulateYourNewNode", true); 

Ahora vamos a hacer que la función que va a añadir un nodo a la disposición una vez que el gráfico se ha inicializado!

newNodeData es un objeto con los datos que desea utilizar para su nuevo nodo. connectToMe es una cadena que contiene la identificación única de un nodo al que le gustaría conectar su nuevo nodo.

function createNode (newNodeData, connectToMe) { 
    force.nodes().push(newNodeData); 
    el.selectAll("g") 
     .data(force.nodes(), function(datum, index) { return index }) 

la función dada como el segundo argumento opcional en .data() se ejecuta una vez para cada nodo en la selección y otra vez para cada nodo en force.nodes(), igualando a ellos basado en el valor devuelto. Si no se proporciona ninguna función, se invoca una función de retorno, que devuelve el index (como se indicó anteriormente).

Sin embargo, es muy probable que haya una disputa entre el índice de su nueva selección (creo que la orden es aleatoria) y la orden en force.nodes(). En cambio, lo más probable es que necesite la función para devolver una propiedad que sea única para cada nodo.

Esta vez, .enter() solo devolverá el nodo que está tratando de agregar como newData porque no encontró ninguna clave para él con el segundo argumento de .data().

 .enter() 
     .insert("g", "#svg") 
     .attr("id", d.name) 
     .classed("manipulatYourNewNode", true); 

    createLink(connectToMe, newNodeData.name); 

    force.start(); 
} 

La función createLink (definida a continuación) crea un enlace entre su nuevo nodo y su nodo de elección.

Además, the d3js API states that force.start() should be called after updating the layout.

Nota: Calling force.stop() en el comienzo de mi función fue una gran ayuda para mí cuando yo estaba tratando de encontrar la manera de añadir nodos y enlaces a mi primera gráfica.

function createLink (from, to) { 
    var source = d3.select("g#" + from).datum(), 
     target = d3.select("g#" + to).datum(), 
     newLink = { 
      source: source, 
      target: target, 
      value: 1 
     }; 
    force.links().push(newLink); 

El código siguiente funciona bajo los supuestos de que:

  1. #links es el elemento contenedor que contiene todos los elementos de enlace
  2. Sus enlaces se representan como <line> elementos:

    d3.select("#links") 
        .selectAll("line") 
        .data(force.links()) 
        .enter() 
        .append("line"); 
    
Cuestiones relacionadas