Javascript D3.js具有动态偏移箭头的力有向图?

Javascript D3.js具有动态偏移箭头的力有向图?,javascript,d3.js,geometry,observablehq,cubic-bezier,Javascript,D3.js,Geometry,Observablehq,Cubic Bezier,我在D3.js中有一个力定向图,其中节点半径与该数据的属性(例如,页面视图)成比例,链接宽度与链接数据的属性(例如,点击)成比例。我想给连接曲线一个方向指示器。问题是链接会移动到数据节点的中心,因此如果我使用标记end,我会得到: (数据节点通常使用链接到其他数据类别的颜色填充…) 我使用以下方法创建我的~~弧~~曲线: positionLink=(d)=>{ 常数偏移=100; 常量中点_x=(d.source.x+d.target.x)/2; 常量中点_y=(d.source.y+d.ta

我在D3.js中有一个力定向图,其中节点半径与该数据的属性(例如,页面视图)成比例,链接宽度与链接数据的属性(例如,点击)成比例。我想给连接曲线一个方向指示器。问题是链接会移动到数据节点的中心,因此如果我使用
标记end
,我会得到:

(数据节点通常使用链接到其他数据类别的颜色填充…)

我使用以下方法创建我的~~弧~~曲线:

positionLink=(d)=>{
常数偏移=100;
常量中点_x=(d.source.x+d.target.x)/2;
常量中点_y=(d.source.y+d.target.y)/2;
常数dx=d.source.x-d.target.x;
const dy=d.source.y-d.target.y;
//垂直向量
常数nx=-dy;
常数ny=dx;
常量norm_length=Math.sqrt((nx*nx)+(ny*ny));
常数normx=nx/标准长度;
常数normy=ny/标准长度;
const offset_x=parseFloat(中点_x+offset*normx.toFixed(2));
const offset_y=parseFloat(中点_y+offset*normy.toFixed(2));
const arc=`M${d.source.x.toFixed(2)}${d.source.y.toFixed(2)}S${offsetx}${offsety}${d.target.x.toFixed(2)}${d.target.y.toFixed(2)};
返回弧;
};
我的代码称之为
arc
的是一个SVG“S”路径,它是一个“平滑曲线”,但我并不特别喜欢它:我只需要将这些圆弧彼此拉开,这样我就可以显示数据在一个方向和另一个方向上的差异

如何定位贝塞尔曲线与圆的交点

(由于曲线的目标是圆的中心,我想这可以重新表述为“距离其终点
r
的贝塞尔曲线值”)

如果我有那一点,我可以使它成为箭头的顶点


(更好的是,如果我在该点有贝塞尔曲线的斜率,这样我就可以真正对齐它,但我认为我可以将它对齐到中点和锚点之间的直线上……)

考虑以下迭代方法:

使用,您可以遍历路径,直到找到与圆中心正好相距
r
的点,然后使用这些坐标重新绘制路径

const数据=[{
x:50,
y:100,
r:20
}, {
x:100,
y:30,
r:5
}];
常量链接=[{
来源:数据[0],
目标:数据[1]
},
{
资料来源:数据[1],
目标:数据[0]
}
];
位置链接=(源、目标)=>{
常数offsetPx=100;
常数中点={
x:(source.x+target.x)/2,
y:(源.y+目标.y)/2
};
常数dx=源.x-目标.x;
const dy=source.y-target.y;
//垂直向量
常数nx=-dy;
常数ny=dx;
常量norm_length=Math.sqrt((nx*nx)+(ny*ny));
常数normx=nx/标准长度;
常数normy=ny/标准长度;
常数偏移={
x:parseFloat(中点x+offsetPx*normx.toFixed(2)),
y:parseFloat(中点y+offsetPx*normy.toFixed(2)),
};
const arc=`M${source.x.toFixed(2)}${source.y.toFixed(2)}${S${offset.x}${offset.y}${target.x.toFixed(2)}${target.y.toFixed(2)};
返回弧;
};
欧几里德=(点,其他)=>Math.sqrt(点.x*other.x+point.y*other.y);
findPointAtLength=(路径、点、起点)=>{
//对于目标,我们需要从路径的另一边开始
设偏移量=点r;
if(fromEnd){
const totalLength=path.getTotalLength();
偏移=总长度-偏移;
}
让current=path.getPointAtLength(偏移量);
//逐渐增加偏移量,直到完全
//“r”远离圆心
while(欧几里德(点,当前)d.x)
.attr(“cy”,d=>d.y)
.attr(“r”,d=>d.r);
svg
.selectAll(“路径”)
.数据(链接)
.输入()
.append(“路径”)
.attr(“d”,位置链接标记)
.attr(“标记结束”、“url(#三角形)”)
g圆,
g路径{
填充:无;
笔画:黑色;
}