@LarsKotthoff 是正确的,textPath
必须遵循路径的方向。在这种情况下,路径的方向不仅定义了弧线方向,还定义了箭头标记在末端的连接——这使得动态交换方向变得很棘手,因为您也必须移动标记。
更简单的解决方案(尽管如果您有大量链接可能不是最好的)是使用仅用于文本的不可见路径“隐藏”真实链接路径:
var link = svg.append("svg:g").selectAll("g.link")
.data(force.links())
.enter().append('g')
.attr('class', 'link');
var linkPath = link.append("svg:path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
var textPath = link.append("svg:path")
.attr("id", function(d) { return d.source.index + "_" + d.target.index; })
.attr("class", "textpath");
现在您有了一个可以正确操作的单独路径。正如您所注意到的,有两个问题 - 您必须更改路径方向,并且必须更改弧线方向。看起来您可以通过交换sweep-flag
值(请参阅文档)在路径命令字符串中执行此操作,因此Arx,ry 0 0,1
您可以使用Arx,ry 0 0,0
. 您可以通过使用一个函数来创建路径字符串来减少一些代码重复:
function arcPath(leftHand, d) {
var start = leftHand ? d.source : d.target,
end = leftHand ? d.target : d.source,
dx = end.x - start.x,
dy = end.y - start.y,
dr = Math.sqrt(dx * dx + dy * dy),
sweep = leftHand ? 0 : 1;
return "M" + start.x + "," + start.y + "A" + dr + "," + dr +
" 0 0," + sweep + " " + end.x + "," + end.y;
}
然后可以分别更新链接路径和文本路径:
linkPath.attr("d", function(d) {
return arcPath(false, d);
});
textPath.attr("d", function(d) {
return arcPath(d.source.x < d.target.x, d);
});
请参阅工作代码:http: //jsfiddle.net/nrabinowitz/VYaGg/2/