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>