Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link (diagonal)? #27

Closed
mbostock opened this issue Nov 18, 2015 · 15 comments
Closed

Link (diagonal)? #27

mbostock opened this issue Nov 18, 2015 · 15 comments
Assignees

Comments

@mbostock
Copy link
Member

It’s quite likely we actually want to call this a link (shape) and put it in the d3-hierarchy module, since this shape is typically used to represent links in hierarchical visualizations.

@mbostock mbostock self-assigned this Nov 30, 2015
@mbostock mbostock changed the title Diagonal. Link (diagonal)? Dec 4, 2015
@mbostock mbostock removed their assignment Dec 4, 2015
@mbostock mbostock closed this as completed Dec 5, 2015
@mbostock
Copy link
Member Author

mbostock commented Jun 22, 2016

I dunno… Seems pretty generic and this seems like a reasonable place for it.

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;
}

@mbostock mbostock reopened this Jun 22, 2016
@mbostock
Copy link
Member Author

Also if you want it to render to both Canvas and SVG, then it becomes even more tedious to not have this available in d3-shape.

@ZephryL
Copy link

ZephryL commented Jul 1, 2016

Hi there Mike. I use the svg.diagonal to associate arbitrary shapes (i.e. not necessarily links in a formal hierarchy) like this:
var diagonal = d3.svg.diagonal().projection(function (d) { return [d.y, d.x]; });
I'm at a loss as to how I would implement this behavior in version 4. How would you suggest I go about this?
Thanks!

@ZephryL
Copy link

ZephryL commented Jul 1, 2016

Sorry Mike, I was being a dork. Sorted with your simple link(d) function, which I initially ignored. Apologies

@brettbibby
Copy link

I'm not understanding this exchange very well between you guys.

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

New???

Sorry to disturb!

@mbostock
Copy link
Member Author

mbostock commented Jul 6, 2016

Here are some examples…

@brettbibby
Copy link

Perfect, thanks!

@ZephryL
Copy link

ZephryL commented Jul 6, 2016

Thanks you Mike. Appreciate your time.

@mbostock
Copy link
Member Author

It’s trivial to adjust that line function definition for V4:

var line = d3.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y; })
    .curve(d3.curveLinear);

The rest of what you described is unchanged.

@mbostock mbostock self-assigned this Oct 27, 2016
@mbostock
Copy link
Member Author

The simplest option here is to have two variants of a link shape: one with vertical tangents and one with horizontal tangents:

function linkHorizontal(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;
}

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

Then, in conjunction with d3/d3-hierarchy#63, it becomes much easier to change the orientation of a hierarchical layout and its links without the complexity of diagonal.projection from 3.x.

There’s a related question whether we want the midpoint of the link to be configurable: should it be specified as a parameter t in [0, 1], or as a fixed offset from the source or target? Of course, it’s probably sufficient to just keep it simple and not configurable. But if we want to be forwards-compatible then linkVertical should return a link generator function (like d3.line) rather than being a static, non-configurable shape generator.

@mbostock
Copy link
Member Author

We will also need a radial link.

@gauravtyagi77
Copy link

Hi @mbostock,

In my code written by someone else earlier for rendering d3-sankey with d3 v3 js by using diagonal is given below.

var path = d3.svg.diagonal()
.source(function(d) {
return {"x":d.source.y + d.source.dy / 2,
"y":d.source.x + sankey.nodeWidth()/2};
})
.target(function(d) {
return {"x":d.target.y + d.target.dy / 2,
"y":d.target.x + sankey.nodeWidth()/2};
})
.projection(function(d) { return [d.y, d.x]; });

Can you help me how should I replace my calculation with your.

@ialarmedalien
Copy link

Would it be possible to expose a generic link generator function that could be supplied with custom directions for creating the link? Use case is generating more complex L-shaped and dogleg links, both with straight lines and with arcs. I have some old d3 v3-compatible code that currently generates the links using string concatenation, but it would be really nice to use pathTo, arcTo, and so on instead, without having to compile my own custom module that copies most of the contents of link().

@Malex
Copy link

Malex commented Mar 26, 2019

I read all the exchange, and while I am an happy user of linkVertical/Horizontal and such, I'm having trouble implementing a different kinda of connection, as per example http://bl.ocks.org/jdarling/2503502
Is there an API I'm missing to get something similar?

@specialCoder
Copy link

specialCoder commented Apr 11, 2019

I dunno… Seems pretty generic and this seems like a reasonable place for it.

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;

Horizontal:

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}`;
  }

Vertical:

function link(d) {
    return `M${d.source.x},${d.source.y}C${(d.source.x + d.target.x) / 2},${d.target.y} ${(d.source.x + d.target.x) / 2},${d.source.y} ${d.target.x},${d.target.y}`;
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

7 participants