d3.js - D3 forced layout zoom and pan not working -
i got started d3's forced layout , implemented radial graph implementation referring : http://flowingdata.com/2012/08/02/how-to-make-an-interactive-network-visualization/
the problem facing zooming not working. here's code referred: http://jsfiddle.net/blt909/avhd8/20/ zoom functionality
and here's code:
var w = $("#network-plot").width(), h = 800, r = 6, fill = d3.scale.category20(); var payload={js:'mis1'} $.ajax({ url: "/getsource", type: "post", async: false, data: payload, success: function (data) { mis1=json.parse(data); }, }); var force = d3.layout.force() .charge(-30) .linkdistance(310) .size([w, h]); var zoom = d3.behavior.zoom() .scaleextent([1, 10]) .on("zoom", zoomed); var svgnt = d3.select("#network-plot-svg") .attr("width", w) .attr("height", h) .style('margin-top', h/15) .call(zoom); var vis = svgnt.append("svg:g"); var rect = vis.append("svg:rect") .attr("width", w) .attr("height", h) .attr("fill", '#fff') .style("pointer-events", "all"); function zoomed() { vis.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); } var radius = d3.scale.log(); var mis1; //**********radial code**************** var unsortednodes = {}; var sortednodes = []; var sortagainst = []; var heaviest_node_length = 0; for(var = 0; < mis1.nodes.length; i++) { var count_conn = 0; var heaviest_node; for(var j = 0; j < mis1.links.length; j++) { if(mis1.links[j].source == mis1.nodes[i].group || mis1.links[j].target == mis1.nodes[i].group) { count_conn++; } } if(count_conn > heaviest_node_length) { heaviest_node_length = count_conn; heaviest_node = i; } unsortednodes[i] = 10 + count_conn; sortagainst[i] = 10 + count_conn; } sortagainst.sort(); sortagainst.reverse(); for(i in unsortednodes) { var index = sortagainst.indexof(unsortednodes[i]); sortednodes[index] = i; sortagainst[index] = ''; } var c = {"x":w/2, "y":h/2}; var negativey = 0; var positivey = 0; var negativex = 0; var positivex = 0; var groupcenters = radialplacement(c, 300, 18, sortednodes); //following lines readjustment code in case svg container outgrown graph h = math.abs(negativey) + math.abs(positivey) + 100; //tbd: padding needs dynamic w = math.abs(negativex) + math.abs(positivex) + 200; c = {"x":w/2, "y":h/2}; groupcenters = radialplacement(c, 300, 18, sortednodes); svgnt.attr("height", h); vis.attr("height", h); svgnt.attr("width", w); vis.attr("width", w); function radiallocation(center, angle, radius) { x = (center.x + radius * math.cos(angle * math.pi / 180)); y = (center.y + radius * math.sin(angle * math.pi / 180)); if(y < negativey) { negativey = y; } if(y > positivey) { positivey = y; } if(x < negativex) { negativex = x; } if(x > positivex) { positivex = x; } return {"x":x,"y":y}; } function radialplacement(center, radius, increment, keys) { var values_circle = {}; var increment; var start = -90; var current = start; var total_nodes = keys.length; var circles = math.floor(math.sqrt((total_nodes - 1)/5)); if(circles == 0) { circles = 1; } var ratio; var r = []; var circlekeys = []; var radius = 140; r[0] = radius; var sum_r = r[0]; for(var j = 1; j < circles; j++){ r[j] = r[j-1] + 100 //tbd: should radius linearly incremented this? sum_r += r[j]; } ratio = 1/sum_r; var temp = 0; for(j = 0; j < circles; j++) { if(j == circles - 1) circlekeys[j] = total_nodes - temp; else { circlekeys[j] = math.floor(total_nodes * r[j] * ratio); temp += circlekeys[j]; } } var k = 0; for(var = 0; < circlekeys.length; i++) { increment = 360/circlekeys[i]; for(j = 0; j < circlekeys[i]; j++, k++) { if(k == 0) { values_circle[keys[k]] = radiallocation(center, -90, 0); } else { values_circle[keys[k]] = radiallocation(center, current, r[i]);; current += increment; } } } return values_circle; } //************radial code ends*************** d3.json(mis1, function() { var link = svgnt.selectall("line") .data(mis1.links) .enter() .append("svg:line") .style("stroke","#ddd"); var node = svgnt.selectall("circle") .data(mis1.nodes) .enter() .append("svg:circle") .attr("r", function(d, j){ var count = 0; for(var i=0; i<mis1.links.length; i++) { if(mis1.links[i].source == d.group || mis1.links[i].target == d.group){ count ++; } } return (10+count); }) .style("fill", function(d) { return fill(d.group); }) .on("mouseover", fade(.1)) .on("mouseout", fade(1)); texts = svgnt.selectall("text.label") .data(mis1.nodes) .enter().append("text") .attr("class", "label") .attr("fill", "black") .text(function(d) { return d.name; }); force.nodes(mis1.nodes).links(mis1.links).on("tick", tick).start(); var linkedbyindex = {}; mis1.links.foreach(function(d) { linkedbyindex[d.source.index + "," + d.target.index] = 1; }); function isconnected(a, b) { return linkedbyindex[a.index + "," + b.index] || linkedbyindex[b.index + "," + a.index] || a.index == b.index; } function tick() { node.attr("cx", function(d, i) { return d.x = groupcenters[i].x; }).attr("cy", function(d, i) { return d.y = groupcenters[i].y; }); 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; }); texts.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); }
any idea doing wrong? graph displayed fine doesn't have zoom capability.
the problem is, appending nodes , links directly svg
, not g
element. since zoom transformations applied vis
(g
element), nodes , links not zoom/pan.
so instead of below code
var link = svgnt.selectall("line") .data(mis1.links) .enter() .append("svg:line") .style("stroke","#ddd"); var node = svgnt.selectall("circle") .data(mis1.nodes) .enter() .append("svg:circle") ---------------------- ---------------------- ----------------------
try code.
var link = vis.selectall("line") .data(mis1.links) .enter() .append("svg:line") .style("stroke","#ddd"); var node = vis.selectall("circle") .data(mis1.nodes) .enter() .append("svg:circle") ---------------------- ---------------------- ----------------------
Comments
Post a Comment