Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 523
Mopparthy Ravindranath Avatar asked Nov 28 '16 13:11

Mopparthy Ravindranath


People also ask

What is D3 SVG diagonal?

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.

How is SVG used with D3?

SVG stands for Scalable Vector Graphics. SVG is an XML-based vector graphics format. It provides options to draw different shapes such as Lines, Rectangles, Circles, Ellipses, etc. Hence, designing visualizations with SVG gives you more power and flexibility.

Does D3 use SVG or Canvas?

D3 charts are most often rendered using SVG, a retained mode graphics model, which is easy to use, but performance is limited. SVG charts can typically handle around 1,000 datapoints. Since D3 v4 you've also had the option to render charts using canvas, which is an immediate mode graphics model.

How will you invoke the link method while constructing a tree layout using D3?

In the update() function, links = d3. layout. tree(). links(nodes); is 'selecting' the nodes in the tree and their specified links in the JSON file.


3 Answers

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:

  • d3.linkHorizontal()
  • d3.linkVertical()
  • d3.linkRadial()

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:

var svg = d3.select("svg");

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

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

svg.append("path")
  .attr("d", link(data))
  .style("fill", "none")
  .style("stroke", "darkslateblue")
  .style("stroke-width", "4px");
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>
like image 168
Gerardo Furtado Avatar answered Oct 17 '22 21:10

Gerardo Furtado


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;
}
like image 31
Mark Avatar answered Oct 17 '22 20:10

Mark


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.

like image 17
Pete Adam Bialecki Avatar answered Oct 17 '22 21:10

Pete Adam Bialecki