2012-08-13 41 views
45

que tienen un diseño gráfico usando la fuerza, pero tiene un ancho fijo y altura wh:Como hacer gráfico de la disposición vigente en D3.js sensible al tamaño de pantalla/navegador

var svg = d3.select("#viz").append("svg") 
      .attr("id", "playgraph") 
      .attr("width", w) 
      .attr("height", h) 

var force = d3.layout.force() 
       .nodes(nodes) 
       .links(links) 
       .charge(-1600) 
       .linkDistance(45) 
       .size([w, h]); 

lo que se traduce en un SVG gráfico que no aumenta o disminuye a pesar de los cambios en la pantalla o el tamaño de la ventana del navegador. Con el fin de hacer que responda (es decir, cambia automáticamente el tamaño en sí), he intentado usar viewBox y preserveAspectRatio atributos:

var svg = d3.select("#viz").append("svg") 
      .attr("id", "playgraph") 
      .attr("width", w) 
      .attr("height", h) 
      .attr("viewBox", "0, 0, 600, 400") 
      .attr("preserveAspectRatio", "xMidYMid meet"); 

Por desgracia, esto no funcionó como no ocurre nada cuando se ajusta el tamaño de la ventana del navegador. Me pregunto si el .size([w, h]) del gráfico de fuerza tiene algo que ver con esto.

Por favor arroja algo de luz sobre cómo usar los atributos viewBox y preserveAspectRatio con gráficos de fuerza de diseño.

+0

Es posible que también desee adjuntar su función de redibujado a 'window.onresize' – Wex

+0

Esta pregunta es bastante antigua, pero para aquellos que lo encuentran útil, también puede considerar restringir los nodos a un cuadro delimitado. Al cambiar el tamaño, los nodos permanecerán en la pantalla. Ejemplo: http://bl.ocks.org/mbostock/1129492 – joshfindit

Respuesta

50

El problema no está dentro de .size(), sino que indica las dimensiones de SVG en .attr("width", w) .attr("height", h). Remover estos dos atributos y te haré bien ...

var svg = d3.select("#viz").append("svg") 
      .attr("id", "playgraph") 
      //better to keep the viewBox dimensions with variables 
      .attr("viewBox", "0 0 " + w + " " + h) 
      .attr("preserveAspectRatio", "xMidYMid meet"); 

http://jsfiddle.net/aaSjd/

+0

gracias! Así que ahora la imagen svg cambia de tamaño. Sin embargo, sin configurar 'attr (" width ", ...)' y 'attr (" height ", ...)', el ancho/alto de la imagen parece ser el ancho/alto de la ventana actual del navegador. ¿Hay alguna manera de que pueda establecer estas dos dimensiones del elemento 'svg' en otro lugar, sin afectar los atributos' viewBox' y 'preserveAspectRatio'? – MLister

+3

' 'debería comenzar. – Duopixel

4

Duopixel está muy cerca de lo que necesitaba, excepto que no sé por qué se anida dos elementos <g> y adjunta la oyentes de eventos en el extremo <g> (que también requieren un rectángulo invisible detrás de todo para que el g reaccione a los eventos en todo su espacio).

Es más fácil conectar los oyentes al <svg> y solo necesita un <g> interno.

Aquí está mi pantalla completa fuerza dirigida ejemplo:

var width = 1000, 
    height = 1000; 

var color = d3.scale.category20(); 

var svg = d3.select("body") 
    .append("svg") 
     .attr({ 
     "width": "100%", 
     "height": "100%" 
     }) 
     .attr("viewBox", "0 0 " + width + " " + height) 
     .attr("preserveAspectRatio", "xMidYMid meet") 
     .attr("pointer-events", "all") 
    .call(d3.behavior.zoom().on("zoom", redraw)); 

var vis = svg 
    .append('svg:g'); 

function redraw() { 
    vis.attr("transform", 
     "translate(" + d3.event.translate + ")" 
     + " scale(" + d3.event.scale + ")"); 
} 

function draw_graph(graph) { 
    var force = d3.layout.force() 
     .charge(-120) 
     .linkDistance(30) 
     .nodes(graph.nodes) 
     .links(graph.links) 
     .size([width, height]) 
     .start(); 

    var link = vis.selectAll(".link") 
     .data(graph.links) 
     .enter().append("line") 
     .attr("class", "link") 
     .style("stroke-width", function(d) { return Math.sqrt(d.value); }); 

    var node = vis.selectAll(".node") 
     .data(graph.nodes) 
     .enter().append("circle") 
     .attr("class", "node") 
     .attr("r", 5) 
     .style("fill", function(d) { return color(d.group); }) 
     .call(force.drag); 

    node.append("title") 
     .text(function(d) { return d.name; }); 

    force.on("tick", function() { 
    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; }); 
    }); 
}; 

draw_graph(data); 
8

La solución que se muestra aquí: http://bl.ocks.org/mbostock/3355967 funcionado bien para mí!

window.addEventListener('resize', resize); 

function resize() { 
    var width = window.innerWidth, height = window.innerHeight; 
    svg.attr("width", width).attr("height", height); 
    force.size([width, height]).resume(); 
} 

Asegúrese de ejecutar resize() después de haber agregado todas sus líneas, nodos, etc.