I am currently implementing arrows in my force layout as is done in this example (http://bl.ocks.org/mbostock/1153292) and that works perfectly. However, one will quickly realize that the location and size of the arrows are hard-coded here since the nodes never change size.
I have a graph were I dynamically change node sizes, and as such I would like the arrows to update accordingly since otherwise they are covered by the node or cover the node or are just not attached to the node.
There is only one post I have found (linking nodes of variable radius with arrows) that talks about this issue. However, it was not answered, and the answer that one poster gives of having the edges end at the radius of the node rather than the center is not something I want to do. It would require constantly recomputing edge positions, which given the number of edges I have is not practical.
I thought this would be relatively simple but haven't been able to figure it out. The change that I a currently working on is moving the marker creation below the generation of the nodes, since otherwise there is no ability to get node size data unless I want to run the size method I am using, which would be a massive waste of processing power (I have hundreds of nodes).
What I am trying (rough example, my code is a bit more complex)
var path = svg.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
.attr("class", function(d) { return d.target.nodeID; });
var circle = svg.append("svg:g").selectAll("circle")
.data(force.nodes())
.enter().append("svg:circle")
.attr("r", nodeSize) //Dynamically determine size
.call(force.drag);
// Per-node markers, as each node could potentially have a unique size
svg.append("svg:defs").selectAll("marker")
.data(nodes, function(d) { return d.nodeID; })
.enter().append("svg:marker")
.attr("id", function(d) { return d.nodeID; })
.attr("viewBox", "0 -5 10 10")
.attr("refX", function(d) { return d.r; }) //Offset by the radius of the node
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
//Now that we know radius data for nodes, add the arrows in
path.each(function(d) {
d.attr("marker-end", function(d) { return "url(#" + d.target.nodeID + ")"; })
});
Does anyone have an idea about the best way to go about this? Thanks in advance!
Update: per request, I have created a jsfiddle (http://jsfiddle.net/herbstmb/j5wJ7/). This is a basic force layout that I am trying to get the dynamic arrow sizes to work on.