[d3-sankey] Update to Version 0.5 (#16761)

* [d3-sankey] Update to Version 0.5
* [BREAKING CHANGE] `SankeyLayout` API rewritten
* [BREAKING CHANGE] `SankeyLinkPathGenerator` removed. `sankeyLinkHorizontal` added as replacement.
* [CHORE] Update version numbers.

* [d3-sankey] JSDoc comment fixes. Thx @gustavderdrache
This commit is contained in:
Tom Wanzek
2017-06-01 12:30:55 -04:00
committed by Andy
parent 1b814e5ba7
commit cae1ec5491
2 changed files with 224 additions and 117 deletions

View File

@@ -8,6 +8,7 @@
import * as d3Sankey from 'd3-sankey';
import {select, Selection} from 'd3-selection';
import { Link } from 'd3-shape';
// ---------------------------------------------------------------------------
// Preparatory Steps
@@ -30,12 +31,12 @@ type SNode = d3Sankey.SankeyNode<SNodeExtra, SLinkExtra>;
type SLink = d3Sankey.SankeyLink<SNodeExtra, SLinkExtra>;
interface DAG {
nodes: SNode[];
links: SLink[];
customNodes: SNode[];
customLinks: SLink[];
}
const graph: DAG = {
nodes: [{
customNodes: [{
nodeId: 0,
name: "node0"
}, {
@@ -51,7 +52,7 @@ const graph: DAG = {
nodeId: 4,
name: "node4"
}],
links: [{
customLinks: [{
source: 0,
target: 2,
value: 2,
@@ -96,15 +97,18 @@ let num: number;
let numMaybe: number | undefined;
let str: string;
let size: [number, number];
let extent: [[number, number], [number, number]];
const svgLinkPaths = select<SVGSVGElement, undefined>('svg').selectAll<SVGPathElement, SLink>('.linkPath'); // assume mock DOM
let sGraph: d3Sankey.SankeyGraph<SNodeExtra, SLinkExtra>;
// ---------------------------------------------------------------------------
// Obtain SankeyLayout Generator
// ---------------------------------------------------------------------------
let slgDefault: d3Sankey.SankeyLayout<{}, {}> = d3Sankey.sankey();
let slgDAG: d3Sankey.SankeyLayout<SNodeExtra, SLinkExtra> = d3Sankey.sankey<SNodeExtra, SLinkExtra>();
let slgDefault: d3Sankey.SankeyLayout<d3Sankey.SankeyGraph<{}, {}>, {}, {}> = d3Sankey.sankey();
let slgDAG: d3Sankey.SankeyLayout<DAG, SNodeExtra, SLinkExtra> = d3Sankey.sankey<DAG, SNodeExtra, SLinkExtra>();
// ---------------------------------------------------------------------------
// NodeWidth
@@ -132,6 +136,19 @@ slgDAG = slgDAG.nodePadding(8);
num = slgDAG.nodePadding();
// ---------------------------------------------------------------------------
// Extent
// ---------------------------------------------------------------------------
// Set -----------------------------------------------------------------------
// test return type for chainability
slgDAG = slgDAG.extent([[0, 0], [1200, 800]]);
// Get -----------------------------------------------------------------------
extent = slgDAG.extent();
// ---------------------------------------------------------------------------
// Size
// ---------------------------------------------------------------------------
@@ -151,12 +168,15 @@ size = slgDAG.size();
// Set -----------------------------------------------------------------------
// test return type for chainability
slgDAG = slgDAG.nodes(graph.nodes);
// Use array and test return type for chainability
slgDAG = slgDAG.nodes(graph.customNodes);
// Use accessor function and test return type for chainability
slgDAG = slgDAG.nodes(d => d.customNodes);
// Get -----------------------------------------------------------------------
sNodes = slgDAG.nodes();
let nodesAccessor: (d: DAG) => SNode[] = slgDAG.nodes();
// ---------------------------------------------------------------------------
// Links
@@ -165,51 +185,59 @@ sNodes = slgDAG.nodes();
// Set -----------------------------------------------------------------------
// test return type for chainability
slgDAG = slgDAG.links(graph.links);
slgDAG = slgDAG.links(graph.customLinks);
// Use accessor function and test return type for chainability
slgDAG = slgDAG.links(d => d.customLinks);
// Get -----------------------------------------------------------------------
sLinks = slgDAG.links();
let linksAccessor: (d: DAG) => SLink[] = slgDAG.links();
// ---------------------------------------------------------------------------
// Compute Layout
// Compute Initial Layout
// ---------------------------------------------------------------------------
// test return type for chainability
slgDAG = slgDAG.layout(22);
sGraph = slgDAG(graph);
// With additional arguments, although here unused.
sGraph = slgDAG(graph, "foo", 50);
// ---------------------------------------------------------------------------
// Relayout
// Update Layout
// ---------------------------------------------------------------------------
// test return type for chainability
slgDAG = slgDAG.relayout();
sGraph = slgDAG.update(sGraph);
// ---------------------------------------------------------------------------
// Obtain and Use Link SVG Path Generator
// Obtain and Use Horizontal Link Path Generator
// ---------------------------------------------------------------------------
let pathGen: d3Sankey.SankeyLinkPathGenerator<SNodeExtra, SLinkExtra>;
let defaultPathGen: Link<any, d3Sankey.SankeyLink<{}, {}>, [number, number]>;
let pathGen: Link<any, SLink, [number, number]>;
pathGen = slgDAG.link();
defaultPathGen = d3Sankey.sankeyLinkHorizontal();
// Adjust Link SVG Path Generator curvature ----------------------------------
pathGen = d3Sankey.sankeyLinkHorizontal<SNodeExtra, SLinkExtra>();
// test return type
pathGen = pathGen.curvature(0.6);
num = pathGen.curvature();
// Render to svg path
// uses
let svgPathString: string = pathGen(slgDAG.links()[0]);
let svgPathString: string | null = pathGen(sGraph.links[0]);
svgLinkPaths.attr('d', pathGen);
// Render to canvas
declare const ctx: CanvasRenderingContext2D;
pathGen.context(ctx);
pathGen(sGraph.links[0]);
// ---------------------------------------------------------------------------
// Shape test Node/Link related interfaces and types
// ---------------------------------------------------------------------------
// Sankey Node --------------------------------------------------------------
sNodes = sGraph.nodes;
let sNode = sNodes[0];
// User-specified extra properties:
@@ -232,6 +260,7 @@ linksArrMaybe = sNode.targetLinks;
// Sankey Link --------------------------------------------------------------
sLinks = sGraph.links;
let sLink = sLinks[0];
// User-specified extra properties:

View File

@@ -1,14 +1,16 @@
// Type definitions for D3JS d3-sankey module 0.4
// Type definitions for D3JS d3-sankey module 0.5
// Project: https://github.com/d3/d3-sankey/
// Definitions by: Tom Wanzek <https://github.com/tomwanzek>, Alex Ford <https://github.com/gustavderdrache>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// Last module patch version validated against: 0.4.2
// Last module patch version validated against: 0.5
import { Link } from 'd3-shape';
/**
* A helper interface as an extension reference for user-provided properties of
* nodes and links in the graph, which are not required or calculated by
* the Sankey Layout Generator
* the Sankey layout Generator
*/
export interface SankeyExtraProperties { [key: string]: any; }
@@ -26,33 +28,34 @@ export interface SankeyExtraProperties { [key: string]: any; }
*/
export interface SankeyNodeMinimal<N extends SankeyExtraProperties, L extends SankeyExtraProperties> {
/**
* Array of links which have this node as their source.
* Array of outgoing links which have this node as their source.
* This property is calculated internally by the Sankey layout generator.
*/
sourceLinks?: Array<SankeyLink<N, L>>;
/**
* Array of links which have this node as their target.
* Array of incoming links which have this node as their target.
* This property is calculated internally by the Sankey layout generator.
*/
targetLinks?: Array<SankeyLink<N, L>>;
/**
* Node value calculated by Sankey Layout Generator based on values of incoming and outgoing links
* Node's value calculated by Sankey layout Generator;
* the sum of link.value for the nodes incoming links.
*/
value?: number;
/**
* Node horizontal position calculated by Sankey layout generator
* Node's horizontal position (derived from the graph topology) calculated by Sankey layout generator.
*/
x?: number;
/**
* Node width calculated by Sankey layout generator
* Node's node width calculated by Sankey layout generator.
*/
dx?: number;
/**
* Node vertical position (depth) calculated by Sankey layout generator
* Node's vertical position calculated by Sankey layout generator.
*/
y?: number;
/**
* Node height (vertical extent based on node value) calculated by Sankey layout generator
* Node's height (proportional to its value) calculated by Sankey layout generator.
*/
dy?: number;
}
@@ -85,31 +88,37 @@ export type SankeyNode<N extends SankeyExtraProperties, L extends SankeyExtraPro
*/
export interface SankeyLinkMinimal<N extends SankeyExtraProperties, L extends SankeyExtraProperties> {
/**
* Source node of the link. For convenience, when initializing a Sankey layout, source may be the index of the source node in the nodes array
* passed into the Sankey layout generator. Once the layout(...) method is invoked, the numeric index will be replaced with the corresponding
* source node object.
* Link's source node. For convenience, when initializing a Sankey layout,
* source may be the zero-based index of the corresponding node in the nodes array
* returned by the nodes accessor of the Sankey layout generator rather than object references.
*
* Once the Sankey generator is invoked to return the Sankey graph object,
* the numeric index will be replaced with the corresponding source node object.
*/
source: number | SankeyNode<N, L>;
/**
* Target node of the link. For convenience, when initializing a Sankey layout, target may be the index of the target node in the nodes array
* passed into the Sankey layout generator. Once the layout(...) method is invoked, the numeric index will be replaced with the corresponding
* target node object.
* Link's target node. For convenience, when initializing a Sankey layout,
* target may be the zero-based index of the corresponding node in the nodes array
* returned by the nodes accessor of the Sankey layout generator rather than object references.
*
* Once the Sankey generator is invoked to return the Sankey graph object,
* the numeric index will be replaced with the corresponding target node object.
*/
target: number | SankeyNode<N, L>;
/**
* Value of the link
* Link's numeric value
*/
value: number;
/**
* Link breadth calculated by Sankey layout generator based on the link value
* Link breadth (proportional to its value) calculated by Sankey layout generator.
*/
dy?: number;
/**
* Vertical starting position of the link (at source node) calculated by Sankey layout generator
* Link's vertical starting position (at source node) calculated by Sankey layout generator.
*/
sy?: number;
/**
* Vertical end position of the link (at target node) calculated by Sankey layout generator
* Link's vertical end position (at target node) calculated by Sankey layout generator.
*/
ty?: number;
}
@@ -129,32 +138,7 @@ export interface SankeyLinkMinimal<N extends SankeyExtraProperties, L extends Sa
export type SankeyLink<N extends SankeyExtraProperties, L extends SankeyExtraProperties> = L & SankeyLinkMinimal<N, L>;
/**
* An svg path generator factory for the link paths in a calculated Sankey Layout.
*/
export interface SankeyLinkPathGenerator<N extends SankeyExtraProperties, L extends SankeyExtraProperties> {
/**
* Return svg path string for a given link.
*
* IMPORTANT: Only invoke for link data with Sankey Layout information previously calculated.
*
* @param link A Sankey diagram link, for which the layout has already been calculated.
*/
(link: SankeyLink<N, L>): string;
/**
* Returns the current curvature used to calculate svg paths for links.
* The default curvature is 0.5.
*/
curvature(): number;
/**
* Set the curvature used to calculate svg paths for links and return the updated link path generator.
*
* @param curvature Curvature to be used when calculating svg paths for links. The default curvature is 0.5.
*/
curvature(curvature: number): this;
}
/**
* A Sankey layout generator.
* A Sankey Graph Object which contains the computed layout information for nodes and links.
*
* The first generic N refers to user-defined properties contained in the node data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
@@ -164,7 +148,90 @@ export interface SankeyLinkPathGenerator<N extends SankeyExtraProperties, L exte
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyLinkMinimal interface.
*/
export interface SankeyLayout<N extends SankeyExtraProperties, L extends SankeyExtraProperties> {
export interface SankeyGraph<N extends SankeyExtraProperties, L extends SankeyExtraProperties> {
/**
* Array of Sankey diagram nodes
*/
nodes: Array<SankeyNode<N, L>>;
/**
* Array of Sankey diagram links
*/
links: Array<SankeyLink<N, L>>;
}
/**
* A Sankey layout generator.
*
* The first generic Data refers to the data type of the first argument passed in when invoking the
* Sankey layout generator and internally the configured nodes/links accessor functions.
*
* The second generic N refers to user-defined properties contained in the node data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyNodeMinimal interface.
*
* The third generic L refers to user-defined properties contained in the link data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyLinkMinimal interface.
*/
export interface SankeyLayout<Data, N extends SankeyExtraProperties, L extends SankeyExtraProperties> {
/**
* Computes the node and link positions for the given arguments, returning a graph representing the Sankey layout.
*
* @param data Data object being passed as the first argument to the nodes and links accessor functions. Additional arguments will also be passed
* to the accessor functions.
*/
(data: Data, ...args: any[]): SankeyGraph<N, L>;
/**
* Recomputes the specified graphs links positions, updating the following properties of each link:
*
* - link.sy: the links vertical starting position (at source node)
* - link.ty: the links vertical end position (at target node)
*
* This method is intended to be called after computing the initial Sankey layout, for example when the diagram is repositioned interactively.
*
* @param graph
*/
update(graph: SankeyGraph<N, L>): SankeyGraph<N, L>;
/**
* Return the current nodes accessor function, which defaults to a function returning the "nodes" property of the
* first argument it is invoked with.
*/
nodes(): (data: Data, ...args: any[]) => Array<SankeyNode<N, L>>;
/**
* Set the Sankey generator's nodes accessor to a function returning the specified array of objects and returns this Sankey layout generator.
*
* @param nodes Array of nodes.
*/
nodes(nodes: Array<SankeyNode<N, L>>): this;
/**
* Set the Sankey generator's nodes accessor to the specified function and returns this Sankey layout generator.
*
* @param nodes A nodes accessor function. The function is invoked when the Sankey layout is generated, being passed any arguments passed to the Sankey generator.
* This function must return an array of nodes.
*/
nodes(nodes: (data: Data, ...args: any[]) => Array<SankeyNode<N, L>>): this;
/**
* Return the current links accessor function, which defaults to a function returning the "links" property of the
* first argument it is invoked with.
*/
links(): (data: Data, ...args: any[]) => Array<SankeyLink<N, L>>;
/**
* Set the Sankey generator's links accessor to a function returning the specified array of objects and returns this Sankey layout generator.
*
* @param links Array of links.
*/
links(links: Array<SankeyLink<N, L>>): this;
/**
* Set the Sankey generator's links accessor to the specified function and returns this Sankey layout generator.
*
* @param links A links accessor function. The function is invoked when the Sankey layout is generated, being passed any arguments passed to the Sankey generator.
* This function must return an array of links.
*/
links(links: (data: Data, ...args: any[]) => Array<SankeyLink<N, L>>): this;
/**
* Return the current node width, which defaults to 24.
*/
@@ -183,48 +250,23 @@ export interface SankeyLayout<N extends SankeyExtraProperties, L extends SankeyE
*/
nodePadding(): number;
/**
* Set the node padding to the specified number and return this Sankey layout generator.
* Set the vertical separation between nodes at each column to the specified number and return this Sankey layout generator.
*
* Node padding refers to the vertical space between nodes which occupy the same horizontal space.
*
* @param padding Node padding in pixels, which defaults to 8.
* @param padding Node padding, i.e. vertical separation between nodes at each column, in pixels, which defaults to 8.
*/
nodePadding(padding: number): this;
/**
* Return the current array of nodes, which defaults to [].
* Return the current extent which defaults to [[0, 0], [1, 1]].
*/
nodes(): Array<SankeyNode<N, L>>;
extent(): [[number, number], [number, number]];
/**
* Set the sankey generator's nodes to the specified array of objects and returns this sankey layout generator.
* Set the extent of the Sankey layout to the specified bounds and returns this Sankey layout generator.
*
* @param nodes Array of nodes.
* @param extent Extent bounds for the layout. The extent bounds are specified as an array [[x0, y0], [x1, y1]],
* where x0 is the left side of the extent, y0 is the top, x1 is the right and y1 is the bottom. The default is [[0, 0], [1, 1]].
*/
nodes(nodes: Array<SankeyNode<N, L>>): this;
/**
* Return the current array of links, which defaults to [].
*/
links(): Array<SankeyLink<N, L>>;
/**
* Set the sankey generator's links to the specified array of objects and returns this sankey layout generator.
*
* @param links Array of links.
*/
links(links: Array<SankeyLink<N, L>>): this;
/**
* Runs the sankey layout algorithm updating the nodes and links with their respective layout information and returns this sankey generator.
*
* @param iterations Number of passes to be used in the iterative relaxation algorithm for node placement.
*/
layout(iterations: number): this;
/**
* Recalculate the depth of links and return this Sankey layout generator.
* This methods is primarily used when a node is moved vertically, e.g. using d3-drag.
*/
relayout(): this;
extent(extent: [[number, number], [number, number]]): this;
/**
* Return the current layout size in pixels. The size is a two element array of [width, height] which defaults to [1, 1].
@@ -232,18 +274,11 @@ export interface SankeyLayout<N extends SankeyExtraProperties, L extends SankeyE
size(): [number, number];
/**
* Set the size of the layout and return this Sankey layout generator.
* This convenience method is equivalent to using extent([[0, 0], [width, height]]).
*
* @param size A two element array of [width, height] in pixels which defaults to [1, 1].
*/
size(size: [number, number]): this;
/**
* Return a Sankey link path generator for the links based on the calculated Sankey diagram layout.
* The link path generator can be invoked as a function being passed as its argument a link object
* with calculated layout information. It returns the computed <svg> path string for the link.
* By default the link path generator uses a curvature of 0.5.
*/
link(): SankeyLinkPathGenerator<N, L>;
}
/**
@@ -251,11 +286,15 @@ export interface SankeyLayout<N extends SankeyExtraProperties, L extends SankeyE
*
* Invoking sankey() without generics, means the node type and link type assume no user-defined attributes, i.e.
* only the attributes internally used by the Sankey layout generator.
*
* Default nodes/links accessors are assumed.
*/
export function sankey(): SankeyLayout<{}, {}>;
export function sankey(): SankeyLayout<SankeyGraph<{}, {}>, {}, {}>;
/**
* Get a Sankey layout generator.
*
* Default nodes/links accessors are assumed.
*
* The first generic N refers to user-defined properties contained in the node data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyNodeMinimal interface.
@@ -264,4 +303,43 @@ export function sankey(): SankeyLayout<{}, {}>;
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyLinkMinimal interface.
*/
export function sankey<N extends SankeyExtraProperties, L extends SankeyExtraProperties>(): SankeyLayout<N, L>;
export function sankey<N extends SankeyExtraProperties, L extends SankeyExtraProperties>(): SankeyLayout<SankeyGraph<N, L>, N, L>;
/**
* Get a Sankey layout generator.
*
* The nodes/links accessors need to be configured to work with the data type of the first argument passed
* in when invoking the Sankey lyout generator.
*
* The first generic corresponds to the data type of the first argument passed in when invoking the Sankey layout generator,
* and its nodes/links accessors.
*
* The second generic N refers to user-defined properties contained in the node data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyNodeMinimal interface.
*
* The third generic L refers to user-defined properties contained in the link data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyLinkMinimal interface.
*/
export function sankey<Data, N extends SankeyExtraProperties, L extends SankeyExtraProperties>(): SankeyLayout<Data, N, L>;
/**
* Get a horizontal link shape suitable for a Sankey diagram.
* Source and target accessors are pre-configured and work with the
* default x- and y- accessors of the link shape generator.
*/
export function sankeyLinkHorizontal(): Link<any, SankeyLink<{}, {}>, [number, number]>;
/**
* Get a horizontal link shape suitable for a Sankey diagram.
* Source and target accessors are pre-configured and work with the
* default x- and y- accessors of the link shape generator.
*
* The first generic N refers to user-defined properties contained in the node data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyNodeMinimal interface.
*
* The second generic L refers to user-defined properties contained in the link data passed into
* Sankey layout generator. These properties are IN EXCESS to the properties explicitly identified in the
* SankeyLinkMinimal interface.
*/
export function sankeyLinkHorizontal<N extends SankeyExtraProperties, L extends SankeyExtraProperties>(): Link<any, SankeyLink<N, L>, [number, number]>;