Is there a way to zoom in on the D3 layout diagram?

D3 has a power circuit here . Is there any way to add scaling to this graph? Currently, I was able to capture the mouse wheel event, but I'm not sure how to write a redraw function. Any suggestions?

var vis = d3.select("#graph") .append("svg:svg") .call(d3.behavior.zoom().on("zoom", redraw)) // <-- redraw function .attr("width", w) .attr("height", h); 
+76
javascript jquery zoom force-layout
Oct 24 2018-11-11T00:
source share
6 answers

Update 6/4/14

See also Mike Bostock, respond here to the changes in D3 v.3 and related example . I think this is likely to replace the answer below.

Update 02/18/2014

I think @ahaarnos answer is preferable if you want the whole SVG to be enabled and scaled. The nested g elements in my answer below are really only needed if you have objects without scaling in the same SVG (not in the original question). If you apply behavior to the g element, then to ensure that g receives pointer events, you need a rect background or similar element.

Original answer

I got this work based on the zoom-pan-transform example - here you can see my jsFiddle: http://jsfiddle.net/nrabinowitz/QMKm3/

It was a bit more complicated than I had hoped - you need to nest a few g elements to make it work, set the SVG attribute pointer-events to all , and then add a background rectangle to receive (otherwise it only works when the pointer is over node or link). The redraw function is relatively simple, just setting the transform to the innermost g :

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

This effectively scales the entire SVG, so it also scales the stroke width, such as image scaling.

There is another example that illustrates a similar technique.

+96
Oct 26 '11 at 18:17
source share

Why nested <g> ?

This code below worked well for me (only one <g> , without random large white <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 + ")"); } 

Here all the elements in your svg are added to the vis element.

+17
Mar 07 '13 at 20:38
source share

The answers provided work in D3 v2, but not in v3. I synthesized the answers as a clean solution and solved the v3 problem using the answer provided here: Why d3.js v3 breaks my graph of strength when implementing scaling when v2 is not?

First, the main code. This is a cleaned version of @ahaarnos answer:

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

Now you have panning and zooming, but you will not be able to drag the nodes, because the pan function cancels the drag function. Therefore, we must do this:

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

Here the @nrabinowitz script has been modified to use this cleaner scaling implementation, but it illustrates how D3v3 splits the node drag and drop: http://jsfiddle.net/QMKm3/718/

And here is the same fiddle modified to work with D3v3: http://jsfiddle.net/QMKm3/719/

+14
Jun 04 '14 at 2:37
source share

I got my schedule to work without the second "svg: g" append.

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

The rest is the same.

+2
Apr 15 '13 at 16:54
source share

I have a scalable D3 radiation pattern solution.

  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 + ")"); } 
0
May 29 '14 at 6:01
source share

If you want to zoom and pan without changing node-size, try below. You can also drag nodes without jitter. This code is based on an example of the original power layout. For these nodes and links, refer to the original sample data. http://bl.ocks.org/mbostock/4062045

Note the xScale and yScale variables, the dragstarted (), dragged (), and dragended () functions. The tick () function has also been changed.

The result can be seen at http://steelblue.tistory.com/9. The language on the site is Korean. However, you can easily find the result in the third example on the page.

 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()); dx = xScale.invert(mouse[0]); dy = yScale.invert(mouse[1]); d.px = dx; d.py = dy; 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(dx) + "," + yScale(dy) + ")"; }); }; 

0
Nov 27 '14 at 18:13
source share



All Articles