mirror of
https://github.com/hanzo-labs/exchange-sdk.git
synced 2026-10-30 18:54:21 +00:00
3294 lines
106 KiB
HTML
3294 lines
106 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||
<title>RollUp Visualizer</title>
|
||
<style>:root {
|
||
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
|
||
"Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
|
||
"Noto Color Emoji";
|
||
--background-color: #f5edda;
|
||
--text-color: #6d6875;
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--background-color: #2b2d42;
|
||
--text-color: #edf2f4;
|
||
}
|
||
}
|
||
html {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
*,
|
||
*:before,
|
||
*:after {
|
||
box-sizing: inherit;
|
||
}
|
||
|
||
html {
|
||
background-color: var(--background-color);
|
||
color: var(--text-color);
|
||
font-family: var(--font-family);
|
||
}
|
||
|
||
body {
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
|
||
html,
|
||
body {
|
||
height: 100%;
|
||
width: 100%;
|
||
}
|
||
|
||
body {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
svg {
|
||
vertical-align: middle;
|
||
}
|
||
|
||
h1 {
|
||
font-weight: 600;
|
||
font-size: 70px;
|
||
text-transform: uppercase;
|
||
text-align: center;
|
||
}
|
||
|
||
.chart {
|
||
position: relative;
|
||
margin: 0 auto;
|
||
min-height: 350px;
|
||
}
|
||
|
||
#main {
|
||
width: 1000px;
|
||
margin: 0 auto;
|
||
flex: 1;
|
||
}
|
||
|
||
footer {
|
||
text-align: center;
|
||
font-size: 10px;
|
||
padding: 20px;
|
||
}
|
||
|
||
a {
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.tooltip {
|
||
position: absolute;
|
||
z-index: 1070;
|
||
display: block;
|
||
border: solid;
|
||
border-width: 2px;
|
||
border-radius: 5px;
|
||
margin: 0;
|
||
padding: 5px;
|
||
font-style: normal;
|
||
font-weight: 400;
|
||
line-height: 1.5;
|
||
text-align: left;
|
||
text-decoration: none;
|
||
text-shadow: none;
|
||
text-transform: none;
|
||
letter-spacing: normal;
|
||
word-break: normal;
|
||
word-spacing: normal;
|
||
word-wrap: break-word;
|
||
white-space: normal;
|
||
line-break: auto;
|
||
font-size: 0.875rem;
|
||
opacity: 0;
|
||
background-color: var(--background-color);
|
||
color: var(--text-color);
|
||
}
|
||
|
||
path {
|
||
stroke: #fff;
|
||
}
|
||
|
||
#main {
|
||
width: 700px;
|
||
}
|
||
|
||
.details {
|
||
position: absolute;
|
||
top: 350px;
|
||
left: 50%;
|
||
width: 170px;
|
||
margin-left: -85px;
|
||
font-size: 14px;
|
||
text-align: center;
|
||
color: #eee;
|
||
z-index: 100;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.details-size {
|
||
font-size: 0.8em;
|
||
margin-top: 1em;
|
||
}
|
||
|
||
.details-name {
|
||
font-weight: bold;
|
||
}
|
||
|
||
.details-size::before {
|
||
content: "(";
|
||
}
|
||
|
||
.details-size::after {
|
||
content: ")";
|
||
}
|
||
|
||
.details-percentage {
|
||
margin: 0.4em 0 0em;
|
||
font-size: 2.4em;
|
||
line-height: 1em;
|
||
}
|
||
|
||
rect {
|
||
fill: cadetblue;
|
||
opacity: 0.3;
|
||
stroke: white;
|
||
}</style>
|
||
<style>undefined</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<h1>RollUp Visualizer</h1>
|
||
</header>
|
||
<main id="main"></main>
|
||
<footer>
|
||
<span>Generated with <a href="https://github.com/btd/rollup-plugin-visualizer" target="_blank" rel="noopener noreferrer">rollup-plugin-visualizer</a></span>
|
||
</footer>
|
||
<script>window.nodesData = [{"id":"index.esm.js","root":{"name":"root","children":[{"name":"\u0000rollupPluginBabelHelpers.js","children":[],"size":1224,"originalSize":42897},{"name":"node_modules","children":[{"name":"uuid","children":[{"name":"lib","children":[{"name":"rng.js","children":[],"size":209,"originalSize":246},{"name":"bytesToUuid.js","children":[],"size":749,"originalSize":747}]},{"name":"v1.js","children":[],"size":3250,"originalSize":3336},{"name":"v4.js","children":[],"size":594,"originalSize":680},{"name":"index.js","children":[],"size":68,"originalSize":120}]},{"name":"decimal.js","children":[{"name":"decimal.mjs","children":[],"size":125465,"originalSize":125523}]},{"name":"performance-now","children":[{"name":"lib","children":[{"name":"performance-now.js","children":[],"size":1093,"originalSize":1061}]}]},{"name":"raf","children":[{"name":"index.js","children":[],"size":1970,"originalSize":1933}]},{"name":"mnemonist","children":[{"name":"utils","children":[{"name":"comparators.js","children":[],"size":879,"originalSize":720}]},{"name":"fibonacci-heap.js","children":[],"size":6349,"originalSize":6435}]},{"name":"obliterator","children":[{"name":"foreach.js","children":[],"size":3532,"originalSize":3536}]},{"name":"avl","children":[{"name":"src","children":[{"name":"utils.js","children":[],"size":3035,"originalSize":3072},{"name":"index.js","children":[],"size":15011,"originalSize":15108}]}]},{"name":"moment","children":[{"name":"moment.js","children":[],"size":150830,"originalSize":150941}]},{"name":"moment-timezone","children":[{"name":"moment-timezone.js","children":[],"size":14651,"originalSize":14758},{"name":"data","children":[{"name":"packed","children":[{"name":"latest.json","children":[],"size":178963,"originalSize":180690}]}]},{"name":"index.js","children":[],"size":141,"originalSize":114}]},{"name":"depd","children":[{"name":"lib","children":[{"name":"compat","children":[{"name":"callsite-tostring.js","children":[],"size":2250,"originalSize":2229},{"name":"event-listener-count.js","children":[],"size":334,"originalSize":338},{"name":"index.js","children":[],"size":1356,"originalSize":1421}]}]},{"name":"index.js","children":[],"size":10689,"originalSize":10669}]},{"name":"bytes","children":[{"name":"index.js","children":[],"size":3485,"originalSize":3469}]},{"name":"content-type","children":[{"name":"index.js","children":[],"size":4899,"originalSize":4809}]},{"name":"setprototypeof","children":[{"name":"index.js","children":[],"size":377,"originalSize":384}]},{"name":"statuses","children":[{"name":"codes.json","children":[],"size":1576,"originalSize":1821},{"name":"index.js","children":[],"size":1937,"originalSize":2088}]},{"name":"inherits","children":[{"name":"inherits_browser.js","children":[],"size":746,"originalSize":672},{"name":"inherits.js","children":[],"size":230,"originalSize":192}]},{"name":"toidentifier","children":[{"name":"index.js","children":[],"size":492,"originalSize":490}]},{"name":"http-errors","children":[{"name":"index.js","children":[],"size":5739,"originalSize":5878}]},{"name":"ms","children":[{"name":"index.js","children":[],"size":2759,"originalSize":2764}]},{"name":"debug","children":[{"name":"src","children":[{"name":"debug.js","children":[],"size":4677,"originalSize":4394},{"name":"browser.js","children":[],"size":5014,"originalSize":4734},{"name":"node.js","children":[],"size":6212,"originalSize":6015},{"name":"index.js","children":[],"size":285,"originalSize":263}]}]},{"name":"safer-buffer","children":[{"name":"safer.js","children":[],"size":2047,"originalSize":2110}]},{"name":"iconv-lite","children":[{"name":"lib","children":[{"name":"bom-handling.js","children":[],"size":1158,"originalSize":1109},{"name":"streams.js","children":[],"size":3359,"originalSize":3387},{"name":"extend-node.js","children":[],"size":8688,"originalSize":8701},{"name":"index.js","children":[],"size":4847,"originalSize":5120}]},{"name":"encodings","children":[{"name":"internal.js","children":[],"size":6089,"originalSize":6113},{"name":"utf16.js","children":[],"size":5043,"originalSize":5011},{"name":"utf7.js","children":[],"size":9291,"originalSize":9215},{"name":"sbcs-codec.js","children":[],"size":2206,"originalSize":2191},{"name":"sbcs-data.js","children":[],"size":4165,"originalSize":4184},{"name":"sbcs-data-generated.js","children":[],"size":18858,"originalSize":18865},{"name":"dbcs-codec.js","children":[],"size":20963,"originalSize":21415},{"name":"tables","children":[{"name":"shiftjis.json","children":[],"size":8996,"originalSize":9105},{"name":"eucjp.json","children":[],"size":15450,"originalSize":15619},{"name":"cp936.json","children":[],"size":20548,"originalSize":20799},{"name":"gbk-added.json","children":[],"size":915,"originalSize":954},{"name":"gb18030-ranges.json","children":[],"size":2275,"originalSize":2216},{"name":"cp949.json","children":[],"size":17065,"originalSize":17325},{"name":"cp950.json","children":[],"size":15527,"originalSize":15691},{"name":"big5-added.json","children":[],"size":8047,"originalSize":8152}]},{"name":"dbcs-data.js","children":[],"size":8007,"originalSize":8288},{"name":"index.js","children":[],"size":655,"originalSize":710}]}]},{"name":"unpipe","children":[{"name":"index.js","children":[],"size":1108,"originalSize":1118}]},{"name":"raw-body","children":[{"name":"index.js","children":[],"size":5834,"originalSize":6059}]},{"name":"ee-first","children":[{"name":"index.js","children":[],"size":1686,"originalSize":1684}]},{"name":"on-finished","children":[{"name":"index.js","children":[],"size":3588,"originalSize":3686}]},{"name":"body-parser","children":[{"name":"lib","children":[{"name":"read.js","children":[],"size":3642,"originalSize":3894},{"name":"types","children":[{"name":"json.js","children":[],"size":4644,"originalSize":4918},{"name":"raw.js","children":[],"size":1707,"originalSize":1884},{"name":"text.js","children":[],"size":2074,"originalSize":2285},{"name":"urlencoded.js","children":[],"size":5526,"originalSize":5797}]}]},{"name":"index.js","children":[],"size":2547,"originalSize":2656}]},{"name":"media-typer","children":[{"name":"index.js","children":[],"size":6492,"originalSize":6375}]},{"name":"mime-db","children":[{"name":"db.json","children":[],"size":129607,"originalSize":174026},{"name":"index.js","children":[],"size":124,"originalSize":136}]},{"name":"mime-types","children":[{"name":"index.js","children":[],"size":3872,"originalSize":3663}]},{"name":"type-is","children":[{"name":"index.js","children":[],"size":5442,"originalSize":5562}]},{"name":"qs","children":[{"name":"lib","children":[{"name":"utils.js","children":[],"size":6183,"originalSize":6204},{"name":"formats.js","children":[],"size":368,"originalSize":387},{"name":"stringify.js","children":[],"size":8163,"originalSize":8228},{"name":"parse.js","children":[],"size":8478,"originalSize":8486},{"name":"index.js","children":[],"size":85,"originalSize":211}]}]},{"name":"merge-descriptors","children":[{"name":"index.js","children":[],"size":1216,"originalSize":1215}]},{"name":"encodeurl","children":[{"name":"index.js","children":[],"size":1574,"originalSize":1586}]},{"name":"escape-html","children":[{"name":"index.js","children":[],"size":1348,"originalSize":1362}]},{"name":"parseurl","children":[{"name":"index.js","children":[],"size":2693,"originalSize":2809}]},{"name":"finalhandler","children":[{"name":"index.js","children":[],"size":6266,"originalSize":6518}]},{"name":"array-flatten","children":[{"name":"array-flatten.js","children":[],"size":1191,"originalSize":1195}]},{"name":"path-to-regexp","children":[{"name":"index.js","children":[],"size":3329,"originalSize":3328}]},{"name":"express","children":[{"name":"lib","children":[{"name":"router","children":[{"name":"layer.js","children":[],"size":3074,"originalSize":3296},{"name":"route.js","children":[],"size":3882,"originalSize":4149},{"name":"index.js","children":[],"size":14545,"originalSize":14883}]},{"name":"middleware","children":[{"name":"init.js","children":[],"size":655,"originalSize":853},{"name":"query.js","children":[],"size":617,"originalSize":885}]},{"name":"view.js","children":[],"size":3112,"originalSize":3326},{"name":"utils.js","children":[],"size":6008,"originalSize":5972},{"name":"application.js","children":[],"size":13749,"originalSize":14270},{"name":"request.js","children":[],"size":12097,"originalSize":12504},{"name":"response.js","children":[],"size":26638,"originalSize":27124},{"name":"express.js","children":[],"size":2391,"originalSize":2409}]},{"name":"index.js","children":[],"size":24,"originalSize":224}]},{"name":"methods","children":[{"name":"index.js","children":[],"size":864,"originalSize":1040}]},{"name":"utils-merge","children":[{"name":"index.js","children":[],"size":451,"originalSize":381}]},{"name":"safe-buffer","children":[{"name":"index.js","children":[],"size":1621,"originalSize":1529}]},{"name":"content-disposition","children":[{"name":"index.js","children":[],"size":10607,"originalSize":10594}]},{"name":"destroy","children":[{"name":"index.js","children":[],"size":938,"originalSize":1043}]},{"name":"etag","children":[{"name":"index.js","children":[],"size":2351,"originalSize":2479}]},{"name":"fresh","children":[{"name":"index.js","children":[],"size":2718,"originalSize":2711}]},{"name":"mime","children":[{"name":"types.json","children":[],"size":31568,"originalSize":31555},{"name":"mime.js","children":[],"size":2657,"originalSize":2726}]},{"name":"send","children":[{"name":"node_modules","children":[{"name":"ms","children":[{"name":"index.js","children":[],"size":3111,"originalSize":3034}]}]},{"name":"index.js","children":[],"size":23104,"originalSize":23287}]},{"name":"range-parser","children":[{"name":"index.js","children":[],"size":2910,"originalSize":2900}]},{"name":"forwarded","children":[{"name":"index.js","children":[],"size":1362,"originalSize":1360}]},{"name":"ipaddr.js","children":[{"name":"lib","children":[{"name":"ipaddr.js","children":[],"size":19211,"originalSize":19333}]}]},{"name":"proxy-addr","children":[{"name":"index.js","children":[],"size":5885,"originalSize":5977}]},{"name":"negotiator","children":[{"name":"lib","children":[{"name":"charset.js","children":[],"size":3103,"originalSize":3081},{"name":"encoding.js","children":[],"size":3547,"originalSize":3506},{"name":"language.js","children":[],"size":3449,"originalSize":3408},{"name":"mediaType.js","children":[],"size":5406,"originalSize":5358}]},{"name":"index.js","children":[],"size":3120,"originalSize":3344}]},{"name":"accepts","children":[{"name":"index.js","children":[],"size":5073,"originalSize":5252}]},{"name":"cookie-signature","children":[{"name":"index.js","children":[],"size":1372,"originalSize":1230}]},{"name":"cookie","children":[{"name":"index.js","children":[],"size":4095,"originalSize":4037}]},{"name":"vary","children":[{"name":"index.js","children":[],"size":2954,"originalSize":2930}]},{"name":"serve-static","children":[{"name":"index.js","children":[],"size":4314,"originalSize":4570}]},{"name":"object-assign","children":[{"name":"index.js","children":[],"size":2098,"originalSize":2108}]},{"name":"cors","children":[{"name":"lib","children":[{"name":"index.js","children":[],"size":6612,"originalSize":6623}]}]}]},{"name":"src","children":[{"name":"utils","children":[{"name":"time.ts","children":[],"size":218,"originalSize":312}]},{"name":"Order.ts","children":[],"size":2455,"originalSize":2599},{"name":"Trade.ts","children":[],"size":1518,"originalSize":1542},{"name":"Book.ts","children":[],"size":13064,"originalSize":13312},{"name":"Candle.ts","children":[],"size":3848,"originalSize":5397},{"name":"servers","children":[{"name":"http.ts","children":[],"size":1710,"originalSize":2118},{"name":"socketio.ts","children":[],"size":4222,"originalSize":4534}]}]},{"name":"\u0000commonjsHelpers.js","children":[],"size":518,"originalSize":686},{"name":"\u0000/home/groot/matching-engine/node_modules/moment-timezone/data/packed/latest.json?commonjs-proxy","children":[],"size":53,"originalSize":219},{"name":"\u0000/home/groot/matching-engine/node_modules/statuses/codes.json?commonjs-proxy","children":[],"size":49,"originalSize":197},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/shiftjis.json?commonjs-proxy","children":[],"size":55,"originalSize":225},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/eucjp.json?commonjs-proxy","children":[],"size":54,"originalSize":216},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/cp936.json?commonjs-proxy","children":[],"size":52,"originalSize":216},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/gbk-added.json?commonjs-proxy","children":[],"size":55,"originalSize":226},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json?commonjs-proxy","children":[],"size":60,"originalSize":241},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/cp949.json?commonjs-proxy","children":[],"size":52,"originalSize":216},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/cp950.json?commonjs-proxy","children":[],"size":52,"originalSize":216},{"name":"\u0000/home/groot/matching-engine/node_modules/iconv-lite/encodings/tables/big5-added.json?commonjs-proxy","children":[],"size":56,"originalSize":229},{"name":"\u0000/home/groot/matching-engine/node_modules/mime-db/db.json?commonjs-proxy","children":[],"size":51,"originalSize":187},{"name":"\u0000/home/groot/matching-engine/node_modules/mime/types.json?commonjs-proxy","children":[],"size":54,"originalSize":193}]}}];</script>
|
||
<script>window.chartParameters = {};</script>
|
||
<script>(function () {
|
||
'use strict';
|
||
|
||
var xhtml = "http://www.w3.org/1999/xhtml";
|
||
|
||
var namespaces = {
|
||
svg: "http://www.w3.org/2000/svg",
|
||
xhtml: xhtml,
|
||
xlink: "http://www.w3.org/1999/xlink",
|
||
xml: "http://www.w3.org/XML/1998/namespace",
|
||
xmlns: "http://www.w3.org/2000/xmlns/"
|
||
};
|
||
|
||
function namespace(name) {
|
||
var prefix = name += "", i = prefix.indexOf(":");
|
||
if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
|
||
return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
|
||
}
|
||
|
||
function creatorInherit(name) {
|
||
return function() {
|
||
var document = this.ownerDocument,
|
||
uri = this.namespaceURI;
|
||
return uri === xhtml && document.documentElement.namespaceURI === xhtml
|
||
? document.createElement(name)
|
||
: document.createElementNS(uri, name);
|
||
};
|
||
}
|
||
|
||
function creatorFixed(fullname) {
|
||
return function() {
|
||
return this.ownerDocument.createElementNS(fullname.space, fullname.local);
|
||
};
|
||
}
|
||
|
||
function creator(name) {
|
||
var fullname = namespace(name);
|
||
return (fullname.local
|
||
? creatorFixed
|
||
: creatorInherit)(fullname);
|
||
}
|
||
|
||
function none() {}
|
||
|
||
function selector(selector) {
|
||
return selector == null ? none : function() {
|
||
return this.querySelector(selector);
|
||
};
|
||
}
|
||
|
||
function selection_select(select) {
|
||
if (typeof select !== "function") select = selector(select);
|
||
|
||
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
|
||
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
|
||
if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
|
||
if ("__data__" in node) subnode.__data__ = node.__data__;
|
||
subgroup[i] = subnode;
|
||
}
|
||
}
|
||
}
|
||
|
||
return new Selection(subgroups, this._parents);
|
||
}
|
||
|
||
function empty() {
|
||
return [];
|
||
}
|
||
|
||
function selectorAll(selector) {
|
||
return selector == null ? empty : function() {
|
||
return this.querySelectorAll(selector);
|
||
};
|
||
}
|
||
|
||
function selection_selectAll(select) {
|
||
if (typeof select !== "function") select = selectorAll(select);
|
||
|
||
for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
|
||
for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
|
||
if (node = group[i]) {
|
||
subgroups.push(select.call(node, node.__data__, i, group));
|
||
parents.push(node);
|
||
}
|
||
}
|
||
}
|
||
|
||
return new Selection(subgroups, parents);
|
||
}
|
||
|
||
function matcher(selector) {
|
||
return function() {
|
||
return this.matches(selector);
|
||
};
|
||
}
|
||
|
||
function selection_filter(match) {
|
||
if (typeof match !== "function") match = matcher(match);
|
||
|
||
for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
|
||
for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
|
||
if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
|
||
subgroup.push(node);
|
||
}
|
||
}
|
||
}
|
||
|
||
return new Selection(subgroups, this._parents);
|
||
}
|
||
|
||
function sparse(update) {
|
||
return new Array(update.length);
|
||
}
|
||
|
||
function selection_enter() {
|
||
return new Selection(this._enter || this._groups.map(sparse), this._parents);
|
||
}
|
||
|
||
function EnterNode(parent, datum) {
|
||
this.ownerDocument = parent.ownerDocument;
|
||
this.namespaceURI = parent.namespaceURI;
|
||
this._next = null;
|
||
this._parent = parent;
|
||
this.__data__ = datum;
|
||
}
|
||
|
||
EnterNode.prototype = {
|
||
constructor: EnterNode,
|
||
appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
|
||
insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
|
||
querySelector: function(selector) { return this._parent.querySelector(selector); },
|
||
querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
|
||
};
|
||
|
||
function constant(x) {
|
||
return function() {
|
||
return x;
|
||
};
|
||
}
|
||
|
||
var keyPrefix = "$"; // Protect against keys like “__proto__”.
|
||
|
||
function bindIndex(parent, group, enter, update, exit, data) {
|
||
var i = 0,
|
||
node,
|
||
groupLength = group.length,
|
||
dataLength = data.length;
|
||
|
||
// Put any non-null nodes that fit into update.
|
||
// Put any null nodes into enter.
|
||
// Put any remaining data into enter.
|
||
for (; i < dataLength; ++i) {
|
||
if (node = group[i]) {
|
||
node.__data__ = data[i];
|
||
update[i] = node;
|
||
} else {
|
||
enter[i] = new EnterNode(parent, data[i]);
|
||
}
|
||
}
|
||
|
||
// Put any non-null nodes that don’t fit into exit.
|
||
for (; i < groupLength; ++i) {
|
||
if (node = group[i]) {
|
||
exit[i] = node;
|
||
}
|
||
}
|
||
}
|
||
|
||
function bindKey(parent, group, enter, update, exit, data, key) {
|
||
var i,
|
||
node,
|
||
nodeByKeyValue = {},
|
||
groupLength = group.length,
|
||
dataLength = data.length,
|
||
keyValues = new Array(groupLength),
|
||
keyValue;
|
||
|
||
// Compute the key for each node.
|
||
// If multiple nodes have the same key, the duplicates are added to exit.
|
||
for (i = 0; i < groupLength; ++i) {
|
||
if (node = group[i]) {
|
||
keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
|
||
if (keyValue in nodeByKeyValue) {
|
||
exit[i] = node;
|
||
} else {
|
||
nodeByKeyValue[keyValue] = node;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Compute the key for each datum.
|
||
// If there a node associated with this key, join and add it to update.
|
||
// If there is not (or the key is a duplicate), add it to enter.
|
||
for (i = 0; i < dataLength; ++i) {
|
||
keyValue = keyPrefix + key.call(parent, data[i], i, data);
|
||
if (node = nodeByKeyValue[keyValue]) {
|
||
update[i] = node;
|
||
node.__data__ = data[i];
|
||
nodeByKeyValue[keyValue] = null;
|
||
} else {
|
||
enter[i] = new EnterNode(parent, data[i]);
|
||
}
|
||
}
|
||
|
||
// Add any remaining nodes that were not bound to data to exit.
|
||
for (i = 0; i < groupLength; ++i) {
|
||
if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
|
||
exit[i] = node;
|
||
}
|
||
}
|
||
}
|
||
|
||
function selection_data(value, key) {
|
||
if (!value) {
|
||
data = new Array(this.size()), j = -1;
|
||
this.each(function(d) { data[++j] = d; });
|
||
return data;
|
||
}
|
||
|
||
var bind = key ? bindKey : bindIndex,
|
||
parents = this._parents,
|
||
groups = this._groups;
|
||
|
||
if (typeof value !== "function") value = constant(value);
|
||
|
||
for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
|
||
var parent = parents[j],
|
||
group = groups[j],
|
||
groupLength = group.length,
|
||
data = value.call(parent, parent && parent.__data__, j, parents),
|
||
dataLength = data.length,
|
||
enterGroup = enter[j] = new Array(dataLength),
|
||
updateGroup = update[j] = new Array(dataLength),
|
||
exitGroup = exit[j] = new Array(groupLength);
|
||
|
||
bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
|
||
|
||
// Now connect the enter nodes to their following update node, such that
|
||
// appendChild can insert the materialized enter node before this node,
|
||
// rather than at the end of the parent node.
|
||
for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
|
||
if (previous = enterGroup[i0]) {
|
||
if (i0 >= i1) i1 = i0 + 1;
|
||
while (!(next = updateGroup[i1]) && ++i1 < dataLength);
|
||
previous._next = next || null;
|
||
}
|
||
}
|
||
}
|
||
|
||
update = new Selection(update, parents);
|
||
update._enter = enter;
|
||
update._exit = exit;
|
||
return update;
|
||
}
|
||
|
||
function selection_exit() {
|
||
return new Selection(this._exit || this._groups.map(sparse), this._parents);
|
||
}
|
||
|
||
function selection_join(onenter, onupdate, onexit) {
|
||
var enter = this.enter(), update = this, exit = this.exit();
|
||
enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
|
||
if (onupdate != null) update = onupdate(update);
|
||
if (onexit == null) exit.remove(); else onexit(exit);
|
||
return enter && update ? enter.merge(update).order() : update;
|
||
}
|
||
|
||
function selection_merge(selection) {
|
||
|
||
for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
|
||
for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
|
||
if (node = group0[i] || group1[i]) {
|
||
merge[i] = node;
|
||
}
|
||
}
|
||
}
|
||
|
||
for (; j < m0; ++j) {
|
||
merges[j] = groups0[j];
|
||
}
|
||
|
||
return new Selection(merges, this._parents);
|
||
}
|
||
|
||
function selection_order() {
|
||
|
||
for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
|
||
for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
|
||
if (node = group[i]) {
|
||
if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
|
||
next = node;
|
||
}
|
||
}
|
||
}
|
||
|
||
return this;
|
||
}
|
||
|
||
function selection_sort(compare) {
|
||
if (!compare) compare = ascending;
|
||
|
||
function compareNode(a, b) {
|
||
return a && b ? compare(a.__data__, b.__data__) : !a - !b;
|
||
}
|
||
|
||
for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
|
||
for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
|
||
if (node = group[i]) {
|
||
sortgroup[i] = node;
|
||
}
|
||
}
|
||
sortgroup.sort(compareNode);
|
||
}
|
||
|
||
return new Selection(sortgroups, this._parents).order();
|
||
}
|
||
|
||
function ascending(a, b) {
|
||
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
|
||
}
|
||
|
||
function selection_call() {
|
||
var callback = arguments[0];
|
||
arguments[0] = this;
|
||
callback.apply(null, arguments);
|
||
return this;
|
||
}
|
||
|
||
function selection_nodes() {
|
||
var nodes = new Array(this.size()), i = -1;
|
||
this.each(function() { nodes[++i] = this; });
|
||
return nodes;
|
||
}
|
||
|
||
function selection_node() {
|
||
|
||
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
|
||
for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
|
||
var node = group[i];
|
||
if (node) return node;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function selection_size() {
|
||
var size = 0;
|
||
this.each(function() { ++size; });
|
||
return size;
|
||
}
|
||
|
||
function selection_empty() {
|
||
return !this.node();
|
||
}
|
||
|
||
function selection_each(callback) {
|
||
|
||
for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
|
||
for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
|
||
if (node = group[i]) callback.call(node, node.__data__, i, group);
|
||
}
|
||
}
|
||
|
||
return this;
|
||
}
|
||
|
||
function attrRemove(name) {
|
||
return function() {
|
||
this.removeAttribute(name);
|
||
};
|
||
}
|
||
|
||
function attrRemoveNS(fullname) {
|
||
return function() {
|
||
this.removeAttributeNS(fullname.space, fullname.local);
|
||
};
|
||
}
|
||
|
||
function attrConstant(name, value) {
|
||
return function() {
|
||
this.setAttribute(name, value);
|
||
};
|
||
}
|
||
|
||
function attrConstantNS(fullname, value) {
|
||
return function() {
|
||
this.setAttributeNS(fullname.space, fullname.local, value);
|
||
};
|
||
}
|
||
|
||
function attrFunction(name, value) {
|
||
return function() {
|
||
var v = value.apply(this, arguments);
|
||
if (v == null) this.removeAttribute(name);
|
||
else this.setAttribute(name, v);
|
||
};
|
||
}
|
||
|
||
function attrFunctionNS(fullname, value) {
|
||
return function() {
|
||
var v = value.apply(this, arguments);
|
||
if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
|
||
else this.setAttributeNS(fullname.space, fullname.local, v);
|
||
};
|
||
}
|
||
|
||
function selection_attr(name, value) {
|
||
var fullname = namespace(name);
|
||
|
||
if (arguments.length < 2) {
|
||
var node = this.node();
|
||
return fullname.local
|
||
? node.getAttributeNS(fullname.space, fullname.local)
|
||
: node.getAttribute(fullname);
|
||
}
|
||
|
||
return this.each((value == null
|
||
? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
|
||
? (fullname.local ? attrFunctionNS : attrFunction)
|
||
: (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
|
||
}
|
||
|
||
function defaultView(node) {
|
||
return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
|
||
|| (node.document && node) // node is a Window
|
||
|| node.defaultView; // node is a Document
|
||
}
|
||
|
||
function styleRemove(name) {
|
||
return function() {
|
||
this.style.removeProperty(name);
|
||
};
|
||
}
|
||
|
||
function styleConstant(name, value, priority) {
|
||
return function() {
|
||
this.style.setProperty(name, value, priority);
|
||
};
|
||
}
|
||
|
||
function styleFunction(name, value, priority) {
|
||
return function() {
|
||
var v = value.apply(this, arguments);
|
||
if (v == null) this.style.removeProperty(name);
|
||
else this.style.setProperty(name, v, priority);
|
||
};
|
||
}
|
||
|
||
function selection_style(name, value, priority) {
|
||
return arguments.length > 1
|
||
? this.each((value == null
|
||
? styleRemove : typeof value === "function"
|
||
? styleFunction
|
||
: styleConstant)(name, value, priority == null ? "" : priority))
|
||
: styleValue(this.node(), name);
|
||
}
|
||
|
||
function styleValue(node, name) {
|
||
return node.style.getPropertyValue(name)
|
||
|| defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
|
||
}
|
||
|
||
function propertyRemove(name) {
|
||
return function() {
|
||
delete this[name];
|
||
};
|
||
}
|
||
|
||
function propertyConstant(name, value) {
|
||
return function() {
|
||
this[name] = value;
|
||
};
|
||
}
|
||
|
||
function propertyFunction(name, value) {
|
||
return function() {
|
||
var v = value.apply(this, arguments);
|
||
if (v == null) delete this[name];
|
||
else this[name] = v;
|
||
};
|
||
}
|
||
|
||
function selection_property(name, value) {
|
||
return arguments.length > 1
|
||
? this.each((value == null
|
||
? propertyRemove : typeof value === "function"
|
||
? propertyFunction
|
||
: propertyConstant)(name, value))
|
||
: this.node()[name];
|
||
}
|
||
|
||
function classArray(string) {
|
||
return string.trim().split(/^|\s+/);
|
||
}
|
||
|
||
function classList(node) {
|
||
return node.classList || new ClassList(node);
|
||
}
|
||
|
||
function ClassList(node) {
|
||
this._node = node;
|
||
this._names = classArray(node.getAttribute("class") || "");
|
||
}
|
||
|
||
ClassList.prototype = {
|
||
add: function(name) {
|
||
var i = this._names.indexOf(name);
|
||
if (i < 0) {
|
||
this._names.push(name);
|
||
this._node.setAttribute("class", this._names.join(" "));
|
||
}
|
||
},
|
||
remove: function(name) {
|
||
var i = this._names.indexOf(name);
|
||
if (i >= 0) {
|
||
this._names.splice(i, 1);
|
||
this._node.setAttribute("class", this._names.join(" "));
|
||
}
|
||
},
|
||
contains: function(name) {
|
||
return this._names.indexOf(name) >= 0;
|
||
}
|
||
};
|
||
|
||
function classedAdd(node, names) {
|
||
var list = classList(node), i = -1, n = names.length;
|
||
while (++i < n) list.add(names[i]);
|
||
}
|
||
|
||
function classedRemove(node, names) {
|
||
var list = classList(node), i = -1, n = names.length;
|
||
while (++i < n) list.remove(names[i]);
|
||
}
|
||
|
||
function classedTrue(names) {
|
||
return function() {
|
||
classedAdd(this, names);
|
||
};
|
||
}
|
||
|
||
function classedFalse(names) {
|
||
return function() {
|
||
classedRemove(this, names);
|
||
};
|
||
}
|
||
|
||
function classedFunction(names, value) {
|
||
return function() {
|
||
(value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
|
||
};
|
||
}
|
||
|
||
function selection_classed(name, value) {
|
||
var names = classArray(name + "");
|
||
|
||
if (arguments.length < 2) {
|
||
var list = classList(this.node()), i = -1, n = names.length;
|
||
while (++i < n) if (!list.contains(names[i])) return false;
|
||
return true;
|
||
}
|
||
|
||
return this.each((typeof value === "function"
|
||
? classedFunction : value
|
||
? classedTrue
|
||
: classedFalse)(names, value));
|
||
}
|
||
|
||
function textRemove() {
|
||
this.textContent = "";
|
||
}
|
||
|
||
function textConstant(value) {
|
||
return function() {
|
||
this.textContent = value;
|
||
};
|
||
}
|
||
|
||
function textFunction(value) {
|
||
return function() {
|
||
var v = value.apply(this, arguments);
|
||
this.textContent = v == null ? "" : v;
|
||
};
|
||
}
|
||
|
||
function selection_text(value) {
|
||
return arguments.length
|
||
? this.each(value == null
|
||
? textRemove : (typeof value === "function"
|
||
? textFunction
|
||
: textConstant)(value))
|
||
: this.node().textContent;
|
||
}
|
||
|
||
function htmlRemove() {
|
||
this.innerHTML = "";
|
||
}
|
||
|
||
function htmlConstant(value) {
|
||
return function() {
|
||
this.innerHTML = value;
|
||
};
|
||
}
|
||
|
||
function htmlFunction(value) {
|
||
return function() {
|
||
var v = value.apply(this, arguments);
|
||
this.innerHTML = v == null ? "" : v;
|
||
};
|
||
}
|
||
|
||
function selection_html(value) {
|
||
return arguments.length
|
||
? this.each(value == null
|
||
? htmlRemove : (typeof value === "function"
|
||
? htmlFunction
|
||
: htmlConstant)(value))
|
||
: this.node().innerHTML;
|
||
}
|
||
|
||
function raise() {
|
||
if (this.nextSibling) this.parentNode.appendChild(this);
|
||
}
|
||
|
||
function selection_raise() {
|
||
return this.each(raise);
|
||
}
|
||
|
||
function lower() {
|
||
if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
|
||
}
|
||
|
||
function selection_lower() {
|
||
return this.each(lower);
|
||
}
|
||
|
||
function selection_append(name) {
|
||
var create = typeof name === "function" ? name : creator(name);
|
||
return this.select(function() {
|
||
return this.appendChild(create.apply(this, arguments));
|
||
});
|
||
}
|
||
|
||
function constantNull() {
|
||
return null;
|
||
}
|
||
|
||
function selection_insert(name, before) {
|
||
var create = typeof name === "function" ? name : creator(name),
|
||
select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
|
||
return this.select(function() {
|
||
return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
|
||
});
|
||
}
|
||
|
||
function remove() {
|
||
var parent = this.parentNode;
|
||
if (parent) parent.removeChild(this);
|
||
}
|
||
|
||
function selection_remove() {
|
||
return this.each(remove);
|
||
}
|
||
|
||
function selection_cloneShallow() {
|
||
return this.parentNode.insertBefore(this.cloneNode(false), this.nextSibling);
|
||
}
|
||
|
||
function selection_cloneDeep() {
|
||
return this.parentNode.insertBefore(this.cloneNode(true), this.nextSibling);
|
||
}
|
||
|
||
function selection_clone(deep) {
|
||
return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
|
||
}
|
||
|
||
function selection_datum(value) {
|
||
return arguments.length
|
||
? this.property("__data__", value)
|
||
: this.node().__data__;
|
||
}
|
||
|
||
var filterEvents = {};
|
||
|
||
if (typeof document !== "undefined") {
|
||
var element = document.documentElement;
|
||
if (!("onmouseenter" in element)) {
|
||
filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
|
||
}
|
||
}
|
||
|
||
function filterContextListener(listener, index, group) {
|
||
listener = contextListener(listener, index, group);
|
||
return function(event) {
|
||
var related = event.relatedTarget;
|
||
if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
|
||
listener.call(this, event);
|
||
}
|
||
};
|
||
}
|
||
|
||
function contextListener(listener, index, group) {
|
||
return function(event1) {
|
||
try {
|
||
listener.call(this, this.__data__, index, group);
|
||
} finally {
|
||
}
|
||
};
|
||
}
|
||
|
||
function parseTypenames(typenames) {
|
||
return typenames.trim().split(/^|\s+/).map(function(t) {
|
||
var name = "", i = t.indexOf(".");
|
||
if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
|
||
return {type: t, name: name};
|
||
});
|
||
}
|
||
|
||
function onRemove(typename) {
|
||
return function() {
|
||
var on = this.__on;
|
||
if (!on) return;
|
||
for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
|
||
if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
|
||
this.removeEventListener(o.type, o.listener, o.capture);
|
||
} else {
|
||
on[++i] = o;
|
||
}
|
||
}
|
||
if (++i) on.length = i;
|
||
else delete this.__on;
|
||
};
|
||
}
|
||
|
||
function onAdd(typename, value, capture) {
|
||
var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
|
||
return function(d, i, group) {
|
||
var on = this.__on, o, listener = wrap(value, i, group);
|
||
if (on) for (var j = 0, m = on.length; j < m; ++j) {
|
||
if ((o = on[j]).type === typename.type && o.name === typename.name) {
|
||
this.removeEventListener(o.type, o.listener, o.capture);
|
||
this.addEventListener(o.type, o.listener = listener, o.capture = capture);
|
||
o.value = value;
|
||
return;
|
||
}
|
||
}
|
||
this.addEventListener(typename.type, listener, capture);
|
||
o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
|
||
if (!on) this.__on = [o];
|
||
else on.push(o);
|
||
};
|
||
}
|
||
|
||
function selection_on(typename, value, capture) {
|
||
var typenames = parseTypenames(typename + ""), i, n = typenames.length, t;
|
||
|
||
if (arguments.length < 2) {
|
||
var on = this.node().__on;
|
||
if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
|
||
for (i = 0, o = on[j]; i < n; ++i) {
|
||
if ((t = typenames[i]).type === o.type && t.name === o.name) {
|
||
return o.value;
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
on = value ? onAdd : onRemove;
|
||
if (capture == null) capture = false;
|
||
for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
|
||
return this;
|
||
}
|
||
|
||
function dispatchEvent(node, type, params) {
|
||
var window = defaultView(node),
|
||
event = window.CustomEvent;
|
||
|
||
if (typeof event === "function") {
|
||
event = new event(type, params);
|
||
} else {
|
||
event = window.document.createEvent("Event");
|
||
if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
|
||
else event.initEvent(type, false, false);
|
||
}
|
||
|
||
node.dispatchEvent(event);
|
||
}
|
||
|
||
function dispatchConstant(type, params) {
|
||
return function() {
|
||
return dispatchEvent(this, type, params);
|
||
};
|
||
}
|
||
|
||
function dispatchFunction(type, params) {
|
||
return function() {
|
||
return dispatchEvent(this, type, params.apply(this, arguments));
|
||
};
|
||
}
|
||
|
||
function selection_dispatch(type, params) {
|
||
return this.each((typeof params === "function"
|
||
? dispatchFunction
|
||
: dispatchConstant)(type, params));
|
||
}
|
||
|
||
var root = [null];
|
||
|
||
function Selection(groups, parents) {
|
||
this._groups = groups;
|
||
this._parents = parents;
|
||
}
|
||
|
||
function selection() {
|
||
return new Selection([[document.documentElement]], root);
|
||
}
|
||
|
||
Selection.prototype = selection.prototype = {
|
||
constructor: Selection,
|
||
select: selection_select,
|
||
selectAll: selection_selectAll,
|
||
filter: selection_filter,
|
||
data: selection_data,
|
||
enter: selection_enter,
|
||
exit: selection_exit,
|
||
join: selection_join,
|
||
merge: selection_merge,
|
||
order: selection_order,
|
||
sort: selection_sort,
|
||
call: selection_call,
|
||
nodes: selection_nodes,
|
||
node: selection_node,
|
||
size: selection_size,
|
||
empty: selection_empty,
|
||
each: selection_each,
|
||
attr: selection_attr,
|
||
style: selection_style,
|
||
property: selection_property,
|
||
classed: selection_classed,
|
||
text: selection_text,
|
||
html: selection_html,
|
||
raise: selection_raise,
|
||
lower: selection_lower,
|
||
append: selection_append,
|
||
insert: selection_insert,
|
||
remove: selection_remove,
|
||
clone: selection_clone,
|
||
datum: selection_datum,
|
||
on: selection_on,
|
||
dispatch: selection_dispatch
|
||
};
|
||
|
||
function select(selector) {
|
||
return typeof selector === "string"
|
||
? new Selection([[document.querySelector(selector)]], [document.documentElement])
|
||
: new Selection([[selector]], root);
|
||
}
|
||
|
||
function count(node) {
|
||
var sum = 0,
|
||
children = node.children,
|
||
i = children && children.length;
|
||
if (!i) sum = 1;
|
||
else while (--i >= 0) sum += children[i].value;
|
||
node.value = sum;
|
||
}
|
||
|
||
function node_count() {
|
||
return this.eachAfter(count);
|
||
}
|
||
|
||
function node_each(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;
|
||
}
|
||
|
||
function node_eachBefore(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;
|
||
}
|
||
|
||
function node_eachAfter(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;
|
||
}
|
||
|
||
function node_sum(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;
|
||
});
|
||
}
|
||
|
||
function node_sort(compare) {
|
||
return this.eachBefore(function(node) {
|
||
if (node.children) {
|
||
node.children.sort(compare);
|
||
}
|
||
});
|
||
}
|
||
|
||
function node_path(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;
|
||
}
|
||
|
||
function node_ancestors() {
|
||
var node = this, nodes = [node];
|
||
while (node = node.parent) {
|
||
nodes.push(node);
|
||
}
|
||
return nodes;
|
||
}
|
||
|
||
function node_descendants() {
|
||
var nodes = [];
|
||
this.each(function(node) {
|
||
nodes.push(node);
|
||
});
|
||
return nodes;
|
||
}
|
||
|
||
function node_leaves() {
|
||
var leaves = [];
|
||
this.eachBefore(function(node) {
|
||
if (!node.children) {
|
||
leaves.push(node);
|
||
}
|
||
});
|
||
return leaves;
|
||
}
|
||
|
||
function node_links() {
|
||
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,
|
||
count: node_count,
|
||
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 roundNode(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);
|
||
}
|
||
|
||
function treemapDice(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;
|
||
}
|
||
}
|
||
|
||
function d3partition() {
|
||
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 pi = Math.PI,
|
||
tau = 2 * pi,
|
||
epsilon = 1e-6,
|
||
tauEpsilon = tau - epsilon;
|
||
|
||
function Path() {
|
||
this._x0 = this._y0 = // start of current subpath
|
||
this._x1 = this._y1 = null; // end of current subpath
|
||
this._ = "";
|
||
}
|
||
|
||
function path() {
|
||
return new Path;
|
||
}
|
||
|
||
Path.prototype = path.prototype = {
|
||
constructor: Path,
|
||
moveTo: function(x, y) {
|
||
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
|
||
},
|
||
closePath: function() {
|
||
if (this._x1 !== null) {
|
||
this._x1 = this._x0, this._y1 = this._y0;
|
||
this._ += "Z";
|
||
}
|
||
},
|
||
lineTo: function(x, y) {
|
||
this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
|
||
},
|
||
quadraticCurveTo: function(x1, y1, x, y) {
|
||
this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
|
||
},
|
||
bezierCurveTo: function(x1, y1, x2, y2, x, y) {
|
||
this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
|
||
},
|
||
arcTo: function(x1, y1, x2, y2, r) {
|
||
x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
|
||
var x0 = this._x1,
|
||
y0 = this._y1,
|
||
x21 = x2 - x1,
|
||
y21 = y2 - y1,
|
||
x01 = x0 - x1,
|
||
y01 = y0 - y1,
|
||
l01_2 = x01 * x01 + y01 * y01;
|
||
|
||
// Is the radius negative? Error.
|
||
if (r < 0) throw new Error("negative radius: " + r);
|
||
|
||
// Is this path empty? Move to (x1,y1).
|
||
if (this._x1 === null) {
|
||
this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
|
||
}
|
||
|
||
// Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
|
||
else if (!(l01_2 > epsilon));
|
||
|
||
// Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
|
||
// Equivalently, is (x1,y1) coincident with (x2,y2)?
|
||
// Or, is the radius zero? Line to (x1,y1).
|
||
else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {
|
||
this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
|
||
}
|
||
|
||
// Otherwise, draw an arc!
|
||
else {
|
||
var x20 = x2 - x0,
|
||
y20 = y2 - y0,
|
||
l21_2 = x21 * x21 + y21 * y21,
|
||
l20_2 = x20 * x20 + y20 * y20,
|
||
l21 = Math.sqrt(l21_2),
|
||
l01 = Math.sqrt(l01_2),
|
||
l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
|
||
t01 = l / l01,
|
||
t21 = l / l21;
|
||
|
||
// If the start tangent is not coincident with (x0,y0), line to.
|
||
if (Math.abs(t01 - 1) > epsilon) {
|
||
this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
|
||
}
|
||
|
||
this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
|
||
}
|
||
},
|
||
arc: function(x, y, r, a0, a1, ccw) {
|
||
x = +x, y = +y, r = +r, ccw = !!ccw;
|
||
var dx = r * Math.cos(a0),
|
||
dy = r * Math.sin(a0),
|
||
x0 = x + dx,
|
||
y0 = y + dy,
|
||
cw = 1 ^ ccw,
|
||
da = ccw ? a0 - a1 : a1 - a0;
|
||
|
||
// Is the radius negative? Error.
|
||
if (r < 0) throw new Error("negative radius: " + r);
|
||
|
||
// Is this path empty? Move to (x0,y0).
|
||
if (this._x1 === null) {
|
||
this._ += "M" + x0 + "," + y0;
|
||
}
|
||
|
||
// Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
|
||
else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
|
||
this._ += "L" + x0 + "," + y0;
|
||
}
|
||
|
||
// Is this arc empty? We’re done.
|
||
if (!r) return;
|
||
|
||
// Does the angle go the wrong way? Flip the direction.
|
||
if (da < 0) da = da % tau + tau;
|
||
|
||
// Is this a complete circle? Draw two arcs to complete the circle.
|
||
if (da > tauEpsilon) {
|
||
this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
|
||
}
|
||
|
||
// Is this arc non-empty? Draw an arc!
|
||
else if (da > epsilon) {
|
||
this._ += "A" + r + "," + r + ",0," + (+(da >= pi)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
|
||
}
|
||
},
|
||
rect: function(x, y, w, h) {
|
||
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z";
|
||
},
|
||
toString: function() {
|
||
return this._;
|
||
}
|
||
};
|
||
|
||
function constant$1(x) {
|
||
return function constant() {
|
||
return x;
|
||
};
|
||
}
|
||
|
||
var abs = Math.abs;
|
||
var atan2 = Math.atan2;
|
||
var cos = Math.cos;
|
||
var max = Math.max;
|
||
var min = Math.min;
|
||
var sin = Math.sin;
|
||
var sqrt = Math.sqrt;
|
||
|
||
var epsilon$1 = 1e-12;
|
||
var pi$1 = Math.PI;
|
||
var halfPi = pi$1 / 2;
|
||
var tau$1 = 2 * pi$1;
|
||
|
||
function acos(x) {
|
||
return x > 1 ? 0 : x < -1 ? pi$1 : Math.acos(x);
|
||
}
|
||
|
||
function asin(x) {
|
||
return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x);
|
||
}
|
||
|
||
function arcInnerRadius(d) {
|
||
return d.innerRadius;
|
||
}
|
||
|
||
function arcOuterRadius(d) {
|
||
return d.outerRadius;
|
||
}
|
||
|
||
function arcStartAngle(d) {
|
||
return d.startAngle;
|
||
}
|
||
|
||
function arcEndAngle(d) {
|
||
return d.endAngle;
|
||
}
|
||
|
||
function arcPadAngle(d) {
|
||
return d && d.padAngle; // Note: optional!
|
||
}
|
||
|
||
function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
|
||
var x10 = x1 - x0, y10 = y1 - y0,
|
||
x32 = x3 - x2, y32 = y3 - y2,
|
||
t = y32 * x10 - x32 * y10;
|
||
if (t * t < epsilon$1) return;
|
||
t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t;
|
||
return [x0 + t * x10, y0 + t * y10];
|
||
}
|
||
|
||
// Compute perpendicular offset line of length rc.
|
||
// http://mathworld.wolfram.com/Circle-LineIntersection.html
|
||
function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
|
||
var x01 = x0 - x1,
|
||
y01 = y0 - y1,
|
||
lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01),
|
||
ox = lo * y01,
|
||
oy = -lo * x01,
|
||
x11 = x0 + ox,
|
||
y11 = y0 + oy,
|
||
x10 = x1 + ox,
|
||
y10 = y1 + oy,
|
||
x00 = (x11 + x10) / 2,
|
||
y00 = (y11 + y10) / 2,
|
||
dx = x10 - x11,
|
||
dy = y10 - y11,
|
||
d2 = dx * dx + dy * dy,
|
||
r = r1 - rc,
|
||
D = x11 * y10 - x10 * y11,
|
||
d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)),
|
||
cx0 = (D * dy - dx * d) / d2,
|
||
cy0 = (-D * dx - dy * d) / d2,
|
||
cx1 = (D * dy + dx * d) / d2,
|
||
cy1 = (-D * dx + dy * d) / d2,
|
||
dx0 = cx0 - x00,
|
||
dy0 = cy0 - y00,
|
||
dx1 = cx1 - x00,
|
||
dy1 = cy1 - y00;
|
||
|
||
// Pick the closer of the two intersection points.
|
||
// TODO Is there a faster way to determine which intersection to use?
|
||
if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
|
||
|
||
return {
|
||
cx: cx0,
|
||
cy: cy0,
|
||
x01: -ox,
|
||
y01: -oy,
|
||
x11: cx0 * (r1 / r - 1),
|
||
y11: cy0 * (r1 / r - 1)
|
||
};
|
||
}
|
||
|
||
function d3arc() {
|
||
var innerRadius = arcInnerRadius,
|
||
outerRadius = arcOuterRadius,
|
||
cornerRadius = constant$1(0),
|
||
padRadius = null,
|
||
startAngle = arcStartAngle,
|
||
endAngle = arcEndAngle,
|
||
padAngle = arcPadAngle,
|
||
context = null;
|
||
|
||
function arc() {
|
||
var buffer,
|
||
r,
|
||
r0 = +innerRadius.apply(this, arguments),
|
||
r1 = +outerRadius.apply(this, arguments),
|
||
a0 = startAngle.apply(this, arguments) - halfPi,
|
||
a1 = endAngle.apply(this, arguments) - halfPi,
|
||
da = abs(a1 - a0),
|
||
cw = a1 > a0;
|
||
|
||
if (!context) context = buffer = path();
|
||
|
||
// Ensure that the outer radius is always larger than the inner radius.
|
||
if (r1 < r0) r = r1, r1 = r0, r0 = r;
|
||
|
||
// Is it a point?
|
||
if (!(r1 > epsilon$1)) context.moveTo(0, 0);
|
||
|
||
// Or is it a circle or annulus?
|
||
else if (da > tau$1 - epsilon$1) {
|
||
context.moveTo(r1 * cos(a0), r1 * sin(a0));
|
||
context.arc(0, 0, r1, a0, a1, !cw);
|
||
if (r0 > epsilon$1) {
|
||
context.moveTo(r0 * cos(a1), r0 * sin(a1));
|
||
context.arc(0, 0, r0, a1, a0, cw);
|
||
}
|
||
}
|
||
|
||
// Or is it a circular or annular sector?
|
||
else {
|
||
var a01 = a0,
|
||
a11 = a1,
|
||
a00 = a0,
|
||
a10 = a1,
|
||
da0 = da,
|
||
da1 = da,
|
||
ap = padAngle.apply(this, arguments) / 2,
|
||
rp = (ap > epsilon$1) && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)),
|
||
rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
|
||
rc0 = rc,
|
||
rc1 = rc,
|
||
t0,
|
||
t1;
|
||
|
||
// Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
|
||
if (rp > epsilon$1) {
|
||
var p0 = asin(rp / r0 * sin(ap)),
|
||
p1 = asin(rp / r1 * sin(ap));
|
||
if ((da0 -= p0 * 2) > epsilon$1) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
|
||
else da0 = 0, a00 = a10 = (a0 + a1) / 2;
|
||
if ((da1 -= p1 * 2) > epsilon$1) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
|
||
else da1 = 0, a01 = a11 = (a0 + a1) / 2;
|
||
}
|
||
|
||
var x01 = r1 * cos(a01),
|
||
y01 = r1 * sin(a01),
|
||
x10 = r0 * cos(a10),
|
||
y10 = r0 * sin(a10);
|
||
|
||
// Apply rounded corners?
|
||
if (rc > epsilon$1) {
|
||
var x11 = r1 * cos(a11),
|
||
y11 = r1 * sin(a11),
|
||
x00 = r0 * cos(a00),
|
||
y00 = r0 * sin(a00),
|
||
oc;
|
||
|
||
// Restrict the corner radius according to the sector angle.
|
||
if (da < pi$1 && (oc = intersect(x01, y01, x00, y00, x11, y11, x10, y10))) {
|
||
var ax = x01 - oc[0],
|
||
ay = y01 - oc[1],
|
||
bx = x11 - oc[0],
|
||
by = y11 - oc[1],
|
||
kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2),
|
||
lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
|
||
rc0 = min(rc, (r0 - lc) / (kc - 1));
|
||
rc1 = min(rc, (r1 - lc) / (kc + 1));
|
||
}
|
||
}
|
||
|
||
// Is the sector collapsed to a line?
|
||
if (!(da1 > epsilon$1)) context.moveTo(x01, y01);
|
||
|
||
// Does the sector’s outer ring have rounded corners?
|
||
else if (rc1 > epsilon$1) {
|
||
t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
|
||
t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
|
||
|
||
context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
|
||
|
||
// Have the corners merged?
|
||
if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw);
|
||
|
||
// Otherwise, draw the two corners and the ring.
|
||
else {
|
||
context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);
|
||
context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
|
||
context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);
|
||
}
|
||
}
|
||
|
||
// Or is the outer ring just a circular arc?
|
||
else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
|
||
|
||
// Is there no inner ring, and it’s a circular sector?
|
||
// Or perhaps it’s an annular sector collapsed due to padding?
|
||
if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10);
|
||
|
||
// Does the sector’s inner ring (or point) have rounded corners?
|
||
else if (rc0 > epsilon$1) {
|
||
t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
|
||
t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
|
||
|
||
context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
|
||
|
||
// Have the corners merged?
|
||
if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw);
|
||
|
||
// Otherwise, draw the two corners and the ring.
|
||
else {
|
||
context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw);
|
||
context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw);
|
||
context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw);
|
||
}
|
||
}
|
||
|
||
// Or is the inner ring just a circular arc?
|
||
else context.arc(0, 0, r0, a10, a00, cw);
|
||
}
|
||
|
||
context.closePath();
|
||
|
||
if (buffer) return context = null, buffer + "" || null;
|
||
}
|
||
|
||
arc.centroid = function() {
|
||
var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
|
||
a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$1 / 2;
|
||
return [cos(a) * r, sin(a) * r];
|
||
};
|
||
|
||
arc.innerRadius = function(_) {
|
||
return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$1(+_), arc) : innerRadius;
|
||
};
|
||
|
||
arc.outerRadius = function(_) {
|
||
return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$1(+_), arc) : outerRadius;
|
||
};
|
||
|
||
arc.cornerRadius = function(_) {
|
||
return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$1(+_), arc) : cornerRadius;
|
||
};
|
||
|
||
arc.padRadius = function(_) {
|
||
return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$1(+_), arc) : padRadius;
|
||
};
|
||
|
||
arc.startAngle = function(_) {
|
||
return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$1(+_), arc) : startAngle;
|
||
};
|
||
|
||
arc.endAngle = function(_) {
|
||
return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$1(+_), arc) : endAngle;
|
||
};
|
||
|
||
arc.padAngle = function(_) {
|
||
return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$1(+_), arc) : padAngle;
|
||
};
|
||
|
||
arc.context = function(_) {
|
||
return arguments.length ? ((context = _ == null ? null : _), arc) : context;
|
||
};
|
||
|
||
return arc;
|
||
}
|
||
|
||
function sign(x) {
|
||
return x < 0 ? -1 : 1;
|
||
}
|
||
|
||
// Calculate the slopes of the tangents (Hermite-type interpolation) based on
|
||
// the following paper: Steffen, M. 1990. A Simple Method for Monotonic
|
||
// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
|
||
// NOV(II), P. 443, 1990.
|
||
function slope3(that, x2, y2) {
|
||
var h0 = that._x1 - that._x0,
|
||
h1 = x2 - that._x1,
|
||
s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
|
||
s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
|
||
p = (s0 * h1 + s1 * h0) / (h0 + h1);
|
||
return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
|
||
}
|
||
|
||
// Calculate a one-sided slope.
|
||
function slope2(that, t) {
|
||
var h = that._x1 - that._x0;
|
||
return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
|
||
}
|
||
|
||
// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
|
||
// "you can express cubic Hermite interpolation in terms of cubic Bézier curves
|
||
// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
|
||
function point(that, t0, t1) {
|
||
var x0 = that._x0,
|
||
y0 = that._y0,
|
||
x1 = that._x1,
|
||
y1 = that._y1,
|
||
dx = (x1 - x0) / 3;
|
||
that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
|
||
}
|
||
|
||
function MonotoneX(context) {
|
||
this._context = context;
|
||
}
|
||
|
||
MonotoneX.prototype = {
|
||
areaStart: function() {
|
||
this._line = 0;
|
||
},
|
||
areaEnd: function() {
|
||
this._line = NaN;
|
||
},
|
||
lineStart: function() {
|
||
this._x0 = this._x1 =
|
||
this._y0 = this._y1 =
|
||
this._t0 = NaN;
|
||
this._point = 0;
|
||
},
|
||
lineEnd: function() {
|
||
switch (this._point) {
|
||
case 2: this._context.lineTo(this._x1, this._y1); break;
|
||
case 3: point(this, this._t0, slope2(this, this._t0)); break;
|
||
}
|
||
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
|
||
this._line = 1 - this._line;
|
||
},
|
||
point: function(x, y) {
|
||
var t1 = NaN;
|
||
|
||
x = +x, y = +y;
|
||
if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
|
||
switch (this._point) {
|
||
case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
|
||
case 1: this._point = 2; break;
|
||
case 2: this._point = 3; point(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
|
||
default: point(this, this._t0, t1 = slope3(this, x, y)); break;
|
||
}
|
||
|
||
this._x0 = this._x1, this._x1 = x;
|
||
this._y0 = this._y1, this._y1 = y;
|
||
this._t0 = t1;
|
||
}
|
||
};
|
||
|
||
function MonotoneY(context) {
|
||
this._context = new ReflectContext(context);
|
||
}
|
||
|
||
(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
|
||
MonotoneX.prototype.point.call(this, y, x);
|
||
};
|
||
|
||
function ReflectContext(context) {
|
||
this._context = context;
|
||
}
|
||
|
||
ReflectContext.prototype = {
|
||
moveTo: function(x, y) { this._context.moveTo(y, x); },
|
||
closePath: function() { this._context.closePath(); },
|
||
lineTo: function(x, y) { this._context.lineTo(y, x); },
|
||
bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
|
||
};
|
||
|
||
function ascending$1(a, b) {
|
||
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
|
||
}
|
||
|
||
function bisector(compare) {
|
||
if (compare.length === 1) compare = ascendingComparator(compare);
|
||
return {
|
||
left: function(a, x, lo, hi) {
|
||
if (lo == null) lo = 0;
|
||
if (hi == null) hi = a.length;
|
||
while (lo < hi) {
|
||
var mid = lo + hi >>> 1;
|
||
if (compare(a[mid], x) < 0) lo = mid + 1;
|
||
else hi = mid;
|
||
}
|
||
return lo;
|
||
},
|
||
right: function(a, x, lo, hi) {
|
||
if (lo == null) lo = 0;
|
||
if (hi == null) hi = a.length;
|
||
while (lo < hi) {
|
||
var mid = lo + hi >>> 1;
|
||
if (compare(a[mid], x) > 0) hi = mid;
|
||
else lo = mid + 1;
|
||
}
|
||
return lo;
|
||
}
|
||
};
|
||
}
|
||
|
||
function ascendingComparator(f) {
|
||
return function(d, x) {
|
||
return ascending$1(f(d), x);
|
||
};
|
||
}
|
||
|
||
var ascendingBisect = bisector(ascending$1);
|
||
var bisectRight = ascendingBisect.right;
|
||
|
||
var e10 = Math.sqrt(50),
|
||
e5 = Math.sqrt(10),
|
||
e2 = Math.sqrt(2);
|
||
|
||
function ticks(start, stop, count) {
|
||
var reverse,
|
||
i = -1,
|
||
n,
|
||
ticks,
|
||
step;
|
||
|
||
stop = +stop, start = +start, count = +count;
|
||
if (start === stop && count > 0) return [start];
|
||
if (reverse = stop < start) n = start, start = stop, stop = n;
|
||
if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
|
||
|
||
if (step > 0) {
|
||
start = Math.ceil(start / step);
|
||
stop = Math.floor(stop / step);
|
||
ticks = new Array(n = Math.ceil(stop - start + 1));
|
||
while (++i < n) ticks[i] = (start + i) * step;
|
||
} else {
|
||
start = Math.floor(start * step);
|
||
stop = Math.ceil(stop * step);
|
||
ticks = new Array(n = Math.ceil(start - stop + 1));
|
||
while (++i < n) ticks[i] = (start - i) / step;
|
||
}
|
||
|
||
if (reverse) ticks.reverse();
|
||
|
||
return ticks;
|
||
}
|
||
|
||
function tickIncrement(start, stop, count) {
|
||
var step = (stop - start) / Math.max(0, count),
|
||
power = Math.floor(Math.log(step) / Math.LN10),
|
||
error = step / Math.pow(10, power);
|
||
return power >= 0
|
||
? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
|
||
: -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
|
||
}
|
||
|
||
function tickStep(start, stop, count) {
|
||
var step0 = Math.abs(stop - start) / Math.max(0, count),
|
||
step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
|
||
error = step0 / step1;
|
||
if (error >= e10) step1 *= 10;
|
||
else if (error >= e5) step1 *= 5;
|
||
else if (error >= e2) step1 *= 2;
|
||
return stop < start ? -step1 : step1;
|
||
}
|
||
|
||
function initRange(domain, range) {
|
||
switch (arguments.length) {
|
||
case 0: break;
|
||
case 1: this.range(domain); break;
|
||
default: this.range(range).domain(domain); break;
|
||
}
|
||
return this;
|
||
}
|
||
|
||
function define(constructor, factory, prototype) {
|
||
constructor.prototype = factory.prototype = prototype;
|
||
prototype.constructor = constructor;
|
||
}
|
||
|
||
function extend(parent, definition) {
|
||
var prototype = Object.create(parent.prototype);
|
||
for (var key in definition) prototype[key] = definition[key];
|
||
return prototype;
|
||
}
|
||
|
||
function Color() {}
|
||
|
||
var darker = 0.7;
|
||
var brighter = 1 / darker;
|
||
|
||
var reI = "\\s*([+-]?\\d+)\\s*",
|
||
reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
|
||
reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
|
||
reHex = /^#([0-9a-f]{3,8})$/,
|
||
reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
|
||
reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
|
||
reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
|
||
reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
|
||
reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
|
||
reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
|
||
|
||
var named = {
|
||
aliceblue: 0xf0f8ff,
|
||
antiquewhite: 0xfaebd7,
|
||
aqua: 0x00ffff,
|
||
aquamarine: 0x7fffd4,
|
||
azure: 0xf0ffff,
|
||
beige: 0xf5f5dc,
|
||
bisque: 0xffe4c4,
|
||
black: 0x000000,
|
||
blanchedalmond: 0xffebcd,
|
||
blue: 0x0000ff,
|
||
blueviolet: 0x8a2be2,
|
||
brown: 0xa52a2a,
|
||
burlywood: 0xdeb887,
|
||
cadetblue: 0x5f9ea0,
|
||
chartreuse: 0x7fff00,
|
||
chocolate: 0xd2691e,
|
||
coral: 0xff7f50,
|
||
cornflowerblue: 0x6495ed,
|
||
cornsilk: 0xfff8dc,
|
||
crimson: 0xdc143c,
|
||
cyan: 0x00ffff,
|
||
darkblue: 0x00008b,
|
||
darkcyan: 0x008b8b,
|
||
darkgoldenrod: 0xb8860b,
|
||
darkgray: 0xa9a9a9,
|
||
darkgreen: 0x006400,
|
||
darkgrey: 0xa9a9a9,
|
||
darkkhaki: 0xbdb76b,
|
||
darkmagenta: 0x8b008b,
|
||
darkolivegreen: 0x556b2f,
|
||
darkorange: 0xff8c00,
|
||
darkorchid: 0x9932cc,
|
||
darkred: 0x8b0000,
|
||
darksalmon: 0xe9967a,
|
||
darkseagreen: 0x8fbc8f,
|
||
darkslateblue: 0x483d8b,
|
||
darkslategray: 0x2f4f4f,
|
||
darkslategrey: 0x2f4f4f,
|
||
darkturquoise: 0x00ced1,
|
||
darkviolet: 0x9400d3,
|
||
deeppink: 0xff1493,
|
||
deepskyblue: 0x00bfff,
|
||
dimgray: 0x696969,
|
||
dimgrey: 0x696969,
|
||
dodgerblue: 0x1e90ff,
|
||
firebrick: 0xb22222,
|
||
floralwhite: 0xfffaf0,
|
||
forestgreen: 0x228b22,
|
||
fuchsia: 0xff00ff,
|
||
gainsboro: 0xdcdcdc,
|
||
ghostwhite: 0xf8f8ff,
|
||
gold: 0xffd700,
|
||
goldenrod: 0xdaa520,
|
||
gray: 0x808080,
|
||
green: 0x008000,
|
||
greenyellow: 0xadff2f,
|
||
grey: 0x808080,
|
||
honeydew: 0xf0fff0,
|
||
hotpink: 0xff69b4,
|
||
indianred: 0xcd5c5c,
|
||
indigo: 0x4b0082,
|
||
ivory: 0xfffff0,
|
||
khaki: 0xf0e68c,
|
||
lavender: 0xe6e6fa,
|
||
lavenderblush: 0xfff0f5,
|
||
lawngreen: 0x7cfc00,
|
||
lemonchiffon: 0xfffacd,
|
||
lightblue: 0xadd8e6,
|
||
lightcoral: 0xf08080,
|
||
lightcyan: 0xe0ffff,
|
||
lightgoldenrodyellow: 0xfafad2,
|
||
lightgray: 0xd3d3d3,
|
||
lightgreen: 0x90ee90,
|
||
lightgrey: 0xd3d3d3,
|
||
lightpink: 0xffb6c1,
|
||
lightsalmon: 0xffa07a,
|
||
lightseagreen: 0x20b2aa,
|
||
lightskyblue: 0x87cefa,
|
||
lightslategray: 0x778899,
|
||
lightslategrey: 0x778899,
|
||
lightsteelblue: 0xb0c4de,
|
||
lightyellow: 0xffffe0,
|
||
lime: 0x00ff00,
|
||
limegreen: 0x32cd32,
|
||
linen: 0xfaf0e6,
|
||
magenta: 0xff00ff,
|
||
maroon: 0x800000,
|
||
mediumaquamarine: 0x66cdaa,
|
||
mediumblue: 0x0000cd,
|
||
mediumorchid: 0xba55d3,
|
||
mediumpurple: 0x9370db,
|
||
mediumseagreen: 0x3cb371,
|
||
mediumslateblue: 0x7b68ee,
|
||
mediumspringgreen: 0x00fa9a,
|
||
mediumturquoise: 0x48d1cc,
|
||
mediumvioletred: 0xc71585,
|
||
midnightblue: 0x191970,
|
||
mintcream: 0xf5fffa,
|
||
mistyrose: 0xffe4e1,
|
||
moccasin: 0xffe4b5,
|
||
navajowhite: 0xffdead,
|
||
navy: 0x000080,
|
||
oldlace: 0xfdf5e6,
|
||
olive: 0x808000,
|
||
olivedrab: 0x6b8e23,
|
||
orange: 0xffa500,
|
||
orangered: 0xff4500,
|
||
orchid: 0xda70d6,
|
||
palegoldenrod: 0xeee8aa,
|
||
palegreen: 0x98fb98,
|
||
paleturquoise: 0xafeeee,
|
||
palevioletred: 0xdb7093,
|
||
papayawhip: 0xffefd5,
|
||
peachpuff: 0xffdab9,
|
||
peru: 0xcd853f,
|
||
pink: 0xffc0cb,
|
||
plum: 0xdda0dd,
|
||
powderblue: 0xb0e0e6,
|
||
purple: 0x800080,
|
||
rebeccapurple: 0x663399,
|
||
red: 0xff0000,
|
||
rosybrown: 0xbc8f8f,
|
||
royalblue: 0x4169e1,
|
||
saddlebrown: 0x8b4513,
|
||
salmon: 0xfa8072,
|
||
sandybrown: 0xf4a460,
|
||
seagreen: 0x2e8b57,
|
||
seashell: 0xfff5ee,
|
||
sienna: 0xa0522d,
|
||
silver: 0xc0c0c0,
|
||
skyblue: 0x87ceeb,
|
||
slateblue: 0x6a5acd,
|
||
slategray: 0x708090,
|
||
slategrey: 0x708090,
|
||
snow: 0xfffafa,
|
||
springgreen: 0x00ff7f,
|
||
steelblue: 0x4682b4,
|
||
tan: 0xd2b48c,
|
||
teal: 0x008080,
|
||
thistle: 0xd8bfd8,
|
||
tomato: 0xff6347,
|
||
turquoise: 0x40e0d0,
|
||
violet: 0xee82ee,
|
||
wheat: 0xf5deb3,
|
||
white: 0xffffff,
|
||
whitesmoke: 0xf5f5f5,
|
||
yellow: 0xffff00,
|
||
yellowgreen: 0x9acd32
|
||
};
|
||
|
||
define(Color, color, {
|
||
copy: function(channels) {
|
||
return Object.assign(new this.constructor, this, channels);
|
||
},
|
||
displayable: function() {
|
||
return this.rgb().displayable();
|
||
},
|
||
hex: color_formatHex, // Deprecated! Use color.formatHex.
|
||
formatHex: color_formatHex,
|
||
formatHsl: color_formatHsl,
|
||
formatRgb: color_formatRgb,
|
||
toString: color_formatRgb
|
||
});
|
||
|
||
function color_formatHex() {
|
||
return this.rgb().formatHex();
|
||
}
|
||
|
||
function color_formatHsl() {
|
||
return hslConvert(this).formatHsl();
|
||
}
|
||
|
||
function color_formatRgb() {
|
||
return this.rgb().formatRgb();
|
||
}
|
||
|
||
function color(format) {
|
||
var m, l;
|
||
format = (format + "").trim().toLowerCase();
|
||
return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
|
||
: l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00
|
||
: l === 8 ? new Rgb(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
|
||
: l === 4 ? new Rgb((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000
|
||
: null) // invalid hex
|
||
: (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
|
||
: (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
|
||
: (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
|
||
: (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
|
||
: (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
|
||
: (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
|
||
: named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
|
||
: format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
|
||
: null;
|
||
}
|
||
|
||
function rgbn(n) {
|
||
return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
|
||
}
|
||
|
||
function rgba(r, g, b, a) {
|
||
if (a <= 0) r = g = b = NaN;
|
||
return new Rgb(r, g, b, a);
|
||
}
|
||
|
||
function rgbConvert(o) {
|
||
if (!(o instanceof Color)) o = color(o);
|
||
if (!o) return new Rgb;
|
||
o = o.rgb();
|
||
return new Rgb(o.r, o.g, o.b, o.opacity);
|
||
}
|
||
|
||
function rgb(r, g, b, opacity) {
|
||
return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
|
||
}
|
||
|
||
function Rgb(r, g, b, opacity) {
|
||
this.r = +r;
|
||
this.g = +g;
|
||
this.b = +b;
|
||
this.opacity = +opacity;
|
||
}
|
||
|
||
define(Rgb, rgb, extend(Color, {
|
||
brighter: function(k) {
|
||
k = k == null ? brighter : Math.pow(brighter, k);
|
||
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
|
||
},
|
||
darker: function(k) {
|
||
k = k == null ? darker : Math.pow(darker, k);
|
||
return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
|
||
},
|
||
rgb: function() {
|
||
return this;
|
||
},
|
||
displayable: function() {
|
||
return (-0.5 <= this.r && this.r < 255.5)
|
||
&& (-0.5 <= this.g && this.g < 255.5)
|
||
&& (-0.5 <= this.b && this.b < 255.5)
|
||
&& (0 <= this.opacity && this.opacity <= 1);
|
||
},
|
||
hex: rgb_formatHex, // Deprecated! Use color.formatHex.
|
||
formatHex: rgb_formatHex,
|
||
formatRgb: rgb_formatRgb,
|
||
toString: rgb_formatRgb
|
||
}));
|
||
|
||
function rgb_formatHex() {
|
||
return "#" + hex(this.r) + hex(this.g) + hex(this.b);
|
||
}
|
||
|
||
function rgb_formatRgb() {
|
||
var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
|
||
return (a === 1 ? "rgb(" : "rgba(")
|
||
+ Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
|
||
+ Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
|
||
+ Math.max(0, Math.min(255, Math.round(this.b) || 0))
|
||
+ (a === 1 ? ")" : ", " + a + ")");
|
||
}
|
||
|
||
function hex(value) {
|
||
value = Math.max(0, Math.min(255, Math.round(value) || 0));
|
||
return (value < 16 ? "0" : "") + value.toString(16);
|
||
}
|
||
|
||
function hsla(h, s, l, a) {
|
||
if (a <= 0) h = s = l = NaN;
|
||
else if (l <= 0 || l >= 1) h = s = NaN;
|
||
else if (s <= 0) h = NaN;
|
||
return new Hsl(h, s, l, a);
|
||
}
|
||
|
||
function hslConvert(o) {
|
||
if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
|
||
if (!(o instanceof Color)) o = color(o);
|
||
if (!o) return new Hsl;
|
||
if (o instanceof Hsl) return o;
|
||
o = o.rgb();
|
||
var r = o.r / 255,
|
||
g = o.g / 255,
|
||
b = o.b / 255,
|
||
min = Math.min(r, g, b),
|
||
max = Math.max(r, g, b),
|
||
h = NaN,
|
||
s = max - min,
|
||
l = (max + min) / 2;
|
||
if (s) {
|
||
if (r === max) h = (g - b) / s + (g < b) * 6;
|
||
else if (g === max) h = (b - r) / s + 2;
|
||
else h = (r - g) / s + 4;
|
||
s /= l < 0.5 ? max + min : 2 - max - min;
|
||
h *= 60;
|
||
} else {
|
||
s = l > 0 && l < 1 ? 0 : h;
|
||
}
|
||
return new Hsl(h, s, l, o.opacity);
|
||
}
|
||
|
||
function hsl(h, s, l, opacity) {
|
||
return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
|
||
}
|
||
|
||
function Hsl(h, s, l, opacity) {
|
||
this.h = +h;
|
||
this.s = +s;
|
||
this.l = +l;
|
||
this.opacity = +opacity;
|
||
}
|
||
|
||
define(Hsl, hsl, extend(Color, {
|
||
brighter: function(k) {
|
||
k = k == null ? brighter : Math.pow(brighter, k);
|
||
return new Hsl(this.h, this.s, this.l * k, this.opacity);
|
||
},
|
||
darker: function(k) {
|
||
k = k == null ? darker : Math.pow(darker, k);
|
||
return new Hsl(this.h, this.s, this.l * k, this.opacity);
|
||
},
|
||
rgb: function() {
|
||
var h = this.h % 360 + (this.h < 0) * 360,
|
||
s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
|
||
l = this.l,
|
||
m2 = l + (l < 0.5 ? l : 1 - l) * s,
|
||
m1 = 2 * l - m2;
|
||
return new Rgb(
|
||
hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
|
||
hsl2rgb(h, m1, m2),
|
||
hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
|
||
this.opacity
|
||
);
|
||
},
|
||
displayable: function() {
|
||
return (0 <= this.s && this.s <= 1 || isNaN(this.s))
|
||
&& (0 <= this.l && this.l <= 1)
|
||
&& (0 <= this.opacity && this.opacity <= 1);
|
||
},
|
||
formatHsl: function() {
|
||
var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
|
||
return (a === 1 ? "hsl(" : "hsla(")
|
||
+ (this.h || 0) + ", "
|
||
+ (this.s || 0) * 100 + "%, "
|
||
+ (this.l || 0) * 100 + "%"
|
||
+ (a === 1 ? ")" : ", " + a + ")");
|
||
}
|
||
}));
|
||
|
||
/* From FvD 13.37, CSS Color Module Level 3 */
|
||
function hsl2rgb(h, m1, m2) {
|
||
return (h < 60 ? m1 + (m2 - m1) * h / 60
|
||
: h < 180 ? m2
|
||
: h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
|
||
: m1) * 255;
|
||
}
|
||
|
||
function constant$2(x) {
|
||
return function() {
|
||
return x;
|
||
};
|
||
}
|
||
|
||
function linear(a, d) {
|
||
return function(t) {
|
||
return a + t * d;
|
||
};
|
||
}
|
||
|
||
function exponential(a, b, y) {
|
||
return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
|
||
return Math.pow(a + t * b, y);
|
||
};
|
||
}
|
||
|
||
function gamma(y) {
|
||
return (y = +y) === 1 ? nogamma : function(a, b) {
|
||
return b - a ? exponential(a, b, y) : constant$2(isNaN(a) ? b : a);
|
||
};
|
||
}
|
||
|
||
function nogamma(a, b) {
|
||
var d = b - a;
|
||
return d ? linear(a, d) : constant$2(isNaN(a) ? b : a);
|
||
}
|
||
|
||
var rgb$1 = (function rgbGamma(y) {
|
||
var color = gamma(y);
|
||
|
||
function rgb$1(start, end) {
|
||
var r = color((start = rgb(start)).r, (end = rgb(end)).r),
|
||
g = color(start.g, end.g),
|
||
b = color(start.b, end.b),
|
||
opacity = nogamma(start.opacity, end.opacity);
|
||
return function(t) {
|
||
start.r = r(t);
|
||
start.g = g(t);
|
||
start.b = b(t);
|
||
start.opacity = opacity(t);
|
||
return start + "";
|
||
};
|
||
}
|
||
|
||
rgb$1.gamma = rgbGamma;
|
||
|
||
return rgb$1;
|
||
})(1);
|
||
|
||
function array(a, b) {
|
||
var nb = b ? b.length : 0,
|
||
na = a ? Math.min(nb, a.length) : 0,
|
||
x = new Array(na),
|
||
c = new Array(nb),
|
||
i;
|
||
|
||
for (i = 0; i < na; ++i) x[i] = interpolate(a[i], b[i]);
|
||
for (; i < nb; ++i) c[i] = b[i];
|
||
|
||
return function(t) {
|
||
for (i = 0; i < na; ++i) c[i] = x[i](t);
|
||
return c;
|
||
};
|
||
}
|
||
|
||
function date(a, b) {
|
||
var d = new Date;
|
||
return a = +a, b -= a, function(t) {
|
||
return d.setTime(a + b * t), d;
|
||
};
|
||
}
|
||
|
||
function interpolateNumber(a, b) {
|
||
return a = +a, b -= a, function(t) {
|
||
return a + b * t;
|
||
};
|
||
}
|
||
|
||
function object(a, b) {
|
||
var i = {},
|
||
c = {},
|
||
k;
|
||
|
||
if (a === null || typeof a !== "object") a = {};
|
||
if (b === null || typeof b !== "object") b = {};
|
||
|
||
for (k in b) {
|
||
if (k in a) {
|
||
i[k] = interpolate(a[k], b[k]);
|
||
} else {
|
||
c[k] = b[k];
|
||
}
|
||
}
|
||
|
||
return function(t) {
|
||
for (k in i) c[k] = i[k](t);
|
||
return c;
|
||
};
|
||
}
|
||
|
||
var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
|
||
reB = new RegExp(reA.source, "g");
|
||
|
||
function zero(b) {
|
||
return function() {
|
||
return b;
|
||
};
|
||
}
|
||
|
||
function one(b) {
|
||
return function(t) {
|
||
return b(t) + "";
|
||
};
|
||
}
|
||
|
||
function string(a, b) {
|
||
var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
|
||
am, // current match in a
|
||
bm, // current match in b
|
||
bs, // string preceding current number in b, if any
|
||
i = -1, // index in s
|
||
s = [], // string constants and placeholders
|
||
q = []; // number interpolators
|
||
|
||
// Coerce inputs to strings.
|
||
a = a + "", b = b + "";
|
||
|
||
// Interpolate pairs of numbers in a & b.
|
||
while ((am = reA.exec(a))
|
||
&& (bm = reB.exec(b))) {
|
||
if ((bs = bm.index) > bi) { // a string precedes the next number in b
|
||
bs = b.slice(bi, bs);
|
||
if (s[i]) s[i] += bs; // coalesce with previous string
|
||
else s[++i] = bs;
|
||
}
|
||
if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
|
||
if (s[i]) s[i] += bm; // coalesce with previous string
|
||
else s[++i] = bm;
|
||
} else { // interpolate non-matching numbers
|
||
s[++i] = null;
|
||
q.push({i: i, x: interpolateNumber(am, bm)});
|
||
}
|
||
bi = reB.lastIndex;
|
||
}
|
||
|
||
// Add remains of b.
|
||
if (bi < b.length) {
|
||
bs = b.slice(bi);
|
||
if (s[i]) s[i] += bs; // coalesce with previous string
|
||
else s[++i] = bs;
|
||
}
|
||
|
||
// Special optimization for only a single match.
|
||
// Otherwise, interpolate each of the numbers and rejoin the string.
|
||
return s.length < 2 ? (q[0]
|
||
? one(q[0].x)
|
||
: zero(b))
|
||
: (b = q.length, function(t) {
|
||
for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
|
||
return s.join("");
|
||
});
|
||
}
|
||
|
||
function interpolate(a, b) {
|
||
var t = typeof b, c;
|
||
return b == null || t === "boolean" ? constant$2(b)
|
||
: (t === "number" ? interpolateNumber
|
||
: t === "string" ? ((c = color(b)) ? (b = c, rgb$1) : string)
|
||
: b instanceof color ? rgb$1
|
||
: b instanceof Date ? date
|
||
: Array.isArray(b) ? array
|
||
: typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object
|
||
: interpolateNumber)(a, b);
|
||
}
|
||
|
||
function interpolateRound(a, b) {
|
||
return a = +a, b -= a, function(t) {
|
||
return Math.round(a + b * t);
|
||
};
|
||
}
|
||
|
||
function constant$3(x) {
|
||
return function() {
|
||
return x;
|
||
};
|
||
}
|
||
|
||
function number(x) {
|
||
return +x;
|
||
}
|
||
|
||
var unit = [0, 1];
|
||
|
||
function identity(x) {
|
||
return x;
|
||
}
|
||
|
||
function normalize(a, b) {
|
||
return (b -= (a = +a))
|
||
? function(x) { return (x - a) / b; }
|
||
: constant$3(isNaN(b) ? NaN : 0.5);
|
||
}
|
||
|
||
function clamper(a, b) {
|
||
var t;
|
||
if (a > b) t = a, a = b, b = t;
|
||
return function(x) { return Math.max(a, Math.min(b, x)); };
|
||
}
|
||
|
||
// normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
|
||
// interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b].
|
||
function bimap(domain, range, interpolate) {
|
||
var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1];
|
||
if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0);
|
||
else d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
|
||
return function(x) { return r0(d0(x)); };
|
||
}
|
||
|
||
function polymap(domain, range, interpolate) {
|
||
var j = Math.min(domain.length, range.length) - 1,
|
||
d = new Array(j),
|
||
r = new Array(j),
|
||
i = -1;
|
||
|
||
// Reverse descending domains.
|
||
if (domain[j] < domain[0]) {
|
||
domain = domain.slice().reverse();
|
||
range = range.slice().reverse();
|
||
}
|
||
|
||
while (++i < j) {
|
||
d[i] = normalize(domain[i], domain[i + 1]);
|
||
r[i] = interpolate(range[i], range[i + 1]);
|
||
}
|
||
|
||
return function(x) {
|
||
var i = bisectRight(domain, x, 1, j) - 1;
|
||
return r[i](d[i](x));
|
||
};
|
||
}
|
||
|
||
function copy(source, target) {
|
||
return target
|
||
.domain(source.domain())
|
||
.range(source.range())
|
||
.interpolate(source.interpolate())
|
||
.clamp(source.clamp())
|
||
.unknown(source.unknown());
|
||
}
|
||
|
||
function transformer() {
|
||
var domain = unit,
|
||
range = unit,
|
||
interpolate$1 = interpolate,
|
||
transform,
|
||
untransform,
|
||
unknown,
|
||
clamp = identity,
|
||
piecewise,
|
||
output,
|
||
input;
|
||
|
||
function rescale() {
|
||
var n = Math.min(domain.length, range.length);
|
||
if (clamp !== identity) clamp = clamper(domain[0], domain[n - 1]);
|
||
piecewise = n > 2 ? polymap : bimap;
|
||
output = input = null;
|
||
return scale;
|
||
}
|
||
|
||
function scale(x) {
|
||
return isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate$1)))(transform(clamp(x)));
|
||
}
|
||
|
||
scale.invert = function(y) {
|
||
return clamp(untransform((input || (input = piecewise(range, domain.map(transform), interpolateNumber)))(y)));
|
||
};
|
||
|
||
scale.domain = function(_) {
|
||
return arguments.length ? (domain = Array.from(_, number), rescale()) : domain.slice();
|
||
};
|
||
|
||
scale.range = function(_) {
|
||
return arguments.length ? (range = Array.from(_), rescale()) : range.slice();
|
||
};
|
||
|
||
scale.rangeRound = function(_) {
|
||
return range = Array.from(_), interpolate$1 = interpolateRound, rescale();
|
||
};
|
||
|
||
scale.clamp = function(_) {
|
||
return arguments.length ? (clamp = _ ? true : identity, rescale()) : clamp !== identity;
|
||
};
|
||
|
||
scale.interpolate = function(_) {
|
||
return arguments.length ? (interpolate$1 = _, rescale()) : interpolate$1;
|
||
};
|
||
|
||
scale.unknown = function(_) {
|
||
return arguments.length ? (unknown = _, scale) : unknown;
|
||
};
|
||
|
||
return function(t, u) {
|
||
transform = t, untransform = u;
|
||
return rescale();
|
||
};
|
||
}
|
||
|
||
function continuous() {
|
||
return transformer()(identity, identity);
|
||
}
|
||
|
||
// Computes the decimal coefficient and exponent of the specified number x with
|
||
// significant digits p, where x is positive and p is in [1, 21] or undefined.
|
||
// For example, formatDecimal(1.23) returns ["123", 0].
|
||
function formatDecimal(x, p) {
|
||
if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
|
||
var i, coefficient = x.slice(0, i);
|
||
|
||
// The string returned by toExponential either has the form \d\.\d+e[-+]\d+
|
||
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
|
||
return [
|
||
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
|
||
+x.slice(i + 1)
|
||
];
|
||
}
|
||
|
||
function exponent(x) {
|
||
return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
|
||
}
|
||
|
||
function formatGroup(grouping, thousands) {
|
||
return function(value, width) {
|
||
var i = value.length,
|
||
t = [],
|
||
j = 0,
|
||
g = grouping[0],
|
||
length = 0;
|
||
|
||
while (i > 0 && g > 0) {
|
||
if (length + g + 1 > width) g = Math.max(1, width - length);
|
||
t.push(value.substring(i -= g, i + g));
|
||
if ((length += g + 1) > width) break;
|
||
g = grouping[j = (j + 1) % grouping.length];
|
||
}
|
||
|
||
return t.reverse().join(thousands);
|
||
};
|
||
}
|
||
|
||
function formatNumerals(numerals) {
|
||
return function(value) {
|
||
return value.replace(/[0-9]/g, function(i) {
|
||
return numerals[+i];
|
||
});
|
||
};
|
||
}
|
||
|
||
// [[fill]align][sign][symbol][0][width][,][.precision][~][type]
|
||
var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
|
||
|
||
function formatSpecifier(specifier) {
|
||
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
|
||
var match;
|
||
return new FormatSpecifier({
|
||
fill: match[1],
|
||
align: match[2],
|
||
sign: match[3],
|
||
symbol: match[4],
|
||
zero: match[5],
|
||
width: match[6],
|
||
comma: match[7],
|
||
precision: match[8] && match[8].slice(1),
|
||
trim: match[9],
|
||
type: match[10]
|
||
});
|
||
}
|
||
|
||
formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
|
||
|
||
function FormatSpecifier(specifier) {
|
||
this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
|
||
this.align = specifier.align === undefined ? ">" : specifier.align + "";
|
||
this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
|
||
this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
|
||
this.zero = !!specifier.zero;
|
||
this.width = specifier.width === undefined ? undefined : +specifier.width;
|
||
this.comma = !!specifier.comma;
|
||
this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
|
||
this.trim = !!specifier.trim;
|
||
this.type = specifier.type === undefined ? "" : specifier.type + "";
|
||
}
|
||
|
||
FormatSpecifier.prototype.toString = function() {
|
||
return this.fill
|
||
+ this.align
|
||
+ this.sign
|
||
+ this.symbol
|
||
+ (this.zero ? "0" : "")
|
||
+ (this.width === undefined ? "" : Math.max(1, this.width | 0))
|
||
+ (this.comma ? "," : "")
|
||
+ (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0))
|
||
+ (this.trim ? "~" : "")
|
||
+ this.type;
|
||
};
|
||
|
||
// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
|
||
function formatTrim(s) {
|
||
out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
|
||
switch (s[i]) {
|
||
case ".": i0 = i1 = i; break;
|
||
case "0": if (i0 === 0) i0 = i; i1 = i; break;
|
||
default: if (i0 > 0) { if (!+s[i]) break out; i0 = 0; } break;
|
||
}
|
||
}
|
||
return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
|
||
}
|
||
|
||
var prefixExponent;
|
||
|
||
function formatPrefixAuto(x, p) {
|
||
var d = formatDecimal(x, p);
|
||
if (!d) return x + "";
|
||
var coefficient = d[0],
|
||
exponent = d[1],
|
||
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
|
||
n = coefficient.length;
|
||
return i === n ? coefficient
|
||
: i > n ? coefficient + new Array(i - n + 1).join("0")
|
||
: i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
|
||
: "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
|
||
}
|
||
|
||
function formatRounded(x, p) {
|
||
var d = formatDecimal(x, p);
|
||
if (!d) return x + "";
|
||
var coefficient = d[0],
|
||
exponent = d[1];
|
||
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
|
||
: coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
|
||
: coefficient + new Array(exponent - coefficient.length + 2).join("0");
|
||
}
|
||
|
||
var formatTypes = {
|
||
"%": function(x, p) { return (x * 100).toFixed(p); },
|
||
"b": function(x) { return Math.round(x).toString(2); },
|
||
"c": function(x) { return x + ""; },
|
||
"d": function(x) { return Math.round(x).toString(10); },
|
||
"e": function(x, p) { return x.toExponential(p); },
|
||
"f": function(x, p) { return x.toFixed(p); },
|
||
"g": function(x, p) { return x.toPrecision(p); },
|
||
"o": function(x) { return Math.round(x).toString(8); },
|
||
"p": function(x, p) { return formatRounded(x * 100, p); },
|
||
"r": formatRounded,
|
||
"s": formatPrefixAuto,
|
||
"X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
|
||
"x": function(x) { return Math.round(x).toString(16); }
|
||
};
|
||
|
||
function identity$1(x) {
|
||
return x;
|
||
}
|
||
|
||
var map = Array.prototype.map,
|
||
prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
|
||
|
||
function formatLocale(locale) {
|
||
var group = locale.grouping === undefined || locale.thousands === undefined ? identity$1 : formatGroup(map.call(locale.grouping, Number), locale.thousands + ""),
|
||
currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
|
||
currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
|
||
decimal = locale.decimal === undefined ? "." : locale.decimal + "",
|
||
numerals = locale.numerals === undefined ? identity$1 : formatNumerals(map.call(locale.numerals, String)),
|
||
percent = locale.percent === undefined ? "%" : locale.percent + "",
|
||
minus = locale.minus === undefined ? "-" : locale.minus + "",
|
||
nan = locale.nan === undefined ? "NaN" : locale.nan + "";
|
||
|
||
function newFormat(specifier) {
|
||
specifier = formatSpecifier(specifier);
|
||
|
||
var fill = specifier.fill,
|
||
align = specifier.align,
|
||
sign = specifier.sign,
|
||
symbol = specifier.symbol,
|
||
zero = specifier.zero,
|
||
width = specifier.width,
|
||
comma = specifier.comma,
|
||
precision = specifier.precision,
|
||
trim = specifier.trim,
|
||
type = specifier.type;
|
||
|
||
// The "n" type is an alias for ",g".
|
||
if (type === "n") comma = true, type = "g";
|
||
|
||
// The "" type, and any invalid type, is an alias for ".12~g".
|
||
else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g";
|
||
|
||
// If zero fill is specified, padding goes after sign and before digits.
|
||
if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
|
||
|
||
// Compute the prefix and suffix.
|
||
// For SI-prefix, the suffix is lazily computed.
|
||
var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
|
||
suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "";
|
||
|
||
// What format function should we use?
|
||
// Is this an integer type?
|
||
// Can this type generate exponential notation?
|
||
var formatType = formatTypes[type],
|
||
maybeSuffix = /[defgprs%]/.test(type);
|
||
|
||
// Set the default precision if not specified,
|
||
// or clamp the specified precision to the supported range.
|
||
// For significant precision, it must be in [1, 21].
|
||
// For fixed precision, it must be in [0, 20].
|
||
precision = precision === undefined ? 6
|
||
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
|
||
: Math.max(0, Math.min(20, precision));
|
||
|
||
function format(value) {
|
||
var valuePrefix = prefix,
|
||
valueSuffix = suffix,
|
||
i, n, c;
|
||
|
||
if (type === "c") {
|
||
valueSuffix = formatType(value) + valueSuffix;
|
||
value = "";
|
||
} else {
|
||
value = +value;
|
||
|
||
// Perform the initial formatting.
|
||
var valueNegative = value < 0;
|
||
value = isNaN(value) ? nan : formatType(Math.abs(value), precision);
|
||
|
||
// Trim insignificant zeros.
|
||
if (trim) value = formatTrim(value);
|
||
|
||
// If a negative value rounds to zero during formatting, treat as positive.
|
||
if (valueNegative && +value === 0) valueNegative = false;
|
||
|
||
// Compute the prefix and suffix.
|
||
valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
|
||
|
||
valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
|
||
|
||
// Break the formatted value into the integer “value” part that can be
|
||
// grouped, and fractional or exponential “suffix” part that is not.
|
||
if (maybeSuffix) {
|
||
i = -1, n = value.length;
|
||
while (++i < n) {
|
||
if (c = value.charCodeAt(i), 48 > c || c > 57) {
|
||
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
|
||
value = value.slice(0, i);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// If the fill character is not "0", grouping is applied before padding.
|
||
if (comma && !zero) value = group(value, Infinity);
|
||
|
||
// Compute the padding.
|
||
var length = valuePrefix.length + value.length + valueSuffix.length,
|
||
padding = length < width ? new Array(width - length + 1).join(fill) : "";
|
||
|
||
// If the fill character is "0", grouping is applied after padding.
|
||
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
|
||
|
||
// Reconstruct the final output based on the desired alignment.
|
||
switch (align) {
|
||
case "<": value = valuePrefix + value + valueSuffix + padding; break;
|
||
case "=": value = valuePrefix + padding + value + valueSuffix; break;
|
||
case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
|
||
default: value = padding + valuePrefix + value + valueSuffix; break;
|
||
}
|
||
|
||
return numerals(value);
|
||
}
|
||
|
||
format.toString = function() {
|
||
return specifier + "";
|
||
};
|
||
|
||
return format;
|
||
}
|
||
|
||
function formatPrefix(specifier, value) {
|
||
var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
|
||
e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
|
||
k = Math.pow(10, -e),
|
||
prefix = prefixes[8 + e / 3];
|
||
return function(value) {
|
||
return f(k * value) + prefix;
|
||
};
|
||
}
|
||
|
||
return {
|
||
format: newFormat,
|
||
formatPrefix: formatPrefix
|
||
};
|
||
}
|
||
|
||
var locale;
|
||
var format;
|
||
var formatPrefix;
|
||
|
||
defaultLocale({
|
||
decimal: ".",
|
||
thousands: ",",
|
||
grouping: [3],
|
||
currency: ["$", ""],
|
||
minus: "-"
|
||
});
|
||
|
||
function defaultLocale(definition) {
|
||
locale = formatLocale(definition);
|
||
format = locale.format;
|
||
formatPrefix = locale.formatPrefix;
|
||
return locale;
|
||
}
|
||
|
||
function precisionFixed(step) {
|
||
return Math.max(0, -exponent(Math.abs(step)));
|
||
}
|
||
|
||
function precisionPrefix(step, value) {
|
||
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
|
||
}
|
||
|
||
function precisionRound(step, max) {
|
||
step = Math.abs(step), max = Math.abs(max) - step;
|
||
return Math.max(0, exponent(max) - exponent(step)) + 1;
|
||
}
|
||
|
||
function tickFormat(start, stop, count, specifier) {
|
||
var step = tickStep(start, stop, count),
|
||
precision;
|
||
specifier = formatSpecifier(specifier == null ? ",f" : specifier);
|
||
switch (specifier.type) {
|
||
case "s": {
|
||
var value = Math.max(Math.abs(start), Math.abs(stop));
|
||
if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
|
||
return formatPrefix(specifier, value);
|
||
}
|
||
case "":
|
||
case "e":
|
||
case "g":
|
||
case "p":
|
||
case "r": {
|
||
if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
|
||
break;
|
||
}
|
||
case "f":
|
||
case "%": {
|
||
if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
|
||
break;
|
||
}
|
||
}
|
||
return format(specifier);
|
||
}
|
||
|
||
function linearish(scale) {
|
||
var domain = scale.domain;
|
||
|
||
scale.ticks = function(count) {
|
||
var d = domain();
|
||
return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
|
||
};
|
||
|
||
scale.tickFormat = function(count, specifier) {
|
||
var d = domain();
|
||
return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
|
||
};
|
||
|
||
scale.nice = function(count) {
|
||
if (count == null) count = 10;
|
||
|
||
var d = domain(),
|
||
i0 = 0,
|
||
i1 = d.length - 1,
|
||
start = d[i0],
|
||
stop = d[i1],
|
||
step;
|
||
|
||
if (stop < start) {
|
||
step = start, start = stop, stop = step;
|
||
step = i0, i0 = i1, i1 = step;
|
||
}
|
||
|
||
step = tickIncrement(start, stop, count);
|
||
|
||
if (step > 0) {
|
||
start = Math.floor(start / step) * step;
|
||
stop = Math.ceil(stop / step) * step;
|
||
step = tickIncrement(start, stop, count);
|
||
} else if (step < 0) {
|
||
start = Math.ceil(start * step) / step;
|
||
stop = Math.floor(stop * step) / step;
|
||
step = tickIncrement(start, stop, count);
|
||
}
|
||
|
||
if (step > 0) {
|
||
d[i0] = Math.floor(start / step) * step;
|
||
d[i1] = Math.ceil(stop / step) * step;
|
||
domain(d);
|
||
} else if (step < 0) {
|
||
d[i0] = Math.ceil(start * step) / step;
|
||
d[i1] = Math.floor(stop * step) / step;
|
||
domain(d);
|
||
}
|
||
|
||
return scale;
|
||
};
|
||
|
||
return scale;
|
||
}
|
||
|
||
function linear$1() {
|
||
var scale = continuous();
|
||
|
||
scale.copy = function() {
|
||
return copy(scale, linear$1());
|
||
};
|
||
|
||
initRange.apply(scale, arguments);
|
||
|
||
return linearish(scale);
|
||
}
|
||
|
||
function transformPow(exponent) {
|
||
return function(x) {
|
||
return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
|
||
};
|
||
}
|
||
|
||
function transformSqrt(x) {
|
||
return x < 0 ? -Math.sqrt(-x) : Math.sqrt(x);
|
||
}
|
||
|
||
function transformSquare(x) {
|
||
return x < 0 ? -x * x : x * x;
|
||
}
|
||
|
||
function powish(transform) {
|
||
var scale = transform(identity, identity),
|
||
exponent = 1;
|
||
|
||
function rescale() {
|
||
return exponent === 1 ? transform(identity, identity)
|
||
: exponent === 0.5 ? transform(transformSqrt, transformSquare)
|
||
: transform(transformPow(exponent), transformPow(1 / exponent));
|
||
}
|
||
|
||
scale.exponent = function(_) {
|
||
return arguments.length ? (exponent = +_, rescale()) : exponent;
|
||
};
|
||
|
||
return linearish(scale);
|
||
}
|
||
|
||
function pow() {
|
||
var scale = powish(transformer());
|
||
|
||
scale.copy = function() {
|
||
return copy(scale, pow()).exponent(scale.exponent());
|
||
};
|
||
|
||
initRange.apply(scale, arguments);
|
||
|
||
return scale;
|
||
}
|
||
|
||
function sqrt$1() {
|
||
return pow.apply(null, arguments).exponent(0.5);
|
||
}
|
||
|
||
/*!
|
||
* bytes
|
||
* Copyright(c) 2012-2014 TJ Holowaychuk
|
||
* Copyright(c) 2015 Jed Watson
|
||
* MIT Licensed
|
||
*/
|
||
var format_1 = format$1;
|
||
|
||
/**
|
||
* Module variables.
|
||
* @private
|
||
*/
|
||
|
||
var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g;
|
||
|
||
var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/;
|
||
|
||
var map$1 = {
|
||
b: 1,
|
||
kb: 1 << 10,
|
||
mb: 1 << 20,
|
||
gb: 1 << 30,
|
||
tb: Math.pow(1024, 4),
|
||
pb: Math.pow(1024, 5),
|
||
};
|
||
|
||
/**
|
||
* Format the given value in bytes into a string.
|
||
*
|
||
* If the value is negative, it is kept as such. If it is a float,
|
||
* it is rounded.
|
||
*
|
||
* @param {number} value
|
||
* @param {object} [options]
|
||
* @param {number} [options.decimalPlaces=2]
|
||
* @param {number} [options.fixedDecimals=false]
|
||
* @param {string} [options.thousandsSeparator=]
|
||
* @param {string} [options.unit=]
|
||
* @param {string} [options.unitSeparator=]
|
||
*
|
||
* @returns {string|null}
|
||
* @public
|
||
*/
|
||
|
||
function format$1(value, options) {
|
||
if (!Number.isFinite(value)) {
|
||
return null;
|
||
}
|
||
|
||
var mag = Math.abs(value);
|
||
var thousandsSeparator = (options && options.thousandsSeparator) || '';
|
||
var unitSeparator = (options && options.unitSeparator) || '';
|
||
var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2;
|
||
var fixedDecimals = Boolean(options && options.fixedDecimals);
|
||
var unit = (options && options.unit) || '';
|
||
|
||
if (!unit || !map$1[unit.toLowerCase()]) {
|
||
if (mag >= map$1.pb) {
|
||
unit = 'PB';
|
||
} else if (mag >= map$1.tb) {
|
||
unit = 'TB';
|
||
} else if (mag >= map$1.gb) {
|
||
unit = 'GB';
|
||
} else if (mag >= map$1.mb) {
|
||
unit = 'MB';
|
||
} else if (mag >= map$1.kb) {
|
||
unit = 'KB';
|
||
} else {
|
||
unit = 'B';
|
||
}
|
||
}
|
||
|
||
var val = value / map$1[unit.toLowerCase()];
|
||
var str = val.toFixed(decimalPlaces);
|
||
|
||
if (!fixedDecimals) {
|
||
str = str.replace(formatDecimalsRegExp, '$1');
|
||
}
|
||
|
||
if (thousandsSeparator) {
|
||
str = str.replace(formatThousandsRegExp, thousandsSeparator);
|
||
}
|
||
|
||
return str + unitSeparator + unit;
|
||
}
|
||
|
||
function getAncestors(node) {
|
||
const parents = [];
|
||
while (node != null) {
|
||
parents.push(node);
|
||
node = node.parent;
|
||
}
|
||
return parents;
|
||
}
|
||
|
||
function color$1(node) {
|
||
if (node.children && node.children.length) {
|
||
const parents = getAncestors(node);
|
||
const hasNodeModules = !!parents.find(n => {
|
||
return n.data.name === "node_modules";
|
||
});
|
||
return hasNodeModules ? "#599e59" : "#487ea4";
|
||
} else {
|
||
return "#db7100";
|
||
}
|
||
}
|
||
|
||
const WIDTH = window.chartParameters.width || 700;
|
||
const HEIGHT = window.chartParameters.height || 700;
|
||
const RADIUS = Math.min(WIDTH, HEIGHT) / 2 - 10;
|
||
|
||
const x = linear$1().range([0, 2 * Math.PI]);
|
||
const y = sqrt$1().range([0, RADIUS]);
|
||
|
||
const mainContainer = document.querySelector("#main");
|
||
|
||
for (const { id, root: data } of window.nodesData) {
|
||
const wrapper = document.createElement("div");
|
||
wrapper.innerHTML = `
|
||
<div class="chart">
|
||
<h3>${id}</h3>
|
||
<div class="details" style="display: none;">
|
||
<div class="details-name" ></div>
|
||
<div class="details-percentage" ></div>
|
||
of bundle size
|
||
<div class="details-size" ></div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
const chartNode = wrapper.querySelector(".chart");
|
||
mainContainer.appendChild(chartNode);
|
||
|
||
const g = select(chartNode)
|
||
.append("svg")
|
||
.attr("viewBox", [0, 0, WIDTH, HEIGHT])
|
||
.append("g")
|
||
.attr("transform", `translate(${WIDTH / 2},${HEIGHT / 2})`);
|
||
|
||
const root = hierarchy(data)
|
||
.sum(d => {
|
||
if (d.children && d.children.length) {
|
||
return 0;
|
||
} else {
|
||
return d.size;
|
||
}
|
||
})
|
||
.sort();
|
||
|
||
const arc = d3arc()
|
||
.startAngle(d => Math.max(0, Math.min(2 * Math.PI, x(d.x0))))
|
||
.endAngle(d => Math.max(0, Math.min(2 * Math.PI, x(d.x1))))
|
||
.innerRadius(d => y(d.y0))
|
||
.outerRadius(d => y(d.y1));
|
||
|
||
const partition = d3partition();
|
||
|
||
partition(root);
|
||
|
||
g.selectAll("path")
|
||
.data(partition(root).descendants())
|
||
.enter()
|
||
.append("path")
|
||
|
||
.attr("d", arc)
|
||
.attr("fill-rule", "evenodd")
|
||
.style("stroke", "#fff")
|
||
.style("fill", d => color$1(d))
|
||
.on("mouseover", d => {
|
||
const percentageNum = (100 * d.value) / totalSize;
|
||
const percentage = percentageNum.toFixed(2);
|
||
const percentageString = percentage + "%";
|
||
|
||
select(chartNode)
|
||
.select(".details-name")
|
||
.text(d.data.name);
|
||
|
||
select(chartNode)
|
||
.select(".details-percentage")
|
||
.text(percentageString);
|
||
|
||
select(chartNode)
|
||
.select(".details-size")
|
||
.text(format_1(d.value));
|
||
|
||
select(chartNode)
|
||
.select(".details")
|
||
.style("display", "block");
|
||
|
||
const sequenceArray = getAncestors(d);
|
||
//updateBreadcrumbs(sequenceArray, percentageString);
|
||
|
||
// Fade all the segments.
|
||
g.selectAll("path").style("opacity", 0.3);
|
||
|
||
// Then highlight only those that are an ancestor of the current segment.
|
||
g.selectAll("path")
|
||
.filter(node => sequenceArray.indexOf(node) >= 0)
|
||
.style("opacity", 1);
|
||
});
|
||
|
||
const totalSize = root.value;
|
||
|
||
select(chartNode).on("mouseleave", () => {
|
||
g.selectAll("path").style("opacity", 1);
|
||
|
||
select(".details").style("display", "none");
|
||
});
|
||
}
|
||
|
||
}());
|
||
</script>
|
||
</body>
|
||
</html>
|