Skip to content

Instantly share code, notes, and snippets.

@timelyportfolio
Last active December 12, 2016 23:08
Show Gist options
  • Save timelyportfolio/e480359ea953d96a38a4466187d3d62b to your computer and use it in GitHub Desktop.
Save timelyportfolio/e480359ea953d96a38a4466187d3d62b to your computer and use it in GitHub Desktop.
D3 Source Treemap (forked for split algo)
border: no
height: 960
license: gpl-3.0

forked from mbostock's block: D3 Source Treemap


Inspired by this discussion, I wanted to try to implement the split algorithm for treemaps. It is still very much a WIP, but I thought this d3 source example would make a great test.


Original README.md

This treemap shows the file size in bytes of D3 4.4.0’s source code. Click on any cell to view the corresponding source.

(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.d3 = global.d3 || {})));
}(this, (function (exports) { 'use strict';
function defaultSeparation(a, b) {
return a.parent === b.parent ? 1 : 2;
}
function meanX(children) {
return children.reduce(meanXReduce, 0) / children.length;
}
function meanXReduce(x, c) {
return x + c.x;
}
function maxY(children) {
return 1 + children.reduce(maxYReduce, 0);
}
function maxYReduce(y, c) {
return Math.max(y, c.y);
}
function leafLeft(node) {
var children;
while (children = node.children) node = children[0];
return node;
}
function leafRight(node) {
var children;
while (children = node.children) node = children[children.length - 1];
return node;
}
var cluster = function() {
var separation = defaultSeparation,
dx = 1,
dy = 1,
nodeSize = false;
function cluster(root) {
var previousNode,
x = 0;
// First walk, computing the initial x & y values.
root.eachAfter(function(node) {
var children = node.children;
if (children) {
node.x = meanX(children);
node.y = maxY(children);
} else {
node.x = previousNode ? x += separation(node, previousNode) : 0;
node.y = 0;
previousNode = node;
}
});
var left = leafLeft(root),
right = leafRight(root),
x0 = left.x - separation(left, right) / 2,
x1 = right.x + separation(right, left) / 2;
// Second walk, normalizing x & y to the desired size.
return root.eachAfter(nodeSize ? function(node) {
node.x = (node.x - root.x) * dx;
node.y = (root.y - node.y) * dy;
} : function(node) {
node.x = (node.x - x0) / (x1 - x0) * dx;
node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
});
}
cluster.separation = function(x) {
return arguments.length ? (separation = x, cluster) : separation;
};
cluster.size = function(x) {
return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
};
cluster.nodeSize = function(x) {
return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
};
return cluster;
};
var node_each = function(callback) {
var node = this, current, next = [node], children, i, n;
do {
current = next.reverse(), next = [];
while (node = current.pop()) {
callback(node), children = node.children;
if (children) for (i = 0, n = children.length; i < n; ++i) {
next.push(children[i]);
}
}
} while (next.length);
return this;
};
var node_eachBefore = function(callback) {
var node = this, nodes = [node], children, i;
while (node = nodes.pop()) {
callback(node), children = node.children;
if (children) for (i = children.length - 1; i >= 0; --i) {
nodes.push(children[i]);
}
}
return this;
};
var node_eachAfter = function(callback) {
var node = this, nodes = [node], next = [], children, i, n;
while (node = nodes.pop()) {
next.push(node), children = node.children;
if (children) for (i = 0, n = children.length; i < n; ++i) {
nodes.push(children[i]);
}
}
while (node = next.pop()) {
callback(node);
}
return this;
};
var node_sum = function(value) {
return this.eachAfter(function(node) {
var sum = +value(node.data) || 0,
children = node.children,
i = children && children.length;
while (--i >= 0) sum += children[i].value;
node.value = sum;
});
};
var node_sort = function(compare) {
return this.eachBefore(function(node) {
if (node.children) {
node.children.sort(compare);
}
});
};
var node_path = function(end) {
var start = this,
ancestor = leastCommonAncestor(start, end),
nodes = [start];
while (start !== ancestor) {
start = start.parent;
nodes.push(start);
}
var k = nodes.length;
while (end !== ancestor) {
nodes.splice(k, 0, end);
end = end.parent;
}
return nodes;
};
function leastCommonAncestor(a, b) {
if (a === b) return a;
var aNodes = a.ancestors(),
bNodes = b.ancestors(),
c = null;
a = aNodes.pop();
b = bNodes.pop();
while (a === b) {
c = a;
a = aNodes.pop();
b = bNodes.pop();
}
return c;
}
var node_ancestors = function() {
var node = this, nodes = [node];
while (node = node.parent) {
nodes.push(node);
}
return nodes;
};
var node_descendants = function() {
var nodes = [];
this.each(function(node) {
nodes.push(node);
});
return nodes;
};
var node_leaves = function() {
var leaves = [];
this.eachBefore(function(node) {
if (!node.children) {
leaves.push(node);
}
});
return leaves;
};
var node_links = function() {
var root = this, links = [];
root.each(function(node) {
if (node !== root) { // Don’t include the root’s parent, if any.
links.push({source: node.parent, target: node});
}
});
return links;
};
function hierarchy(data, children) {
var root = new Node(data),
valued = +data.value && (root.value = data.value),
node,
nodes = [root],
child,
childs,
i,
n;
if (children == null) children = defaultChildren;
while (node = nodes.pop()) {
if (valued) node.value = +node.data.value;
if ((childs = children(node.data)) && (n = childs.length)) {
node.children = new Array(n);
for (i = n - 1; i >= 0; --i) {
nodes.push(child = node.children[i] = new Node(childs[i]));
child.parent = node;
child.depth = node.depth + 1;
}
}
}
return root.eachBefore(computeHeight);
}
function node_copy() {
return hierarchy(this).eachBefore(copyData);
}
function defaultChildren(d) {
return d.children;
}
function copyData(node) {
node.data = node.data.data;
}
function computeHeight(node) {
var height = 0;
do node.height = height;
while ((node = node.parent) && (node.height < ++height));
}
function Node(data) {
this.data = data;
this.depth =
this.height = 0;
this.parent = null;
}
Node.prototype = hierarchy.prototype = {
constructor: Node,
each: node_each,
eachAfter: node_eachAfter,
eachBefore: node_eachBefore,
sum: node_sum,
sort: node_sort,
path: node_path,
ancestors: node_ancestors,
descendants: node_descendants,
leaves: node_leaves,
links: node_links,
copy: node_copy
};
function Node$2(value) {
this._ = value;
this.next = null;
}
var shuffle = function(array) {
var i,
n = (array = array.slice()).length,
head = null,
node = head;
while (n) {
var next = new Node$2(array[n - 1]);
if (node) node = node.next = next;
else node = head = next;
array[i] = array[--n];
}
return {
head: head,
tail: node
};
};
var enclose = function(circles) {
return encloseN(shuffle(circles), []);
};
function encloses(a, b) {
var dx = b.x - a.x,
dy = b.y - a.y,
dr = a.r - b.r;
return dr * dr + 1e-6 > dx * dx + dy * dy;
}
// Returns the smallest circle that contains circles L and intersects circles B.
function encloseN(L, B) {
var circle,
l0 = null,
l1 = L.head,
l2,
p1;
switch (B.length) {
case 1: circle = enclose1(B[0]); break;
case 2: circle = enclose2(B[0], B[1]); break;
case 3: circle = enclose3(B[0], B[1], B[2]); break;
}
while (l1) {
p1 = l1._, l2 = l1.next;
if (!circle || !encloses(circle, p1)) {
// Temporarily truncate L before l1.
if (l0) L.tail = l0, l0.next = null;
else L.head = L.tail = null;
B.push(p1);
circle = encloseN(L, B); // Note: reorders L!
B.pop();
// Move l1 to the front of L and reconnect the truncated list L.
if (L.head) l1.next = L.head, L.head = l1;
else l1.next = null, L.head = L.tail = l1;
l0 = L.tail, l0.next = l2;
} else {
l0 = l1;
}
l1 = l2;
}
L.tail = l0;
return circle;
}
function enclose1(a) {
return {
x: a.x,
y: a.y,
r: a.r
};
}
function enclose2(a, b) {
var x1 = a.x, y1 = a.y, r1 = a.r,
x2 = b.x, y2 = b.y, r2 = b.r,
x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
l = Math.sqrt(x21 * x21 + y21 * y21);
return {
x: (x1 + x2 + x21 / l * r21) / 2,
y: (y1 + y2 + y21 / l * r21) / 2,
r: (l + r1 + r2) / 2
};
}
function enclose3(a, b, c) {
var x1 = a.x, y1 = a.y, r1 = a.r,
x2 = b.x, y2 = b.y, r2 = b.r,
x3 = c.x, y3 = c.y, r3 = c.r,
a2 = 2 * (x1 - x2),
b2 = 2 * (y1 - y2),
c2 = 2 * (r2 - r1),
d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
a3 = 2 * (x1 - x3),
b3 = 2 * (y1 - y3),
c3 = 2 * (r3 - r1),
d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
ab = a3 * b2 - a2 * b3,
xa = (b2 * d3 - b3 * d2) / ab - x1,
xb = (b3 * c2 - b2 * c3) / ab,
ya = (a3 * d2 - a2 * d3) / ab - y1,
yb = (a2 * c3 - a3 * c2) / ab,
A = xb * xb + yb * yb - 1,
B = 2 * (xa * xb + ya * yb + r1),
C = xa * xa + ya * ya - r1 * r1,
r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
return {
x: xa + xb * r + x1,
y: ya + yb * r + y1,
r: r
};
}
function place(a, b, c) {
var ax = a.x,
ay = a.y,
da = b.r + c.r,
db = a.r + c.r,
dx = b.x - ax,
dy = b.y - ay,
dc = dx * dx + dy * dy;
if (dc) {
var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
c.x = ax + x * dx + y * dy;
c.y = ay + x * dy - y * dx;
} else {
c.x = ax + db;
c.y = ay;
}
}
function intersects(a, b) {
var dx = b.x - a.x,
dy = b.y - a.y,
dr = a.r + b.r;
return dr * dr > dx * dx + dy * dy;
}
function distance2(circle, x, y) {
var dx = circle.x - x,
dy = circle.y - y;
return dx * dx + dy * dy;
}
function Node$1(circle) {
this._ = circle;
this.next = null;
this.previous = null;
}
function packEnclose(circles) {
if (!(n = circles.length)) return 0;
var a, b, c, n;
// Place the first circle.
a = circles[0], a.x = 0, a.y = 0;
if (!(n > 1)) return a.r;
// Place the second circle.
b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
if (!(n > 2)) return a.r + b.r;
// Place the third circle.
place(b, a, c = circles[2]);
// Initialize the weighted centroid.
var aa = a.r * a.r,
ba = b.r * b.r,
ca = c.r * c.r,
oa = aa + ba + ca,
ox = aa * a.x + ba * b.x + ca * c.x,
oy = aa * a.y + ba * b.y + ca * c.y,
cx, cy, i, j, k, sj, sk;
// Initialize the front-chain using the first three circles a, b and c.
a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
a.next = c.previous = b;
b.next = a.previous = c;
c.next = b.previous = a;
// Attempt to place each remaining circle…
pack: for (i = 3; i < n; ++i) {
place(a._, b._, c = circles[i]), c = new Node$1(c);
// If there are only three elements in the front-chain…
if ((k = a.previous) === (j = b.next)) {
// If the new circle intersects the third circle,
// rotate the front chain to try the next position.
if (intersects(j._, c._)) {
a = b, b = j, --i;
continue pack;
}
}
// Find the closest intersecting circle on the front-chain, if any.
else {
sj = j._.r, sk = k._.r;
do {
if (sj <= sk) {
if (intersects(j._, c._)) {
b = j, a.next = b, b.previous = a, --i;
continue pack;
}
j = j.next, sj += j._.r;
} else {
if (intersects(k._, c._)) {
a = k, a.next = b, b.previous = a, --i;
continue pack;
}
k = k.previous, sk += k._.r;
}
} while (j !== k.next);
}
// Success! Insert the new circle c between a and b.
c.previous = a, c.next = b, a.next = b.previous = b = c;
// Update the weighted centroid.
oa += ca = c._.r * c._.r;
ox += ca * c._.x;
oy += ca * c._.y;
// Compute the new closest circle a to centroid.
aa = distance2(a._, cx = ox / oa, cy = oy / oa);
while ((c = c.next) !== b) {
if ((ca = distance2(c._, cx, cy)) < aa) {
a = c, aa = ca;
}
}
b = a.next;
}
// Compute the enclosing circle of the front chain.
a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
// Translate the circles to put the enclosing circle around the origin.
for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
return c.r;
}
var siblings = function(circles) {
packEnclose(circles);
return circles;
};
function optional(f) {
return f == null ? null : required(f);
}
function required(f) {
if (typeof f !== "function") throw new Error;
return f;
}
function constantZero() {
return 0;
}
var constant = function(x) {
return function() {
return x;
};
};
function defaultRadius(d) {
return Math.sqrt(d.value);
}
var index = function() {
var radius = null,
dx = 1,
dy = 1,
padding = constantZero;
function pack(root) {
root.x = dx / 2, root.y = dy / 2;
if (radius) {
root.eachBefore(radiusLeaf(radius))
.eachAfter(packChildren(padding, 0.5))
.eachBefore(translateChild(1));
} else {
root.eachBefore(radiusLeaf(defaultRadius))
.eachAfter(packChildren(constantZero, 1))
.eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
.eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
}
return root;
}
pack.radius = function(x) {
return arguments.length ? (radius = optional(x), pack) : radius;
};
pack.size = function(x) {
return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
};
pack.padding = function(x) {
return arguments.length ? (padding = typeof x === "function" ? x : constant(+x), pack) : padding;
};
return pack;
};
function radiusLeaf(radius) {
return function(node) {
if (!node.children) {
node.r = Math.max(0, +radius(node) || 0);
}
};
}
function packChildren(padding, k) {
return function(node) {
if (children = node.children) {
var children,
i,
n = children.length,
r = padding(node) * k || 0,
e;
if (r) for (i = 0; i < n; ++i) children[i].r += r;
e = packEnclose(children);
if (r) for (i = 0; i < n; ++i) children[i].r -= r;
node.r = e + r;
}
};
}
function translateChild(k) {
return function(node) {
var parent = node.parent;
node.r *= k;
if (parent) {
node.x = parent.x + k * node.x;
node.y = parent.y + k * node.y;
}
};
}
var roundNode = function(node) {
node.x0 = Math.round(node.x0);
node.y0 = Math.round(node.y0);
node.x1 = Math.round(node.x1);
node.y1 = Math.round(node.y1);
};
var treemapDice = function(parent, x0, y0, x1, y1) {
var nodes = parent.children,
node,
i = -1,
n = nodes.length,
k = parent.value && (x1 - x0) / parent.value;
while (++i < n) {
node = nodes[i], node.y0 = y0, node.y1 = y1;
node.x0 = x0, node.x1 = x0 += node.value * k;
}
};
var partition = function() {
var dx = 1,
dy = 1,
padding = 0,
round = false;
function partition(root) {
var n = root.height + 1;
root.x0 =
root.y0 = padding;
root.x1 = dx;
root.y1 = dy / n;
root.eachBefore(positionNode(dy, n));
if (round) root.eachBefore(roundNode);
return root;
}
function positionNode(dy, n) {
return function(node) {
if (node.children) {
treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
}
var x0 = node.x0,
y0 = node.y0,
x1 = node.x1 - padding,
y1 = node.y1 - padding;
if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
node.x0 = x0;
node.y0 = y0;
node.x1 = x1;
node.y1 = y1;
};
}
partition.round = function(x) {
return arguments.length ? (round = !!x, partition) : round;
};
partition.size = function(x) {
return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
};
partition.padding = function(x) {
return arguments.length ? (padding = +x, partition) : padding;
};
return partition;
};
var keyPrefix = "$";
var preroot = {depth: -1};
var ambiguous = {};
function defaultId(d) {
return d.id;
}
function defaultParentId(d) {
return d.parentId;
}
var stratify = function() {
var id = defaultId,
parentId = defaultParentId;
function stratify(data) {
var d,
i,
n = data.length,
root,
parent,
node,
nodes = new Array(n),
nodeId,
nodeKey,
nodeByKey = {};
for (i = 0; i < n; ++i) {
d = data[i], node = nodes[i] = new Node(d);
if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
nodeKey = keyPrefix + (node.id = nodeId);
nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
}
}
for (i = 0; i < n; ++i) {
node = nodes[i], nodeId = parentId(data[i], i, data);
if (nodeId == null || !(nodeId += "")) {
if (root) throw new Error("multiple roots");
root = node;
} else {
parent = nodeByKey[keyPrefix + nodeId];
if (!parent) throw new Error("missing: " + nodeId);
if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
if (parent.children) parent.children.push(node);
else parent.children = [node];
node.parent = parent;
}
}
if (!root) throw new Error("no root");
root.parent = preroot;
root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
root.parent = null;
if (n > 0) throw new Error("cycle");
return root;
}
stratify.id = function(x) {
return arguments.length ? (id = required(x), stratify) : id;
};
stratify.parentId = function(x) {
return arguments.length ? (parentId = required(x), stratify) : parentId;
};
return stratify;
};
function defaultSeparation$1(a, b) {
return a.parent === b.parent ? 1 : 2;
}
// function radialSeparation(a, b) {
// return (a.parent === b.parent ? 1 : 2) / a.depth;
// }
// This function is used to traverse the left contour of a subtree (or
// subforest). It returns the successor of v on this contour. This successor is
// either given by the leftmost child of v or by the thread of v. The function
// returns null if and only if v is on the highest level of its subtree.
function nextLeft(v) {
var children = v.children;
return children ? children[0] : v.t;
}
// This function works analogously to nextLeft.
function nextRight(v) {
var children = v.children;
return children ? children[children.length - 1] : v.t;
}
// Shifts the current subtree rooted at w+. This is done by increasing
// prelim(w+) and mod(w+) by shift.
function moveSubtree(wm, wp, shift) {
var change = shift / (wp.i - wm.i);
wp.c -= change;
wp.s += shift;
wm.c += change;
wp.z += shift;
wp.m += shift;
}
// All other shifts, applied to the smaller subtrees between w- and w+, are
// performed by this function. To prepare the shifts, we have to adjust
// change(w+), shift(w+), and change(w-).
function executeShifts(v) {
var shift = 0,
change = 0,
children = v.children,
i = children.length,
w;
while (--i >= 0) {
w = children[i];
w.z += shift;
w.m += shift;
shift += w.s + (change += w.c);
}
}
// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
// returns the specified (default) ancestor.
function nextAncestor(vim, v, ancestor) {
return vim.a.parent === v.parent ? vim.a : ancestor;
}
function TreeNode(node, i) {
this._ = node;
this.parent = null;
this.children = null;
this.A = null; // default ancestor
this.a = this; // ancestor
this.z = 0; // prelim
this.m = 0; // mod
this.c = 0; // change
this.s = 0; // shift
this.t = null; // thread
this.i = i; // number
}
TreeNode.prototype = Object.create(Node.prototype);
function treeRoot(root) {
var tree = new TreeNode(root, 0),
node,
nodes = [tree],
child,
children,
i,
n;
while (node = nodes.pop()) {
if (children = node._.children) {
node.children = new Array(n = children.length);
for (i = n - 1; i >= 0; --i) {
nodes.push(child = node.children[i] = new TreeNode(children[i], i));
child.parent = node;
}
}
}
(tree.parent = new TreeNode(null, 0)).children = [tree];
return tree;
}
// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
var tree = function() {
var separation = defaultSeparation$1,
dx = 1,
dy = 1,
nodeSize = null;
function tree(root) {
var t = treeRoot(root);
// Compute the layout using Buchheim et al.’s algorithm.
t.eachAfter(firstWalk), t.parent.m = -t.z;
t.eachBefore(secondWalk);
// If a fixed node size is specified, scale x and y.
if (nodeSize) root.eachBefore(sizeNode);
// If a fixed tree size is specified, scale x and y based on the extent.
// Compute the left-most, right-most, and depth-most nodes for extents.
else {
var left = root,
right = root,
bottom = root;
root.eachBefore(function(node) {
if (node.x < left.x) left = node;
if (node.x > right.x) right = node;
if (node.depth > bottom.depth) bottom = node;
});
var s = left === right ? 1 : separation(left, right) / 2,
tx = s - left.x,
kx = dx / (right.x + s + tx),
ky = dy / (bottom.depth || 1);
root.eachBefore(function(node) {
node.x = (node.x + tx) * kx;
node.y = node.depth * ky;
});
}
return root;
}
// Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
// applied recursively to the children of v, as well as the function
// APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
// node v is placed to the midpoint of its outermost children.
function firstWalk(v) {
var children = v.children,
siblings = v.parent.children,
w = v.i ? siblings[v.i - 1] : null;
if (children) {
executeShifts(v);
var midpoint = (children[0].z + children[children.length - 1].z) / 2;
if (w) {
v.z = w.z + separation(v._, w._);
v.m = v.z - midpoint;
} else {
v.z = midpoint;
}
} else if (w) {
v.z = w.z + separation(v._, w._);
}
v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
}
// Computes all real x-coordinates by summing up the modifiers recursively.
function secondWalk(v) {
v._.x = v.z + v.parent.m;
v.m += v.parent.m;
}
// The core of the algorithm. Here, a new subtree is combined with the
// previous subtrees. Threads are used to traverse the inside and outside
// contours of the left and right subtree up to the highest common level. The
// vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
// superscript o means outside and i means inside, the subscript - means left
// subtree and + means right subtree. For summing up the modifiers along the
// contour, we use respective variables si+, si-, so-, and so+. Whenever two
// nodes of the inside contours conflict, we compute the left one of the
// greatest uncommon ancestors using the function ANCESTOR and call MOVE
// SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
// Finally, we add a new thread (if necessary).
function apportion(v, w, ancestor) {
if (w) {
var vip = v,
vop = v,
vim = w,
vom = vip.parent.children[0],
sip = vip.m,
sop = vop.m,
sim = vim.m,
som = vom.m,
shift;
while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
vom = nextLeft(vom);
vop = nextRight(vop);
vop.a = v;
shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
if (shift > 0) {
moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
sip += shift;
sop += shift;
}
sim += vim.m;
sip += vip.m;
som += vom.m;
sop += vop.m;
}
if (vim && !nextRight(vop)) {
vop.t = vim;
vop.m += sim - sop;
}
if (vip && !nextLeft(vom)) {
vom.t = vip;
vom.m += sip - som;
ancestor = v;
}
}
return ancestor;
}
function sizeNode(node) {
node.x *= dx;
node.y = node.depth * dy;
}
tree.separation = function(x) {
return arguments.length ? (separation = x, tree) : separation;
};
tree.size = function(x) {
return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
};
tree.nodeSize = function(x) {
return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
};
return tree;
};
var treemapSlice = function(parent, x0, y0, x1, y1) {
var nodes = parent.children,
node,
i = -1,
n = nodes.length,
k = parent.value && (y1 - y0) / parent.value;
while (++i < n) {
node = nodes[i], node.x0 = x0, node.x1 = x1;
node.y0 = y0, node.y1 = y0 += node.value * k;
}
};
var phi = (1 + Math.sqrt(5)) / 2;
function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
var rows = [],
nodes = parent.children,
row,
nodeValue,
i0 = 0,
i1 = 0,
n = nodes.length,
dx, dy,
value = parent.value,
sumValue,
minValue,
maxValue,
newRatio,
minRatio,
alpha,
beta;
while (i0 < n) {
dx = x1 - x0, dy = y1 - y0;
// Find the next non-empty node.
do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
minValue = maxValue = sumValue;
alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
beta = sumValue * sumValue * alpha;
minRatio = Math.max(maxValue / beta, beta / minValue);
// Keep adding nodes while the aspect ratio maintains or improves.
for (; i1 < n; ++i1) {
sumValue += nodeValue = nodes[i1].value;
if (nodeValue < minValue) minValue = nodeValue;
if (nodeValue > maxValue) maxValue = nodeValue;
beta = sumValue * sumValue * alpha;
newRatio = Math.max(maxValue / beta, beta / minValue);
if (newRatio > minRatio) { sumValue -= nodeValue; break; }
minRatio = newRatio;
}
// Position and record the row orientation.
rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
value -= sumValue, i0 = i1;
}
return rows;
}
var squarify = (function custom(ratio) {
function squarify(parent, x0, y0, x1, y1) {
squarifyRatio(ratio, parent, x0, y0, x1, y1);
}
squarify.ratio = function(x) {
return custom((x = +x) > 1 ? x : 1);
};
return squarify;
})(phi);
var index$1 = function() {
var tile = squarify,
round = false,
dx = 1,
dy = 1,
paddingStack = [0],
paddingInner = constantZero,
paddingTop = constantZero,
paddingRight = constantZero,
paddingBottom = constantZero,
paddingLeft = constantZero;
function treemap(root) {
root.x0 =
root.y0 = 0;
root.x1 = dx;
root.y1 = dy;
root.eachBefore(positionNode);
paddingStack = [0];
if (round) root.eachBefore(roundNode);
return root;
}
function positionNode(node) {
var p = paddingStack[node.depth],
x0 = node.x0 + p,
y0 = node.y0 + p,
x1 = node.x1 - p,
y1 = node.y1 - p;
if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
node.x0 = x0;
node.y0 = y0;
node.x1 = x1;
node.y1 = y1;
if (node.children) {
p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
x0 += paddingLeft(node) - p;
y0 += paddingTop(node) - p;
x1 -= paddingRight(node) - p;
y1 -= paddingBottom(node) - p;
if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
tile(node, x0, y0, x1, y1);
}
}
treemap.round = function(x) {
return arguments.length ? (round = !!x, treemap) : round;
};
treemap.size = function(x) {
return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
};
treemap.tile = function(x) {
return arguments.length ? (tile = required(x), treemap) : tile;
};
treemap.padding = function(x) {
return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
};
treemap.paddingInner = function(x) {
return arguments.length ? (paddingInner = typeof x === "function" ? x : constant(+x), treemap) : paddingInner;
};
treemap.paddingOuter = function(x) {
return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
};
treemap.paddingTop = function(x) {
return arguments.length ? (paddingTop = typeof x === "function" ? x : constant(+x), treemap) : paddingTop;
};
treemap.paddingRight = function(x) {
return arguments.length ? (paddingRight = typeof x === "function" ? x : constant(+x), treemap) : paddingRight;
};
treemap.paddingBottom = function(x) {
return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant(+x), treemap) : paddingBottom;
};
treemap.paddingLeft = function(x) {
return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant(+x), treemap) : paddingLeft;
};
return treemap;
};
var binary = function(parent, x0, y0, x1, y1) {
var nodes = parent.children,
i, n = nodes.length,
sum, sums = new Array(n + 1);
for (sums[0] = sum = i = 0; i < n; ++i) {
sums[i + 1] = sum += nodes[i].value;
}
partition(0, n, parent.value, x0, y0, x1, y1);
function partition(i, j, value, x0, y0, x1, y1) {
if (i >= j - 1) {
var node = nodes[i];
node.x0 = x0, node.y0 = y0;
node.x1 = x1, node.y1 = y1;
return;
}
var valueOffset = sums[i],
valueTarget = (value / 2) + valueOffset,
k = i + 1,
hi = j - 1;
while (k < hi) {
var mid = k + hi >>> 1;
if (sums[mid] < valueTarget) k = mid + 1;
else hi = mid;
}
var valueLeft = sums[k] - valueOffset,
valueRight = value - valueLeft;
if ((y1 - y0) > (x1 - x0)) {
var yk = (y0 * valueRight + y1 * valueLeft) / value;
partition(i, k, valueLeft, x0, y0, x1, yk);
partition(k, j, valueRight, x0, yk, x1, y1);
} else {
var xk = (x0 * valueRight + x1 * valueLeft) / value;
partition(i, k, valueLeft, x0, y0, xk, y1);
partition(k, j, valueRight, xk, y0, x1, y1);
}
}
};
var sliceDice = function(parent, x0, y0, x1, y1) {
(parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
};
var split = function(parent, x0, y0, x1, y1) {
// exit if no children
if (!(parent.children) || parent.children.length === 0) {
return;
}
function calcSum(nodes) {
var sum = 0,
i = 0,
n = nodes.length;
for ( ; i < n; ++i) {
sum += nodes[i].value;
}
return sum;
}
var sum = calcSum(parent.children);
splitTree(parent.children, sum, x0, y0, x1, y1);
function splitTree(nodes, sum, x0, y0, x1, y1) {
var i, n = nodes.length;
if (n === 0) {
return;
}
if (n === 1) {
nodes[0].x0 = x0;
nodes[0].x1 = x1;
nodes[0].y0 = y0;
nodes[0].y1 = y1;
return;
}
var width = x1 - x0,
height = y1 - y0;
var list1 = [],
list2 = [],
r1x0 = 0,
r1x1 = 0,
r1y0 = 0,
r1y1 = 0,
r2x0 = 0,
r2x1 = 0,
r2y0 = 0,
r2y1 = 0,
halfSize = 0,
tmp = 0,
w1 = 0,
w2 = 0;
halfSize = sum / 2;
for (i = 0; i < n; i++) {
tmp += nodes[i].value;
if (Math.abs(halfSize - tmp) > Math.abs(halfSize - w1)) {
list1 = nodes.slice(0, i);
break;
}
w1 = tmp;
}
list2 = nodes.slice(i);
w2 = sum - w1;
if (width > height) {
r1x0 = x0;
r1y0 = y0;
r1x1 = x0 + width * w1 / sum;
r1y1 = y1;
r2x0 = r1x1;
r2y0 = y0;
r2x1 = x1;
r2y1 = y1;
} else {
r1x0 = x0;
r1y0 = y0;
r1x1 = x1;
r1y1 = y0 + height * w1 / sum;
r2x0 = x0;
r2y0 = r1y1;
r2x1 = x1;
r2y1 = y1;
}
if (list1.length > 0 && w1 > 0) {
splitTree(list1, w1, r1x0, r1y0, r1x1, r1y1);
}
if (list2.length > 0 && w2 > 0 ) {
splitTree(list2, w2, r2x0, r2y0, r2x1, r2y1);
}
}
};
var resquarify = (function custom(ratio) {
function resquarify(parent, x0, y0, x1, y1) {
if ((rows = parent._squarify) && (rows.ratio === ratio)) {
var rows,
row,
nodes,
i,
j = -1,
n,
m = rows.length,
value = parent.value;
while (++j < m) {
row = rows[j], nodes = row.children;
for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
value -= row.value;
}
} else {
parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
rows.ratio = ratio;
}
}
resquarify.ratio = function(x) {
return custom((x = +x) > 1 ? x : 1);
};
return resquarify;
})(phi);
exports.cluster = cluster;
exports.hierarchy = hierarchy;
exports.pack = index;
exports.packSiblings = siblings;
exports.packEnclose = enclose;
exports.partition = partition;
exports.stratify = stratify;
exports.tree = tree;
exports.treemap = index$1;
exports.treemapBinary = binary;
exports.treemapDice = treemapDice;
exports.treemapSlice = treemapSlice;
exports.treemapSliceDice = sliceDice;
exports.treemapSquarify = squarify;
exports.treemapSplit = split;
exports.treemapResquarify = resquarify;
Object.defineProperty(exports, '__esModule', { value: true });
})));
size path
d3
d3/d3-array
d3/d3-array/threshold
d3/d3-axis
d3/d3-brush
d3/d3-chord
d3/d3-collection
d3/d3-color
d3/d3-dispatch
d3/d3-drag
d3/d3-dsv
d3/d3-ease
d3/d3-force
d3/d3-format
d3/d3-geo
d3/d3-geo/clip
d3/d3-geo/path
d3/d3-geo/projection
d3/d3-hierarchy
d3/d3-hierarchy/hierarchy
d3/d3-hierarchy/pack
d3/d3-hierarchy/treemap
d3/d3-interpolate
d3/d3-interpolate/transform
d3/d3-path
d3/d3-polygon
d3/d3-quadtree
d3/d3-queue
d3/d3-random
d3/d3-request
d3/d3-scale
d3/d3-selection
d3/d3-selection/selection
d3/d3-shape
d3/d3-shape/curve
d3/d3-shape/offset
d3/d3-shape/order
d3/d3-shape/symbol
d3/d3-time-format
d3/d3-time
d3/d3-timer
d3/d3-transition
d3/d3-transition/selection
d3/d3-transition/transition
d3/d3-voronoi
d3/d3-zoom
90 d3/d3-array/array.js
86 d3/d3-array/ascending.js
238 d3/d3-array/bisect.js
786 d3/d3-array/bisector.js
72 d3/d3-array/constant.js
86 d3/d3-array/descending.js
135 d3/d3-array/deviation.js
553 d3/d3-array/extent.js
1876 d3/d3-array/histogram.js
43 d3/d3-array/identity.js
451 d3/d3-array/max.js
362 d3/d3-array/mean.js
452 d3/d3-array/median.js
339 d3/d3-array/merge.js
451 d3/d3-array/min.js
63 d3/d3-array/number.js
182 d3/d3-array/pairs.js
161 d3/d3-array/permute.js
416 d3/d3-array/quantile.js
344 d3/d3-array/range.js
357 d3/d3-array/scan.js
285 d3/d3-array/shuffle.js
295 d3/d3-array/sum.js
361 d3/d3-array/threshold/freedmanDiaconis.js
180 d3/d3-array/threshold/scott.js
96 d3/d3-array/threshold/sturges.js
672 d3/d3-array/ticks.js
356 d3/d3-array/transpose.js
540 d3/d3-array/variance.js
99 d3/d3-array/zip.js
42 d3/d3-axis/array.js
5239 d3/d3-axis/axis.js
43 d3/d3-axis/identity.js
15778 d3/d3-brush/brush.js
72 d3/d3-brush/constant.js
127 d3/d3-brush/event.js
202 d3/d3-brush/noevent.js
42 d3/d3-chord/array.js
3178 d3/d3-chord/chord.js
72 d3/d3-chord/constant.js
159 d3/d3-chord/math.js
2340 d3/d3-chord/ribbon.js
137 d3/d3-collection/entries.js
104 d3/d3-collection/keys.js
1988 d3/d3-collection/map.js
2021 d3/d3-collection/nest.js
800 d3/d3-collection/set.js
115 d3/d3-collection/values.js
9276 d3/d3-color/color.js
1855 d3/d3-color/cubehelix.js
340 d3/d3-color/define.js
3167 d3/d3-color/lab.js
72 d3/d3-color/math.js
2729 d3/d3-dispatch/dispatch.js
72 d3/d3-drag/constant.js
4297 d3/d3-drag/drag.js
430 d3/d3-drag/event.js
857 d3/d3-drag/nodrag.js
202 d3/d3-drag/noevent.js
199 d3/d3-dsv/csv.js
3582 d3/d3-dsv/dsv.js
200 d3/d3-dsv/tsv.js
653 d3/d3-ease/back.js
521 d3/d3-ease/bounce.js
261 d3/d3-ease/circle.js
210 d3/d3-ease/cubic.js
1309 d3/d3-ease/elastic.js
251 d3/d3-ease/exp.js
43 d3/d3-ease/linear.js
596 d3/d3-ease/poly.js
192 d3/d3-ease/quad.js
236 d3/d3-ease/sin.js
654 d3/d3-force/center.js
2447 d3/d3-force/collide.js
72 d3/d3-force/constant.js
69 d3/d3-force/jiggle.js
3213 d3/d3-force/link.js
3181 d3/d3-force/manyBody.js
3444 d3/d3-force/simulation.js
1030 d3/d3-force/x.js
1030 d3/d3-force/y.js
361 d3/d3-format/defaultLocale.js
134 d3/d3-format/exponent.js
656 d3/d3-format/formatDecimal.js
368 d3/d3-format/formatDefault.js
475 d3/d3-format/formatGroup.js
611 d3/d3-format/formatPrefixAuto.js
458 d3/d3-format/formatRounded.js
1589 d3/d3-format/formatSpecifier.js
846 d3/d3-format/formatTypes.js
5247 d3/d3-format/locale.js
119 d3/d3-format/precisionFixed.js
190 d3/d3-format/precisionPrefix.js
186 d3/d3-format/precisionRound.js
906 d3/d3-geo/adder.js
1958 d3/d3-geo/area.js
5361 d3/d3-geo/bounds.js
929 d3/d3-geo/cartesian.js
3816 d3/d3-geo/centroid.js
2373 d3/d3-geo/circle.js
2897 d3/d3-geo/clip/antimeridian.js
470 d3/d3-geo/clip/buffer.js
5956 d3/d3-geo/clip/circle.js
5527 d3/d3-geo/clip/extent.js
3813 d3/d3-geo/clip/index.js
1099 d3/d3-geo/clip/line.js
2802 d3/d3-geo/clip/polygon.js
250 d3/d3-geo/compose.js
72 d3/d3-geo/constant.js
229 d3/d3-geo/distance.js
3034 d3/d3-geo/graticule.js
43 d3/d3-geo/identity.js
911 d3/d3-geo/interpolate.js
1309 d3/d3-geo/length.js
880 d3/d3-geo/math.js
34 d3/d3-geo/noop.js
945 d3/d3-geo/path/area.js
485 d3/d3-geo/path/bounds.js
2033 d3/d3-geo/path/centroid.js
914 d3/d3-geo/path/context.js
1690 d3/d3-geo/path/index.js
1149 d3/d3-geo/path/string.js
139 d3/d3-geo/pointEqual.js
2491 d3/d3-geo/polygonContains.js
235 d3/d3-geo/projection/albers.js
3986 d3/d3-geo/projection/albersUsa.js
502 d3/d3-geo/projection/azimuthal.js
447 d3/d3-geo/projection/azimuthalEqualArea.js
443 d3/d3-geo/projection/azimuthalEquidistant.js
402 d3/d3-geo/projection/conic.js
1017 d3/d3-geo/projection/conicConformal.js
871 d3/d3-geo/projection/conicEqualArea.js
771 d3/d3-geo/projection/conicEquidistant.js
314 d3/d3-geo/projection/cylindricalEqualArea.js
253 d3/d3-geo/projection/equirectangular.js
910 d3/d3-geo/projection/fit.js
387 d3/d3-geo/projection/gnomonic.js
1922 d3/d3-geo/projection/identity.js
3752 d3/d3-geo/projection/index.js
1119 d3/d3-geo/projection/mercator.js
376 d3/d3-geo/projection/orthographic.js
3275 d3/d3-geo/projection/resample.js
436 d3/d3-geo/projection/stereographic.js
762 d3/d3-geo/projection/transverseMercator.js
2509 d3/d3-geo/rotation.js
2305 d3/d3-geo/stream.js
701 d3/d3-geo/transform.js
166 d3/d3-hierarchy/accessors.js
2093 d3/d3-hierarchy/cluster.js
120 d3/d3-hierarchy/constant.js
138 d3/d3-hierarchy/hierarchy/ancestors.js
121 d3/d3-hierarchy/hierarchy/descendants.js
381 d3/d3-hierarchy/hierarchy/each.js
353 d3/d3-hierarchy/hierarchy/eachAfter.js
282 d3/d3-hierarchy/hierarchy/eachBefore.js
1819 d3/d3-hierarchy/hierarchy/index.js
164 d3/d3-hierarchy/hierarchy/leaves.js
246 d3/d3-hierarchy/hierarchy/links.js
606 d3/d3-hierarchy/hierarchy/path.js
151 d3/d3-hierarchy/hierarchy/sort.js
264 d3/d3-hierarchy/hierarchy/sum.js
2452 d3/d3-hierarchy/pack/enclose.js
1917 d3/d3-hierarchy/pack/index.js
389 d3/d3-hierarchy/pack/shuffle.js
3497 d3/d3-hierarchy/pack/siblings.js
1266 d3/d3-hierarchy/partition.js
1934 d3/d3-hierarchy/stratify.js
7060 d3/d3-hierarchy/tree.js
1184 d3/d3-hierarchy/treemap/binary.js
309 d3/d3-hierarchy/treemap/dice.js
2810 d3/d3-hierarchy/treemap/index.js
1029 d3/d3-hierarchy/treemap/resquarify.js
166 d3/d3-hierarchy/treemap/round.js
309 d3/d3-hierarchy/treemap/slice.js
170 d3/d3-hierarchy/treemap/sliceDice.js
1868 d3/d3-hierarchy/treemap/squarify.js
372 d3/d3-interpolate/array.js
600 d3/d3-interpolate/basis.js
360 d3/d3-interpolate/basisClosed.js
697 d3/d3-interpolate/color.js
72 d3/d3-interpolate/constant.js
760 d3/d3-interpolate/cubehelix.js
134 d3/d3-interpolate/date.js
547 d3/d3-interpolate/hcl.js
547 d3/d3-interpolate/hsl.js
447 d3/d3-interpolate/lab.js
100 d3/d3-interpolate/number.js
390 d3/d3-interpolate/object.js
163 d3/d3-interpolate/quantize.js
1277 d3/d3-interpolate/rgb.js
112 d3/d3-interpolate/round.js
1758 d3/d3-interpolate/string.js
672 d3/d3-interpolate/transform/decompose.js
2064 d3/d3-interpolate/transform/index.js
980 d3/d3-interpolate/transform/parse.js
598 d3/d3-interpolate/value.js
1387 d3/d3-interpolate/zoom.js
4089 d3/d3-path/path.js
243 d3/d3-polygon/area.js
346 d3/d3-polygon/centroid.js
411 d3/d3-polygon/contains.js
402 d3/d3-polygon/cross.js
1710 d3/d3-polygon/hull.js
375 d3/d3-polygon/length.js
2441 d3/d3-quadtree/add.js
1667 d3/d3-quadtree/cover.js
170 d3/d3-quadtree/data.js
206 d3/d3-quadtree/extent.js
1696 d3/d3-quadtree/find.js
134 d3/d3-quadtree/quad.js
2077 d3/d3-quadtree/quadtree.js
1898 d3/d3-quadtree/remove.js
51 d3/d3-quadtree/root.js
155 d3/d3-quadtree/size.js
695 d3/d3-quadtree/visit.js
773 d3/d3-quadtree/visitAfter.js
138 d3/d3-quadtree/x.js
138 d3/d3-quadtree/y.js
29 d3/d3-queue/array.js
2870 d3/d3-queue/queue.js
168 d3/d3-random/bates.js
113 d3/d3-random/exponential.js
137 d3/d3-random/irwinHall.js
178 d3/d3-random/logNormal.js
503 d3/d3-random/normal.js
236 d3/d3-random/uniform.js
101 d3/d3-request/csv.js
517 d3/d3-request/dsv.js
157 d3/d3-request/html.js
127 d3/d3-request/json.js
4593 d3/d3-request/request.js
109 d3/d3-request/text.js
118 d3/d3-request/tsv.js
370 d3/d3-request/type.js
174 d3/d3-request/xml.js
90 d3/d3-scale/array.js
2637 d3/d3-scale/band.js
119 d3/d3-scale/category10.js
179 d3/d3-scale/category20.js
179 d3/d3-scale/category20b.js
179 d3/d3-scale/category20c.js
101 d3/d3-scale/colors.js
72 d3/d3-scale/constant.js
3328 d3/d3-scale/continuous.js
188 d3/d3-scale/cubehelix.js
463 d3/d3-scale/identity.js
1206 d3/d3-scale/linear.js
3273 d3/d3-scale/log.js
340 d3/d3-scale/nice.js
44 d3/d3-scale/number.js
1116 d3/d3-scale/ordinal.js
1000 d3/d3-scale/pow.js
1280 d3/d3-scale/quantile.js
1066 d3/d3-scale/quantize.js
536 d3/d3-scale/rainbow.js
717 d3/d3-scale/sequential.js
802 d3/d3-scale/threshold.js
1203 d3/d3-scale/tickFormat.js
4565 d3/d3-scale/time.js
379 d3/d3-scale/utcTime.js
6471 d3/d3-scale/viridis.js
72 d3/d3-selection/constant.js
662 d3/d3-selection/creator.js
536 d3/d3-selection/local.js
533 d3/d3-selection/matcher.js
224 d3/d3-selection/mouse.js
303 d3/d3-selection/namespace.js
254 d3/d3-selection/namespaces.js
448 d3/d3-selection/point.js
259 d3/d3-selection/select.js
282 d3/d3-selection/selectAll.js
235 d3/d3-selection/selection/append.js
1460 d3/d3-selection/selection/attr.js
134 d3/d3-selection/selection/call.js
1740 d3/d3-selection/selection/classed.js
3597 d3/d3-selection/selection/data.js
132 d3/d3-selection/selection/datum.js
869 d3/d3-selection/selection/dispatch.js
289 d3/d3-selection/selection/each.js
53 d3/d3-selection/selection/empty.js
792 d3/d3-selection/selection/enter.js
176 d3/d3-selection/selection/exit.js
546 d3/d3-selection/selection/filter.js
520 d3/d3-selection/selection/html.js
2216 d3/d3-selection/selection/index.js
468 d3/d3-selection/selection/insert.js
171 d3/d3-selection/selection/lower.js
575 d3/d3-selection/selection/merge.js
258 d3/d3-selection/selection/node.js
140 d3/d3-selection/selection/nodes.js
3119 d3/d3-selection/selection/on.js
367 d3/d3-selection/selection/order.js
617 d3/d3-selection/selection/property.js
138 d3/d3-selection/selection/raise.js
153 d3/d3-selection/selection/remove.js
653 d3/d3-selection/selection/select.js
550 d3/d3-selection/selection/selectAll.js
98 d3/d3-selection/selection/size.js
681 d3/d3-selection/selection/sort.js
71 d3/d3-selection/selection/sparse.js
889 d3/d3-selection/selection/style.js
528 d3/d3-selection/selection/text.js
152 d3/d3-selection/selector.js
171 d3/d3-selection/selectorAll.js
175 d3/d3-selection/sourceEvent.js
407 d3/d3-selection/touch.js
323 d3/d3-selection/touches.js
218 d3/d3-selection/window.js
8831 d3/d3-shape/arc.js
2917 d3/d3-shape/area.js
42 d3/d3-shape/array.js
81 d3/d3-shape/constant.js
1436 d3/d3-shape/curve/basis.js
1530 d3/d3-shape/curve/basisClosed.js
1069 d3/d3-shape/curve/basisOpen.js
1081 d3/d3-shape/curve/bundle.js
1633 d3/d3-shape/curve/cardinal.js
1605 d3/d3-shape/curve/cardinalClosed.js
1288 d3/d3-shape/curve/cardinalOpen.js
2637 d3/d3-shape/curve/catmullRom.js
2083 d3/d3-shape/curve/catmullRomClosed.js
1760 d3/d3-shape/curve/catmullRomOpen.js
738 d3/d3-shape/curve/linear.js
514 d3/d3-shape/curve/linearClosed.js
3203 d3/d3-shape/curve/monotone.js
1761 d3/d3-shape/curve/natural.js
655 d3/d3-shape/curve/radial.js
1367 d3/d3-shape/curve/step.js
86 d3/d3-shape/descending.js
43 d3/d3-shape/identity.js
1516 d3/d3-shape/line.js
106 d3/d3-shape/math.js
29 d3/d3-shape/noop.js
319 d3/d3-shape/offset/expand.js
310 d3/d3-shape/offset/none.js
314 d3/d3-shape/offset/silhouette.js
740 d3/d3-shape/offset/wiggle.js
305 d3/d3-shape/order/ascending.js
112 d3/d3-shape/order/descending.js
545 d3/d3-shape/order/insideOut.js
120 d3/d3-shape/order/none.js
97 d3/d3-shape/order/reverse.js
2336 d3/d3-shape/pie.js
81 d3/d3-shape/point.js
934 d3/d3-shape/radialArea.js
396 d3/d3-shape/radialLine.js
1432 d3/d3-shape/stack.js
186 d3/d3-shape/symbol/circle.js
476 d3/d3-shape/symbol/cross.js
307 d3/d3-shape/symbol/diamond.js
137 d3/d3-shape/symbol/square.js
609 d3/d3-shape/symbol/star.js
255 d3/d3-shape/symbol/triangle.js
733 d3/d3-shape/symbol/wye.js
1160 d3/d3-shape/symbol.js
867 d3/d3-time-format/defaultLocale.js
284 d3/d3-time-format/isoFormat.js
319 d3/d3-time-format/isoParse.js
13876 d3/d3-time-format/locale.js
462 d3/d3-time/day.js
164 d3/d3-time/duration.js
569 d3/d3-time/hour.js
1845 d3/d3-time/interval.js
668 d3/d3-time/millisecond.js
437 d3/d3-time/minute.js
414 d3/d3-time/month.js
440 d3/d3-time/second.js
397 d3/d3-time/utcDay.js
399 d3/d3-time/utcHour.js
412 d3/d3-time/utcMinute.js
453 d3/d3-time/utcMonth.js
979 d3/d3-time/utcWeek.js
808 d3/d3-time/utcYear.js
963 d3/d3-time/week.js
754 d3/d3-time/year.js
400 d3/d3-timer/interval.js
250 d3/d3-timer/timeout.js
2771 d3/d3-timer/timer.js
484 d3/d3-transition/active.js
665 d3/d3-transition/interrupt.js
245 d3/d3-transition/selection/index.js
138 d3/d3-transition/selection/interrupt.js
1090 d3/d3-transition/selection/transition.js
2473 d3/d3-transition/transition/attr.js
904 d3/d3-transition/transition/attrTween.js
510 d3/d3-transition/transition/delay.js
528 d3/d3-transition/transition/duration.js
348 d3/d3-transition/transition/ease.js
574 d3/d3-transition/transition/filter.js
1892 d3/d3-transition/transition/index.js
340 d3/d3-transition/transition/interpolate.js
653 d3/d3-transition/transition/merge.js
853 d3/d3-transition/transition/on.js
284 d3/d3-transition/transition/remove.js
4792 d3/d3-transition/transition/schedule.js
826 d3/d3-transition/transition/select.js
883 d3/d3-transition/transition/selectAll.js
174 d3/d3-transition/transition/selection.js
2119 d3/d3-transition/transition/style.js
607 d3/d3-transition/transition/styleTween.js
473 d3/d3-transition/transition/text.js
691 d3/d3-transition/transition/transition.js
2026 d3/d3-transition/transition/tween.js
4381 d3/d3-voronoi/Beach.js
4087 d3/d3-voronoi/Cell.js
1632 d3/d3-voronoi/Circle.js
72 d3/d3-voronoi/constant.js
3415 d3/d3-voronoi/Diagram.js
3634 d3/d3-voronoi/Edge.js
81 d3/d3-voronoi/point.js
5302 d3/d3-voronoi/RedBlackTree.js
1420 d3/d3-voronoi/voronoi.js
72 d3/d3-zoom/constant.js
137 d3/d3-zoom/event.js
202 d3/d3-zoom/noevent.js
1336 d3/d3-zoom/transform.js
12133 d3/d3-zoom/zoom.js
<!DOCTYPE html>
<style>
svg {
font: 10px sans-serif;
}
a:hover tspan:first-child {
text-decoration: underline;
}
tspan:last-child {
font-size: 9px;
fill-opacity: 0.7;
}
</style>
<svg width="960" height="960"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="d3-hierarchy.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var format = d3.format(",d");
var treemap = d3.treemap()
.size([width, height])
.round(true)
.padding(1)
.tile(d3.treemapSplit);
var version = {
"d3-array": "1.0.2",
"d3-axis": "1.0.4",
"d3-brush": "1.0.3",
"d3-chord": "1.0.3",
"d3-collection": "1.0.2",
"d3-color": "1.0.2",
"d3-dispatch": "1.0.2",
"d3-drag": "1.0.2",
"d3-dsv": "1.0.3",
"d3-ease": "1.0.2",
"d3-force": "1.0.4",
"d3-format": "1.0.2",
"d3-geo": "1.4.0",
"d3-hierarchy": "1.0.3",
"d3-interpolate": "1.1.2",
"d3-path": "1.0.3",
"d3-polygon": "1.0.2",
"d3-quadtree": "1.0.2",
"d3-queue": "3.0.3",
"d3-random": "1.0.2",
"d3-request": "1.0.3",
"d3-scale": "1.0.4",
"d3-selection": "1.0.3",
"d3-shape": "1.0.4",
"d3-time": "1.0.4",
"d3-time-format": "2.0.3",
"d3-timer": "1.0.3",
"d3-transition": "1.0.3",
"d3-voronoi": "1.1.0",
"d3-zoom": "1.1.0"
};
d3.csv("d3.csv", function(d) {
d.size = +d.size;
return d;
}, function(error, data) {
if (error) throw error;
var root = d3.stratify()
.id(function(d) { return d.path; })
.parentId(function(d) { return d.path.substring(0, d.path.lastIndexOf("/")); })
(data)
.sum(function(d) { return d.size; })
.sort(function(a, b) { return b.height - a.height || b.value - a.value; });
treemap(root);
var cell = svg.selectAll("a")
.data(root.leaves())
.enter().append("a")
.attr("target", "_blank")
.attr("xlink:href", function(d) { var p = d.data.path.split("/"); return "https://github.com/" + p.slice(0, 2).join("/") + "/blob/v" + version[p[1]] + "/src/" + p.slice(2).join("/"); })
.attr("transform", function(d) { return "translate(" + d.x0 + "," + d.y0 + ")"; });
cell.append("rect")
.attr("id", function(d) { return d.id; })
.attr("width", function(d) { return d.x1 - d.x0; })
.attr("height", function(d) { return d.y1 - d.y0; })
.attr("fill", function(d) { var a = d.ancestors(); return color(a[a.length - 2].id); });
cell.append("clipPath")
.attr("id", function(d) { return "clip-" + d.id; })
.append("use")
.attr("xlink:href", function(d) { return "#" + d.id; });
var label = cell.append("text")
.attr("clip-path", function(d) { return "url(#clip-" + d.id + ")"; });
label.append("tspan")
.attr("x", 4)
.attr("y", 13)
.text(function(d) { return d.data.path.substring(d.data.path.lastIndexOf("/") + 1, d.data.path.lastIndexOf(".")); });
label.append("tspan")
.attr("x", 4)
.attr("y", 25)
.text(function(d) { return format(d.value); });
cell.append("title")
.text(function(d) { return d.id + "\n" + format(d.value); });
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment