framework examples javascript svg d3.js force-layout

javascript - examples - jquery d3



Cómo hacer que el gráfico de diseño de fuerza en D3.js responda al tamaño de pantalla/navegador (3)

Tengo un gráfico usando el diseño de fuerza, pero tiene un ancho fijo w altura h :

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 da como resultado un gráfico svg que no escala ni disminuye a pesar de los cambios en la pantalla o el tamaño de la ventana del navegador. Para que sea receptivo (es decir, se redimensiona automáticamente), traté de usar los atributos viewBox y preserveAspectRatio :

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

Lamentablemente, esto no funcionó ya que no sucede nada cuando ajusto 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 viewBox y preserveAspectRatio con gráficos de diseño forzado.


Duopixel está muy cerca de lo que necesitaba, excepto que no sé por qué anidó dos <g> elementos y unió los oyentes del evento al <g> más externo (también requirió un rectángulo invisible detrás de todo para hacer que el g reaccionara frente a los eventos todo su espacio).

Es más fácil asociar a los oyentes al <svg> mismo y luego solo necesita un <g> interno.

Aquí está mi ejemplo de fuerza dirigida a pantalla completa:

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);


El problema no está en .size() , sino que indica las dimensiones de SVG en .attr("width", w) .attr("height", h) . Elimina estos dos atributos y lo harás 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/


La solución que se muestra aquí: http://bl.ocks.org/mbostock/3355967 funcionó 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.