Arrow head position on Force directed layout with different sized nodes

1,208 views
Skip to first unread message

Steve Eichert

unread,
Oct 25, 2012, 5:45:38 PM10/25/12
to d3...@googlegroups.com
I'm creating a network visualization using the force layout within D3.  Everything is working well, however, I'm sizing the nodes in my visualization and as a result the arrow heads are not aligning appropriately.  For larger nodes the arrow heads are behind the node and can't be seen.  I used this example as my starting point: http://bl.ocks.org/1153292  Can someone point me in the right direction for adjusting the position of the arrow heads appropriately given the radius of the target node?

Thanks,
Steve

Kai Chang

unread,
Oct 31, 2012, 6:33:48 PM10/31/12
to d3...@googlegroups.com
I came up with a somewhat ugly but workable solution for this. You
need to adjust the refX on the marker definition. But can't just
change the marker-- or else all the other arrows will change.

Instead you need to create as many markers as arrow positions.
Something like this:

vis.append("svg:defs").selectAll("marker.arrow")
.data( d3.range(1,Math.ceil(Math.sqrt(maxsize))) )
.enter().append("svg:marker")
.attr("id", function(d) { return "arrow-" + d})
.attr("class", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", function(d) { return 13+d })
.attr("refY", 0)
.attr("markerWidth", 5)
.attr("markerHeight", 5)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");

Then for the links, select the end marker id based on where it needs to be:

.attr("marker-end", function(d) { return "url(#arrow-" +
Math.ceil(Math.sqrt(json.nodes[d.target.index].size)) + ")"; })

Really not an ideal solution. You could also try adjusting the x2, y2
so that the line only goes to the edge of the circle. Might have to do
a little trig.

Let us know what you come up with, it'd be great to have a simple way
to do this that doesn't involve creating a bunch of marker
definitions.
Reply all
Reply to author
Forward
0 new messages