2012-08-10 27 views
16

I tienen un ejemplo de código de trabajo (sólo la parte <script type="text/javascript">) de un gráfico estático usando d3.js como a continuación:Configure-diseño fijo gráfico estático en d3.js

 /* Create graph data */ 
     var nodes = []; 
     for (var i = 0; i < 13; i++) 
     { 
      var datum = { 
       "value": i 
      }; 
      nodes.push(datum); 
     } 

     var links = [{"source": 0, "target": 1}, 
        {"source": 1, "target": 2}, 
        {"source": 2, "target": 0}, 
        {"source": 1, "target": 3}, 
        {"source": 3, "target": 2}, 
        {"source": 3, "target": 4}, 
        {"source": 4, "target": 5}, 
        {"source": 5, "target": 6}, 
        {"source": 5, "target": 7}, 
        {"source": 6, "target": 7}, 
        {"source": 6, "target": 8}, 
        {"source": 7, "target": 8}, 
        {"source": 9, "target": 4}, 
        {"source": 9, "target": 11}, 
        {"source": 9, "target": 10}, 
        {"source": 10, "target": 11}, 
        {"source": 11, "target": 12}, 
        {"source": 12, "target": 10}]; 

     /* Create force graph */ 
     var w = 800; 
     var h = 500; 

     var size = nodes.length; 
     nodes.forEach(function(d, i) { d.x = d.y = w/size * i}); 

     var svg = d3.select("body").append("svg") 
        .attr("width", w) 
        .attr("weight", h); 

     var force = d3.layout.force() 
         .nodes(nodes) 
         .links(links) 
         .linkDistance(200) 
         .size([w, h]); 

     setTimeout(function() { 

      var n = 400 
      force.start(); 
      for (var i = n * n; i > 0; --i) force.tick(); 
      force.stop(); 

      svg.selectAll("line") 
       .data(links) 
       .enter().append("line") 
       .attr("class", "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; }); 

      svg.append("svg:g") 
       .selectAll("circle") 
       .data(nodes) 
       .enter().append("svg:circle") 
       .attr("class", "node") 
       .attr("cx", function(d) { return d.x; }) 
       .attr("cy", function(d) { return d.y; }) 
       .attr("r", 15); 

      svg.append("svg:g") 
       .selectAll("text") 
       .data(nodes) 
       .enter().append("svg:text") 
       .attr("class", "label") 
       .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) 
       .attr("text-anchor", "middle") 
       .attr("y", ".3em") 
       .text(function(d) { return d.value; }); 

     }, 10); 

y produce este lugar revueltos diseño:

enter image description here

Si bien es técnicamente correcta la gráfica, el diseño ideal debe ser algo como esto (haciendo caso omiso de los diferentes gráficos visuales):

enter image description here

Tenga en cuenta que la disposición debe ser fija para que la recarga de la página no cambie la posición de cada nodo; el diseño también debe ser estático, ya que no hay efecto de animación y los nodos no son arrastrables. Ambos requisitos ya se logran en el script anterior.

Entonces, ¿cómo debo configurar este script d3 para producir un diseño que se muestra en la segunda imagen?

Respuesta

30

En primer lugar, aumentar la fuerza de carga y reducir la distancia de enlace. Hacerlo pone más énfasis en la estructura global que en las conexiones locales. Además, si aumenta la fuerza de carga lo suficiente, la carga de repulsión empujará aún más los nodos conectados directamente más separados, lo que aumenta efectivamente la distancia del enlace al tiempo que proporciona una mejor estructura general. (La desventaja de una fuerza de carga más fuerte es que la inicialización gráfica es más caótico, pero esto no debería ser un problema para los diseños estáticos.)

En segundo lugar, puede que tenga que aumentar el número de iteraciones o agregue fuerzas personalizadas para obtener mejores resultados. Los diseños de fuerza a menudo funcionan bien en gráficos arbitrarios, pero no hay garantía de que produzcan un resultado óptimo (o incluso bueno). Para cualquier gráfico en el que pueda hacer suposiciones simplificadoras (por ejemplo, trees), puede haber fuerzas o restricciones adicionales que pueda aplicar para alentar a la simulación a converger en una mejor solución.

+3

** Mayor fuerza de carga ** y ** menor distancia de enlace ** funciona. En cuanto a ** agregar fuerzas personalizadas **, ¿hay algún ejemplo/tutorial que pueda seguir? ¿Podría dar algunos ejemplos de ** restricciones adicionales ** que se pueden aplicar para una mejor convergencia? ¡Muchas gracias! – MLister

+8

Para las fuerzas personalizadas, vea mi [charla sobre diseños de fuerza] (http://vimeo.com/29458354) y las diapositivas que lo acompañan. – mbostock