Where is d3.svg.diagonal()?

I was trying to execute the code of collapsible-tree as mentioned here. But it seems the diagonal method is not applicable in v4 (I may be wrong).

For:

var diagonal = d3.svg.diagonal()

I get this error:

TypeError: Cannot read property ‘diagonal’ of undefined

What is the equivalent in v4? Looking at d3.js API reference didn’t give me any clue.

Solution #1:

D3 version 4.9.0 introduced link shapes, which have the same functionality of the old d3.svg.diagonal in D3 v3.

According to the API:

The link shape generates a smooth cubic Bézier curve from a source point to a target point. The tangents of the curve at the start and end are either vertical, horizontal or radial.

There are three methods:

So, for a collapsible tree like that one you linked, you define the path d attribute as:

.attr("d", d3.linkHorizontal()
    .x(function(d) { return d.y; })
    .y(function(d) { return d.x; }));

Demo:

Suppose you have an object with source and target, each one with x and y properties:

var data = {
  source: {
    x: 20,
    y: 10
  },
  target: {
    x: 280,
    y: 100
  }
};

First, you create the link generator:

var link = d3.linkHorizontal()
  .x(function(d) {
    return d.x;
  })
  .y(function(d) {
    return d.y;
  });

And then you can draw the path just by passing that data to the link generator:

.attr("d", link(data))

Here is the demo:

Respondent: Gerardo Furtado

Solution #2:

See GitHub issue here.

While the issue is still open, it doesn’t seem that Mr. Bostock is in a rush to re-implement it in version 4. Why? Because it’s trivial to implement yourself:

function link(d) {
  return "M" + d.source.y + "," + d.source.x
      + "C" + (d.source.y + d.target.y) / 2 + "," + d.source.x
      + " " + (d.source.y + d.target.y) / 2 + "," + d.target.x
      + " " + d.target.y + "," + d.target.x;
}
Respondent: Mark

Solution #3:

I had a really hard time with this and then after a couple of hours, I realized how easy it really is (just like everyone else that mentions it). Replace:

var diagonal = d3.svg.diagonal()
  .projection(function(d) { return [d.y, d.x]; });

…with this:

var diagonal = function link(d) {
  return "M" + d.source.y + "," + d.source.x
      + "C" + (d.source.y + d.target.y) / 2 + "," + d.source.x
      + " " + (d.source.y + d.target.y) / 2 + "," + d.target.x
      + " " + d.target.y + "," + d.target.x;
};

That should be the only change. Hope this helps anyone else. This should work with a visualization like Patrick Brockman’s Collapsible/Searchable Tree.

Solution #4:

For those with vertical trees, the function below will yield curved diagonals such as shown in this example.

This function was modified from Mark’s answer by (1) switching the x and y calls, and (2) changing the calculated coordinates in the two middle lines. Without the coordinate change, the curve is inverted such as in this post.

var diagonal = function link(d) {
  return "M" + d.source.x + "," + d.source.y
      + "C" + d.source.x + "," + (d.source.y + d.target.y) / 2
      + " " + d.target.x + "," + (d.source.y + d.target.y) / 2
      + " " + d.target.x + "," + d.target.y;
};

As a side note, you can replace "C" with " " if you want boxy, instead of curved, edges.

Respondent: halcyon

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Leave a Reply

Your email address will not be published.