| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- // https://github.com/d3/d3-sankey Version 0.7.1. Copyright 2017 Mike Bostock.
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-collection'), require('d3-shape')) :
- typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-collection', 'd3-shape'], factory) :
- (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3));
- }(this, (function (exports,d3Array,d3Collection,d3Shape) { 'use strict';
- function targetDepth(d) {
- return d.target.depth;
- }
- function left(node) {
- return node.depth;
- }
- function right(node, n) {
- return n - 1 - node.height;
- }
- function justify(node, n) {
- return node.sourceLinks.length ? node.depth : n - 1;
- }
- function center(node) {
- return node.targetLinks.length ? node.depth
- : node.sourceLinks.length ? d3Array.min(node.sourceLinks, targetDepth) - 1
- : 0;
- }
- function constant(x) {
- return function() {
- return x;
- };
- }
- function ascendingSourceBreadth(a, b) {
- return ascendingBreadth(a.source, b.source) || a.index - b.index;
- }
- function ascendingTargetBreadth(a, b) {
- return ascendingBreadth(a.target, b.target) || a.index - b.index;
- }
- function ascendingBreadth(a, b) {
- return a.y0 - b.y0;
- }
- function value(d) {
- return d.value;
- }
- function nodeCenter(node) {
- return (node.y0 + node.y1) / 2;
- }
- function weightedSource(link) {
- return nodeCenter(link.source) * link.value;
- }
- function weightedTarget(link) {
- return nodeCenter(link.target) * link.value;
- }
- function defaultId(d) {
- return d.index;
- }
- function defaultNodes(graph) {
- return graph.nodes;
- }
- function defaultLinks(graph) {
- return graph.links;
- }
- function find(nodeById, id) {
- var node = nodeById.get(id);
- if (!node) throw new Error("missing: " + id);
- return node;
- }
- var sankey = function() {
- var x0 = 0, y0 = 0, x1 = 1, y1 = 1, // extent
- dx = 24, // nodeWidth
- py = 8, // nodePadding
- id = defaultId,
- align = justify,
- nodes = defaultNodes,
- links = defaultLinks,
- iterations = 32;
- function sankey() {
- var graph = {nodes: nodes.apply(null, arguments), links: links.apply(null, arguments)};
- computeNodeLinks(graph);
- computeNodeValues(graph);
- computeNodeDepths(graph);
- computeNodeBreadths(graph, iterations);
- computeLinkBreadths(graph);
- return graph;
- }
- sankey.update = function(graph) {
- computeLinkBreadths(graph);
- return graph;
- };
- sankey.nodeId = function(_) {
- return arguments.length ? (id = typeof _ === "function" ? _ : constant(_), sankey) : id;
- };
- sankey.nodeAlign = function(_) {
- return arguments.length ? (align = typeof _ === "function" ? _ : constant(_), sankey) : align;
- };
- sankey.nodeWidth = function(_) {
- return arguments.length ? (dx = +_, sankey) : dx;
- };
- sankey.nodePadding = function(_) {
- return arguments.length ? (py = +_, sankey) : py;
- };
- sankey.nodes = function(_) {
- return arguments.length ? (nodes = typeof _ === "function" ? _ : constant(_), sankey) : nodes;
- };
- sankey.links = function(_) {
- return arguments.length ? (links = typeof _ === "function" ? _ : constant(_), sankey) : links;
- };
- sankey.size = function(_) {
- return arguments.length ? (x0 = y0 = 0, x1 = +_[0], y1 = +_[1], sankey) : [x1 - x0, y1 - y0];
- };
- sankey.extent = function(_) {
- return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], sankey) : [[x0, y0], [x1, y1]];
- };
- sankey.iterations = function(_) {
- return arguments.length ? (iterations = +_, sankey) : iterations;
- };
- // Populate the sourceLinks and targetLinks for each node.
- // Also, if the source and target are not objects, assume they are indices.
- function computeNodeLinks(graph) {
- graph.nodes.forEach(function(node, i) {
- node.index = i;
- node.sourceLinks = [];
- node.targetLinks = [];
- });
- var nodeById = d3Collection.map(graph.nodes, id);
- graph.links.forEach(function(link, i) {
- link.index = i;
- var source = link.source, target = link.target;
- if (typeof source !== "object") source = link.source = find(nodeById, source);
- if (typeof target !== "object") target = link.target = find(nodeById, target);
- source.sourceLinks.push(link);
- target.targetLinks.push(link);
- });
- }
- // Compute the value (size) of each node by summing the associated links.
- function computeNodeValues(graph) {
- graph.nodes.forEach(function(node) {
- node.value = Math.max(
- d3Array.sum(node.sourceLinks, value),
- d3Array.sum(node.targetLinks, value)
- );
- });
- }
- // Iteratively assign the depth (x-position) for each node.
- // Nodes are assigned the maximum depth of incoming neighbors plus one;
- // nodes with no incoming links are assigned depth zero, while
- // nodes with no outgoing links are assigned the maximum depth.
- function computeNodeDepths(graph) {
- var nodes, next, x;
- for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) {
- nodes.forEach(function(node) {
- node.depth = x;
- node.sourceLinks.forEach(function(link) {
- if (next.indexOf(link.target) < 0) {
- next.push(link.target);
- }
- });
- });
- }
- for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) {
- nodes.forEach(function(node) {
- node.height = x;
- node.targetLinks.forEach(function(link) {
- if (next.indexOf(link.source) < 0) {
- next.push(link.source);
- }
- });
- });
- }
- var kx = (x1 - x0 - dx) / (x - 1);
- graph.nodes.forEach(function(node) {
- node.x1 = (node.x0 = x0 + Math.max(0, Math.min(x - 1, Math.floor(align.call(null, node, x)))) * kx) + dx;
- });
- }
- function computeNodeBreadths(graph) {
- var columns = d3Collection.nest()
- .key(function(d) { return d.x0; })
- .sortKeys(d3Array.ascending)
- .entries(graph.nodes)
- .map(function(d) { return d.values; });
- //
- initializeNodeBreadth();
- resolveCollisions();
- for (var alpha = 1, n = iterations; n > 0; --n) {
- relaxRightToLeft(alpha *= 0.99);
- resolveCollisions();
- relaxLeftToRight(alpha);
- resolveCollisions();
- }
- function initializeNodeBreadth() {
- var ky = d3Array.min(columns, function(nodes) {
- return (y1 - y0 - (nodes.length - 1) * py) / d3Array.sum(nodes, value);
- });
- columns.forEach(function(nodes) {
- nodes.forEach(function(node, i) {
- node.y1 = (node.y0 = i) + node.value * ky;
- });
- });
- graph.links.forEach(function(link) {
- link.width = link.value * ky;
- });
- }
- function relaxLeftToRight(alpha) {
- columns.forEach(function(nodes) {
- nodes.forEach(function(node) {
- if (node.targetLinks.length) {
- var dy = (d3Array.sum(node.targetLinks, weightedSource) / d3Array.sum(node.targetLinks, value) - nodeCenter(node)) * alpha;
- node.y0 += dy, node.y1 += dy;
- }
- });
- });
- }
- function relaxRightToLeft(alpha) {
- columns.slice().reverse().forEach(function(nodes) {
- nodes.forEach(function(node) {
- if (node.sourceLinks.length) {
- var dy = (d3Array.sum(node.sourceLinks, weightedTarget) / d3Array.sum(node.sourceLinks, value) - nodeCenter(node)) * alpha;
- node.y0 += dy, node.y1 += dy;
- }
- });
- });
- }
- function resolveCollisions() {
- columns.forEach(function(nodes) {
- var node,
- dy,
- y = y0,
- n = nodes.length,
- i;
- // Push any overlapping nodes down.
- nodes.sort(ascendingBreadth);
- for (i = 0; i < n; ++i) {
- node = nodes[i];
- dy = y - node.y0;
- if (dy > 0) node.y0 += dy, node.y1 += dy;
- y = node.y1 + py;
- }
- // If the bottommost node goes outside the bounds, push it back up.
- dy = y - py - y1;
- if (dy > 0) {
- y = (node.y0 -= dy), node.y1 -= dy;
- // Push any overlapping nodes back up.
- for (i = n - 2; i >= 0; --i) {
- node = nodes[i];
- dy = node.y1 + py - y;
- if (dy > 0) node.y0 -= dy, node.y1 -= dy;
- y = node.y0;
- }
- }
- });
- }
- }
- function computeLinkBreadths(graph) {
- graph.nodes.forEach(function(node) {
- node.sourceLinks.sort(ascendingTargetBreadth);
- node.targetLinks.sort(ascendingSourceBreadth);
- });
- graph.nodes.forEach(function(node) {
- var y0 = node.y0, y1 = y0;
- node.sourceLinks.forEach(function(link) {
- link.y0 = y0 + link.width / 2, y0 += link.width;
- });
- node.targetLinks.forEach(function(link) {
- link.y1 = y1 + link.width / 2, y1 += link.width;
- });
- });
- }
- return sankey;
- };
- function horizontalSource(d) {
- return [d.source.x1, d.y0];
- }
- function horizontalTarget(d) {
- return [d.target.x0, d.y1];
- }
- var sankeyLinkHorizontal = function() {
- return d3Shape.linkHorizontal()
- .source(horizontalSource)
- .target(horizontalTarget);
- };
- exports.sankey = sankey;
- exports.sankeyCenter = center;
- exports.sankeyLeft = left;
- exports.sankeyRight = right;
- exports.sankeyJustify = justify;
- exports.sankeyLinkHorizontal = sankeyLinkHorizontal;
- Object.defineProperty(exports, '__esModule', { value: true });
- })));
|