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

Add support for additional Sankey diagram orientations #71

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8de4751
Remove horizontal-only assumption from filenames, exports
jayaddison Jan 8, 2020
cc7805a
Add no-op library-internal 'horizontal' orientation
jayaddison Jan 8, 2020
ee1f37b
Add and export 'vertical' orientation
jayaddison Jan 8, 2020
a26355e
Add linkShape utility function
jayaddison Jan 8, 2020
3f63c25
Orient extents before calculating node positions
jayaddison Jan 8, 2020
584ca50
Update README.
jayaddison Jan 9, 2020
d94e35c
Remove ES6 destructuring assignments
jayaddison Jan 15, 2020
9cfd337
Rename {horizontal, vertical} -> {sankeyHorizontal, sankeyVertical}
jayaddison Jan 15, 2020
bcdabc2
Add nodeOrientation function docs, rendered examples
jayaddison Jan 15, 2020
66afca1
Re-arrange README to improve diff clarity
jayaddison Jan 15, 2020
d49ea06
Enable node re-orientation for individual axis values instead of co-o…
jayaddison Sep 10, 2020
58b77c6
Refactor: include concept of direction for orientation
jayaddison Sep 10, 2020
bd170ab
Add left & up orientations
jayaddison Sep 10, 2020
4aec193
Ensure link width is positive
jayaddison Sep 10, 2020
b8a5222
Implement orientation-specific rendering without collision detection
jayaddison Sep 10, 2020
0cf48c2
Enable orientation-specific collision detection
jayaddison Sep 10, 2020
331af05
Update README orientation documentation
jayaddison Sep 10, 2020
0267ad8
Revert "Ensure link width is positive"
jayaddison Sep 10, 2020
d813a6b
Nit: spacing consistency fixup
jayaddison Sep 11, 2020
863b185
Nit: rename variable z -> ymax to remove dimenson-name ambiguity
jayaddison Sep 11, 2020
f603a6c
Revert "Nit: spacing consistency fixup"
jayaddison Sep 11, 2020
5fbbf1b
Refactor:
jayaddison Sep 14, 2020
e70b772
Bounds checking: check both lower and upper bounds during node collis…
jayaddison Sep 14, 2020
9d3dc99
Merge branch 'collision-bounds-checking' into vertical-orientation
jayaddison Sep 14, 2020
332e27b
Update README
jayaddison Sep 14, 2020
ac05124
Nit: brevity during alignment checks
jayaddison Sep 14, 2020
898a673
Nit: attempt to further clarify distinct variable names
jayaddison Sep 14, 2020
ebfda16
Rename variable: orient -> orientation
jayaddison Nov 11, 2020
d674a34
Rename variables: ystart, yend -> yStart, yEnd
jayaddison Nov 11, 2020
1968a46
Use 'const' declaration for static module-level variables
jayaddison Nov 11, 2020
41d6b59
Fixup: documentation hyperlinks
jayaddison Feb 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ For convenience, a link’s source and target may be initialized using numeric o
* *link*.width - the link’s width (proportional to *link*.value)
* *link*.index - the zero-based index of *link* within the array of links

<a name="sankey_linkShape" href="#sankey_linkShape">#</a> <i>sankey</i>.<b>linkShape</b>() [<>](https://github.com/d3/d3-sankey/blob/master/src/sankey.js "Source")

Returns a [link shape](https://github.com/d3/d3-shape#links) suitable for rendering paths between the nodes of this Sankey diagram. This will return either a [horizontal](#sankeyLinkHorizontal) or [vertical](#sankeyLinkVertical) link shape.

<a name="sankey_linkSort" href="#sankey_linkSort">#</a> <i>sankey</i>.<b>linkSort</b>([<i>sort</i>]) [<>](https://github.com/d3/d3-sankey/blob/master/src/sankey.js "Source")

If *sort* is specified, sets the link sort method and returns this Sankey generator. If *sort* is not specified, returns the current link sort method, which defaults to *undefined*, indicating that vertical order of links within each node will be determined automatically by the layout. If *sort* is null, the order is fixed by the input. Otherwise, the specified *sort* function determines the order; the function is passed two links, and must return a value less than 0 if the first link should be above the second, and a value greater than 0 if the second link should be above the first, or 0 if the order is not specified.
Expand Down Expand Up @@ -216,23 +220,13 @@ Like [d3.sankeyLeft](#sankeyLeft), except that nodes without any outgoing links

### Links

<a name="sankeyLinkHorizontal" href="#sankeyLinkHorizontal">#</a> d3.<b>sankeyLinkHorizontal</b>() [<>](https://github.com/d3/d3-sankey/blob/master/src/sankeyLinkHorizontal.js "Source")
<a name="sankeyLinkHorizontal" href="#sankeyLinkHorizontal">#</a> d3.<b>sankeyLinkHorizontal</b>() [<>](https://github.com/d3/d3-sankey/blob/master/src/sankeyLink.js "Source")

Returns a [horizontal link shape](https://github.com/d3/d3-shape/blob/master/README.md#linkHorizontal) suitable for a Sankey diagram. The [source accessor](https://github.com/d3/d3-shape/blob/master/README.md#link_source) is defined as:
Returns a [horizontal link shape](https://github.com/d3/d3-shape/blob/master/README.md#linkHorizontal) suitable for a Sankey diagram rendered in a horizontal orientation.

```js
function source(d) {
jayaddison marked this conversation as resolved.
Show resolved Hide resolved
return [d.source.x1, d.y0];
}
```
<a name="sankeyLinkVertical" href="#sankeyLinkVertical">#</a> d3.<b>sankeyLinkVertical</b>() [<>](https://github.com/d3/d3-sankey/blob/master/src/sankeyLink.js "Source")

The [target accessor](https://github.com/d3/d3-shape/blob/master/README.md#link_target) is defined as:

```js
function target(d) {
return [d.target.x0, d.y1];
}
```
Returns a [vertical link shape](https://github.com/d3/d3-shape/blob/master/README.md#linkVertical) suitable for a Sankey diagram rendered in a vertical orientation.

For example, to render the links of a Sankey diagram in SVG, you might say:

Expand All @@ -244,6 +238,6 @@ svg.append("g")
.selectAll("path")
.data(graph.links)
.join("path")
.attr("d", d3.sankeyLinkHorizontal())
.attr("d", graph.linkShape())
.attr("stroke-width", function(d) { return d.width; });
```
3 changes: 2 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export {default as sankey} from "./sankey.js";
export {center as sankeyCenter, left as sankeyLeft, right as sankeyRight, justify as sankeyJustify} from "./align.js";
export {default as sankeyLinkHorizontal} from "./sankeyLinkHorizontal.js";
export {horizontal, vertical} from "./orientation.js";
export {sankeyLinkHorizontal, sankeyLinkVertical} from "./sankeyLink.js";
7 changes: 7 additions & 0 deletions src/orientation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function horizontal(x, y) {
return [x, y];
}

export function vertical(x, y) {
return [y, x];
}
25 changes: 25 additions & 0 deletions src/sankey.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {max, min, sum} from "d3-array";
import {justify} from "./align.js";
import {horizontal, vertical} from "./orientation.js";
import {sankeyLinkHorizontal, sankeyLinkVertical} from "./sankeyLink.js";
import constant from "./constant.js";

function ascendingSourceBreadth(a, b) {
Expand Down Expand Up @@ -51,12 +53,20 @@ function computeLinkBreadths({nodes}) {
}
}

function orientNodes({nodes}, orientation) {
for (const node of nodes) {
[node.x0, node.y0] = orientation(node.x0, node.y0);
[node.x1, node.y1] = orientation(node.x1, node.y1);
jayaddison marked this conversation as resolved.
Show resolved Hide resolved
}
}

export default function Sankey() {
let x0 = 0, y0 = 0, x1 = 1, y1 = 1; // extent
let dx = 24; // nodeWidth
let dy = 8, py; // nodePadding
let id = defaultId;
let align = justify;
let orientation = horizontal;
let sort;
let linkSort;
let nodes = defaultNodes;
Expand All @@ -65,15 +75,22 @@ export default function Sankey() {

function sankey() {
const graph = {nodes: nodes.apply(null, arguments), links: links.apply(null, arguments)};
orientExtents();
computeNodeLinks(graph);
computeNodeValues(graph);
computeNodeDepths(graph);
computeNodeHeights(graph);
computeNodeBreadths(graph);
computeLinkBreadths(graph);
orientNodes(graph, orientation);
return graph;
}

function orientExtents() {
[x0, y0] = orientation(x0, y0);
[x1, y1] = orientation(x1, y1);
}

sankey.update = function(graph) {
computeLinkBreadths(graph);
return graph;
Expand All @@ -87,6 +104,10 @@ export default function Sankey() {
return arguments.length ? (align = typeof _ === "function" ? _ : constant(_), sankey) : align;
};

sankey.nodeOrientation = function(_) {
return arguments.length ? (orientation = _, sankey) : orientation;
};

sankey.nodeSort = function(_) {
return arguments.length ? (sort = _, sankey) : sort;
};
Expand All @@ -107,6 +128,10 @@ export default function Sankey() {
return arguments.length ? (links = typeof _ === "function" ? _ : constant(_), sankey) : links;
};

sankey.linkShape = function() {
return orientation === vertical ? sankeyLinkVertical() : sankeyLinkHorizontal();
};

sankey.linkSort = function(_) {
return arguments.length ? (linkSort = _, sankey) : linkSort;
};
Expand Down
29 changes: 29 additions & 0 deletions src/sankeyLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {linkHorizontal, linkVertical} from "d3-shape";

function horizontalSource(d) {
return [d.source.x1, d.y0];
}

function horizontalTarget(d) {
return [d.target.x0, d.y1];
}

export function sankeyLinkHorizontal() {
return linkHorizontal()
.source(horizontalSource)
jayaddison marked this conversation as resolved.
Show resolved Hide resolved
.target(horizontalTarget);
}

function verticalSource(d) {
return [d.y0, d.source.y1];
}

function verticalTarget(d) {
return [d.y1, d.target.y0];
}

export function sankeyLinkVertical() {
return linkVertical()
.source(verticalSource)
.target(verticalTarget);
}
15 changes: 0 additions & 15 deletions src/sankeyLinkHorizontal.js

This file was deleted.