usuario una interfaz interfaces hacer graficos graficas grafica diseño con como chart javascript jquery d3.js zoom force-layout

javascript - interfaz - ¿Hay alguna manera de acercar un gráfico de diseño de fuerza D3?



graficos html (6)

¿Por qué los <g> anidados?

Este código a continuación funcionó bien para mí (solo uno <g> , sin gran blanco aleatorio <rect> :

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

Donde todos los elementos de tu svg se anexan al elemento vis .

D3 tiene un diseño de fuerza dirigida here . ¿Hay alguna forma de agregar zoom a este gráfico? Actualmente, pude capturar el evento de la rueda del mouse pero no estoy seguro de cómo escribir la función de redibujado. ¿Alguna sugerencia?

var vis = d3.select("#graph") .append("svg:svg") .call(d3.behavior.zoom().on("zoom", redraw)) // <-- redraw function .attr("width", w) .attr("height", h);


Conseguí que mi gráfico funcionara sin el segundo apéndice "svg: g".

[...].attr("pointer-events", "all") .attr("width", width2) .attr("height", height2) .append(''svg:g'') .call(d3.behavior.zoom().on("zoom", redraw));

El resto es lo mismo


Las respuestas proporcionadas funcionan en D3 v2 pero no en v3. He sintetizado las respuestas en una solución limpia y he resuelto el problema de v3 utilizando la respuesta proporcionada aquí: ¿Por qué d3.js v3 rompe mi gráfico de fuerzas al implementar el zoom cuando v2 no lo hace?

Primero el código principal. Esta es una versión limpia de la respuesta de @ahaarnos:

var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height) .call(d3.behavior.zoom().on("zoom", redraw)) .append(''g''); function redraw() { svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }

Ahora tiene una vista panorámica y un zoom, pero no podrá arrastrar los nodos porque la funcionalidad de panorámica anulará la funcionalidad de arrastre. Entonces tenemos que hacer esto:

var drag = force.stop().drag() .on("dragstart", function(d) { d3.event.sourceEvent.stopPropagation(); // to prevent pan functionality from //overriding node drag functionality. // put any other ''dragstart'' actions here });

Aquí está el violín de @nrabinowitz modificado para usar esta implementación de zoom más limpia, pero que ilustra cómo D3v3 rompe el arrastre del nodo: http://jsfiddle.net/QMKm3/718/

Y aquí está el mismo violín modificado para trabajar con D3v3: http://jsfiddle.net/QMKm3/719/


Obtuve una solución para D3 force directed graph con la opción de zoom.

var m = [40, 240, 40, 240], width = 960, height = 700, root; var svg = d3.select("body").append("svg") .attr("class", "svg_container") .attr("width", width) .attr("height", height) .style("overflow", "scroll") .style("background-color", "#EEEEEE") .append("svg:g") .attr("class", "drawarea") .append("svg:g") .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); //applying zoom in&out for svg d3.select("svg") .call(d3.behavior.zoom() .scaleExtent([0.5, 5]) .on("zoom", zoom)); //zooming function zoom() { //zoom in&out function var scale = d3.event.scale, translation = d3.event.translate, tbound = -height * scale, bbound = height * scale, lbound = (-width + m[1]) * scale, rbound = (width - m[3]) * scale; // limit translation to thresholds translation = [ Math.max(Math.min(translation[0], rbound), lbound), Math.max(Math.min(translation[1], bbound), tbound) ]; d3.select(".drawarea") .attr("transform", "translate(" + translation + ")" + " scale(" + scale + ")"); }


Si desea acercar o alejar el diseño de la fuerza sin cambiar el tamaño del nodo, intente a continuación. También puede arrastrar nodos sin temblar. Este código se basa en el ejemplo de diseño de fuerza original. En cuanto a los datos de nodos y enlaces, consulte los datos de muestra originales. http://bl.ocks.org/mbostock/4062045

Por favor, tenga en cuenta las variables xScale y yScale, las funciones dragstarted (), dragged () y dragended (). La función tick () también se modificó.

Puede ver el resultado en http://steelblue.tistory.com/9 El idioma en el sitio es coreano. Sin embargo, puede encontrar fácilmente el resultado en el tercer ejemplo de la página.

var graph = { "nodes": [ { "name": "Myriel", "group": 1 }, { "name": "Napoleon", "group": 1 }, // ...... { "name": "Mme.Hucheloup", "group": 8 } ], "links": [ { "source": 1, "target": 0, "value": 1 }, { "source": 2, "target": 0, "value": 8 }, // ....... { "source": 76, "target": 58, "value": 1 } ] }; var width = 640, height = 400; var color = d3.scale.category20(); var xScale = d3.scale.linear() .domain([0, width]) .range([0, width]); var yScale = d3.scale.linear() .domain([0, height]) .range([0, height]); var zoomer = d3.behavior.zoom().x(xScale).y(yScale).scaleExtent([0.1, 8]).on("zoom", zoom); function zoom() { tick(); }; var drag = d3.behavior.drag() .origin(function (d) { return d; }) .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); d.fixed |= 2; } function dragged(d) { var mouse = d3.mouse(svg.node()); d.x = xScale.invert(mouse[0]); d.y = yScale.invert(mouse[1]); d.px = d.x; d.py = d.y; force.resume(); } function dragended(d) { d.fixed &= ~6; } var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); svg.call(zoomer); force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function (d) { return Math.sqrt(d.value); }); var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function (d) { return color(d.group); }) .call(drag); node.append("title") .text(function (d) { return d.name; }); force.on("tick",tick); function tick(){ link.attr("x1", function (d) { return xScale(d.source.x); }) .attr("y1", function (d) { return yScale(d.source.y); }) .attr("x2", function (d) { return xScale(d.target.x); }) .attr("y2", function (d) { return yScale(d.target.y); }); node.attr("transform", function (d) { return "translate(" + xScale(d.x) + "," + yScale(d.y) + ")"; }); };


Actualización 6/4/14

Ver también la respuesta de Mike Bostock aquí para los cambios en D3 v.3 y el ejemplo relacionado . Creo que esto probablemente reemplaza la respuesta a continuación.

Actualización 18/02/2014

Creo que la respuesta de @ahaarnos es preferible si quieres que todo el SVG se desplace y se amplíe. Los elementos g anidados en mi respuesta a continuación solo son realmente necesarios si tienes elementos sin zoom en el mismo SVG (no es el caso en la pregunta original). Si aplica el comportamiento a un elemento g , se requiere un fondo rect o elemento similar para garantizar que g reciba eventos de puntero.

Respuesta original

Lo conseguí trabajando basado en el ejemplo zoom-pan-transform - puedes ver mi jsFiddle aquí: http://jsfiddle.net/nrabinowitz/QMKm3/

Era un poco más complejo de lo que esperaba: debe anidar varios elementos g para que funcione, establecer el atributo de pointer-events de pointer-events del SVG en all , y luego agregar un rectángulo de fondo para recibir los eventos del puntero (de lo contrario, solo funciona cuando el puntero está sobre un nodo o enlace). La función de redraw es comparativamente simple, simplemente configurando una transformación en la g más interna:

var vis = d3.select("#chart") .append("svg:svg") .attr("width", w) .attr("height", h) .attr("pointer-events", "all") .append(''svg:g'') .call(d3.behavior.zoom().on("zoom", redraw)) .append(''svg:g''); vis.append(''svg:rect'') .attr(''width'', w) .attr(''height'', h) .attr(''fill'', ''white''); function redraw() { console.log("here", d3.event.translate, d3.event.scale); vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }

Esto escala efectivamente todo el SVG, por lo que también escala el ancho del trazo, como acercar una imagen.

Hay otro example que ilustra una técnica similar.