score:9

### The Problem

This jsFiddle demonstrates the problem in question. The values of the marker def are in relation to the stoke width of the element it is attached to (the link lines in this case). See the markerUnits spec. By using `strokeWidth` for the `markerUnits` attribute the coordinates for the different size arrows will be slightly different. In short the appropriate values for one size arrow will not correctly translate to the other sizes.

### Solution 1: Multiple Markers

As mentioned in the comments one solution would be to create a different marker for each `strokeWidth` that's needed. This would work only if you knew up front what sizes were needed.

### Solution 2: Modify the Lines

Another option would be to modify the end point for the lines. Instead of allowing the lines to terminate in the center of a node, terminate it on the outside edge of the node. This jsFiddle demonstrates this. This alleviates the need to shift the arrow head, as we can now just draw it at the end of the line.

This solution involves some math to figure out what the `x2` and `y2` values of the `line` should be. Thus, it may not be ideal for systems with a large number of edges.

``````var nodeRadius = 10;
var lineX2 = function (d) {
var length = Math.sqrt(Math.pow(d.target.y - d.source.y, 2) + Math.pow(d.target.x - d.source.x, 2));
var scale = (length - nodeRadius) / length;
var offset = (d.target.x - d.source.x) - (d.target.x - d.source.x) * scale;
return d.target.x - offset;
};
var lineY2 = function (d) {
var length = Math.sqrt(Math.pow(d.target.y - d.source.y, 2) + Math.pow(d.target.x - d.source.x, 2));
var scale = (length - nodeRadius) / length;
var offset = (d.target.y - d.source.y) - (d.target.y - d.source.y) * scale;
return d.target.y - offset;
};

.enter().append("svg:line")
.style("stroke-width", function (d) {
return Math.sqrt(d.value);
})
.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", lineX2)
.attr("y2", lineY2)
.attr("marker-end", "url(#arrowGray)")
.on("click", function (d) {
node.style("stroke", "#FFFFFF");
d3.select(this).style("stroke", "red");
d3.select(this).attr("marker-end", null);
d3.select(this).attr("marker-end", "url(#arrowRed)");
});

var defs = svg.append('defs');
defs.append("svg:marker")
.attr("id", "arrowGray")
.attr("viewBox", "0 0 10 10")
.attr("refX", "10")
.attr("refY", "5")
.attr("markerUnits", "strokeWidth")
.attr("markerWidth", "10")
.attr("markerHeight", "5")
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M 0 0 L 10 5 L 0 10 z")
.attr("fill", "#000");

var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.style("fill", function (d) {
return color(d.group);
})
.call(force.drag);

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", lineX2)
.attr("y2", lineY2)

node.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
});
``````

score:1

Your `refX` is probably too large. Try setting it to something around 1.