首页 > 解决方案 > 努力在 D3 中使用贝塞尔曲线实现连接器路径

问题描述

我正在尝试使用 D3 创建一个粗略的数据库图表生成器,但我不知道如何在字段之间获取连接器。我可以从两点得到直线,但我希望它是圆形的,就像我猜的一条路径。

我试图把这个特定问题的一个例子放在一起,链接两个文本字段:

https://codesandbox.io/s/gifted-bardeen-5hbw2?fontsize=14&hidenavigation=1&theme=dark

这是我所指的 dbdiagram.io 的一个示例:

来自另一个站点的示例

我一直在阅读 d 属性和各种命令,但似乎没有什么更接近。我怀疑该forceSimulation方法,尤其是forceCenter当我使用小写命令时,该函数可能会弄乱相对定位。但不是100%。

标签: javascriptsvgd3.js

解决方案


您可以通过connectorPath例程计算 2 点之间的连接器路径:

const source = {x: 200, y: 120};
const target = {x: 50, y: 20};
const MAX_RADIUS = 15;

const connectorPath = (from, to) => {
    if (from.y === to.y || from.x === to.x) 
    return `M ${from.x},${from.y} L ${to.x},${to.y}`;
    
    const middle = (from.x + to.x) / 2;
  const xFlag = from.x < to.x ? 1 : -1;
  const yFlag = from.y < to.y ? 1 : -1;
  const dX = Math.abs(from.x - to.x);
  const dY = Math.abs(from.y - to.y);
  const radius = Math.min(dX / 2, dY / 2, MAX_RADIUS);
  return `M ${from.x},${from.y} H ${middle - radius * xFlag} Q ${middle},${from.y} ${middle},${from.y + radius * yFlag} V ${to.y - radius * yFlag} Q ${middle},${to.y} ${middle + radius * xFlag},${to.y} H ${to.x}`;
};

d3.select('#source').attr('cx', source.x).attr('cy', source.y);
d3.select('#target').attr('cx', target.x).attr('cy', target.y);
d3.select('#connector').attr('d', connectorPath(source, target));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="300" height="200">
  <path id="connector" stroke="blue" fill="none" />
  <circle id="source" fill="red" r="5"/>
  <circle id="target" fill="green" r="5"/>
</svg>


推荐阅读