score:1

Eventually, I came up with this function that solves the goal of using both d3.line() and d3.linkHorizontal(). The key was to use a implementation of d3.DefaultLinkObject so that I could use the original source and target passed by attr("d", f(d)).

So, if it helps anybody:

class myLinkObject implements d3.DefaultLinkObject {
    public source: [number, number];
    public target: [number, number];
    constructor(s: [number, number], t: [number, number]) {
        this.source = s;
        this.target = t;
    }
}

function linkGenerator(d) {

   var deltaX = self.settings.nodes.width / 2;

   var pSource: [number, number] = [self.orientation.x(d.source) + deltaX, self.orientation.y(d.source);
   var pTarget: [number, number] = [self.orientation.x(d.target) - deltaX, self.orientation.y(d.target);

   var points = [pSource, pTarget];
   var linkObject: myLinkObject = new myLinkObject(pSource, pTarget);
   var path = "";

  if (self.settings.links.style == "step") {

      var lineGenerator = d3.line().curve(d3.curveStep);
      path = lineGenerator(points);

   } else if (self.settings.links.style == "diagonal") {

      var lineGenerator = d3.line();
      path = lineGenerator(points);

   } else {  // bezier

      var linkGen = d3.linkHorizontal().x(d => d[0]).y(d => d[1]);
      path = linkGen(linkObject);
   }
            
   return path;
}

score:2

Here is a simple Bezier curve function to use instead of the D3's:

const getBezierPath = (from, to) => {
    if (Math.abs(from.x - to.x) > Math.abs(from.y - to.y)) {
    const midX = (to.x + from.x) / 2;
    return `M ${from.x},${from.y} C ${midX},${from.y} ${midX},${to.y} ${to.x},${to.y}`;
  } else {
    const midY = (to.y + from.y) / 2;
    return `M ${from.x},${from.y} C ${from.x},${midY} ${to.x},${midY} ${to.x},${to.y}`;
  }
};

See a demo in a fiddle


Related Query

More Query from same tag