D3 SVG路径上箭头的定位

5
我正在使用D3可视化一个力导向网络,但是我在沿着节点之间的边缘定位箭头时遇到了问题。如图所示,我根据每个节点的属性值来调整节点的大小。基本上,我需要一种方法来动态计算/更改我的箭头在边缘上的位置(根据用于缩放节点的相同值),以使它们可见并防止与节点重叠。实际上,我希望我的箭头“触摸”我的节点的外边缘。是否有人知道如何做到这一点?这些代码片段展示了我如何创建我的箭头。也许我应该使用另一种方式吗?
附:我知道可以更改绘图顺序,将箭头绘制在节点之上,但那不是我想要的。

enter image description here

...

svg.append("defs").append("marker")
.attr("id", "arrowhead")
.attr("refX", 5) /*must be smarter way to calculate shift*/
.attr("refY", 2)
.attr("markerWidth", 6)
.attr("markerHeight", 4)
.attr("orient", "auto")
.append("path")
    .attr("d", "M 0,0 V 4 L6,2 Z");

...

 path.enter()
        .append("svg:path")
        .attr("class", function (d) {
            return "link " + d.type;
        })
        .attr("id", function (d) {
            return "path_" + d.id;
        })
        .attr("marker-end", "url(#arrowhead)")
        .transition().duration(8000)
        .style("stroke-width", stylePathStrokeWidth)
...

你需要动态地为每个路径在defs中构建箭头标记,并根据每个圆的半径调整refX。 - Francis Hemsher
1
请查看我在这里提供的答案 - Mark
@Mark 谢谢你的帮助! - Bavo Devocht
1个回答

7

我根据Mark在这个问题Align Marker on node edges D3 Force Layout的答案解决了这个问题。下面是我的代码:

在tick函数内:

function tick() {

// fit path like you've been doing
path.attr("d", function (d, i) {
    dr = 550 / d.linknum;
    var result = "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
    return result;
});

// recalculate and back off the distance
path.attr("d", function (d, i) {  
    var pl = this.getTotalLength();
    //this is the magic
    var r = d.target.size + 3 * d.size; // Multiply the marker size (3) with the size of the edge (d.size) because the markers are scaling with the edge which they are attached to!!
    var m = this.getPointAtLength(pl - r);
    dr = 550 / d.linknum;
    var result = "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + m.x + "," + m.y;
    return result;
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接