javascript - D3.js network graph using force-directed layout and rectangles for nodes -
i'm trying modify mike's force-directed graph example use rectangles instead of circles nodes. also, want text inside rectangle.
i have rectangles showing text correctly, they're not attached links, , not move.
here's codepen link: http://codepen.io/anon/pen/gpgwaz
var width = 960, height = 500; var color = d3.scale.category20(); 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); 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("g") .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) .call(force.drag); node.append("rect") .attr("class", "node") .attr("width", 100) .attr("height", 35) .style("fill", function(d) { return color(d.group); }) .style("stroke", "black") .style("stroke-width", "1px"); node.append("text") .text(function(d) { return d.name; }) .style("font-size", "12px") .attr("dy", "1em"); 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("x", function(d) { return d.x; }) .attr("y", function(d) { return d.y; }); });
update
thanks lars's comment, , codepen works now.
updates made code:
- add transform illustrated lars
- changed links connect @ center of rectangles
- added rounded corners rectangles
- gave text slight margin indentation
- changed use window width/height
here new codepen: http://codepen.io/anon/pen/bdgred
var width = window.innerwidth, height = window.innerheight, nodewidth = 100, nodeheight = 35; var color = d3.scale.category20(); var force = d3.layout.force() .charge(-1500) .linkdistance(100) .friction(0.5) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); 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("g") .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) .call(force.drag); node.append("rect") .attr("class", "node") .attr("width", nodewidth) .attr("height", nodeheight) .attr("rx", 5) .attr("ry", 5) .style("fill", function(d) { return color(d.group); }) .style("stroke", "black") .style("stroke-width", "1px"); node.append("text") .attr("x", 5) .attr("y", 2) .text(function(d) { return d.name; }) .style("font-size", "12px") .attr("dy", "1em"); node.append("title") .text(function(d) { return d.name; }); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x + (nodewidth / 2); }) .attr("y1", function(d) { return d.source.y + (nodeheight / 2); }) .attr("x2", function(d) { return d.target.x + (nodewidth / 2); }) .attr("y2", function(d) { return d.target.y + (nodeheight / 2); }); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); });
you're setting x
, y
attributes on g
elements change positions -- won't anything. need set transform
attribute instead, you're doing when adding g
elements. tick
handler function contain
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
instead of
node.attr("x", function(d) { return d.x; }) .attr("y", function(d) { return d.y; });
complete demo here.
Comments
Post a Comment