利用d3.js力导布局绘制资源拓扑图实例教程(5)

效果如下:

这些线一对A都没有,分不清正反啊

应用与资源间的关系,是有方向的,大部分情况下是应用调用资源,也有情况会有双向的调用,除了文字意外,我们还需要加上箭头来表明是谁在调用谁。怎么加这个箭头呢?svg 的 path 元素有一个 marker-end 属性,通过设置这个属性可以可以将一个 svg 元素绘制到 path 元素最后的向量上。

// 在 svg 元素中添加一个 marker 元素
<svg> 
 <marker
 id="arrow"
 viewBox="-10 -10 20 20"
 markerWidth="20"
 markerHeight="20"
 orient="auto"
 >
 <path
 d="M-6.75,-6.75 L 0,0 L -6.75,6.75"
 fill="none"
 stroke="#E5E5E5"
 />
 </marker>
</svg>

...

const pathElements = svg.append('g') 
 .selectAll('path')
 .data(visualLinks)
 .enter().append('path')
 .attr('fill', 'none')
 // 设置 marker-end 属性
 .attr('marker-end', 'url(#arrow)')
 .attr('id', link => link.id)
 .attr('stroke-width', 1)
 .attr('stroke', '#E5E5E5');

...

但直接这样写的话,效果会很差,为啥呢?因为我们 path 元素的起点与终点是节点的中心点,直接这样的话箭头都在节点上面,如图:

看到中间那朵菊花没

所以我们没法直接通过加这个属性来加上箭头,我们需要对 path 做一些处理,对 path 线段去头去尾。那怎么做呢?还好有巨佬已经实现了一种算法,算出两个 path 元素之间的交点,因此我们可以在算出原 arcPath 后,再算出这条弧线与节点外一个大一点的圆的交点,再把原 arcPath 的起点与终点移到这两个点上。