enclosing diagram (circle pack), green circles represent items/institutions and the containing grey circles their clusters. Data is randomly generated and has no meaning, just for testing appearance of varying quantities
Last active
January 29, 2018 13:01
-
-
Save eesur/6d47408e1e7378fbb811836f6fe230c1 to your computer and use it in GitHub Desktop.
d3js | enclosing diagram | circle pack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit | |
height: 500 | |
border: no |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See https://help.github.com/ignore-files/ for more about ignoring files. | |
# dependencies | |
/node_modules | |
# testing | |
/coverage | |
# production | |
/build | |
# misc | |
.DS_Store | |
.env.local | |
.env.development.local | |
.env.test.local | |
.env.production.local | |
npm-debug.log* | |
yarn-debug.log* | |
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,Consolas,monaco,monospace;width:960px;margin:0 auto;background:#2f292b;font-size:14px;color:#a5a6a9;letter-spacing:3px}header{left:15px;width:250px}circle.item{fill:#2f292b;cursor:pointer;transition:fill .2s ease}circle.item:hover{fill:#e6c700}circle.cluster{fill:#f45844}circle.root{display:none}span{color:#f45844;font-weight:700}input[type=range]{-webkit-appearance:none;width:100%;height:2px;background:#a5a6a9;background-position:center;background-repeat:no-repeat;margin:auto}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:30px;height:30px;border-radius:100%;background:#a5a6a9;position:relative;border:3px solid #a5a6a9;z-index:2;cursor:pointer}input:focus{outline:0}.d3-tip{font-weight:400;line-height:1.5;padding:12px;background:rgba(0,0,0,.8);color:#f5f5f5;border-radius:2px;pointer-events:none}.d3-tip:after{box-sizing:border-box;display:inline;font-size:10px;width:100%;line-height:1;color:#231f20;position:absolute;pointer-events:none}.d3-tip.n:after{content:"\25BC";margin:-1px 0 0 0;top:100%;left:0;text-align:center} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!function(n){function t(a){if(e[a])return e[a].exports;var g=e[a]={i:a,l:!1,exports:{}};return n[a].call(g.exports,g,g.exports,t),g.l=!0,g.exports}var e={};t.m=n,t.c=e,t.i=function(n){return n},t.d=function(n,e,a){t.o(n,e)||Object.defineProperty(n,e,{configurable:!1,enumerable:!0,get:a})},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},t.p="",t(t.s=1)}([function(module,exports,__webpack_require__){"use strict";eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\nvar d3 = window.d3;\n\nexports.default = function () {\n var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 4;\n\n // list of clusters\n var clusters = createClusters(amount);\n // have a root node to start with\n var data = [{ name: 'root', parent: null }];\n\n clusters.forEach(function (d) {\n var r = Math.floor(d3.randomUniform(2, 40)());\n var children = createChildren(r, d);\n // pass in the parent items\n data.push({ name: d, parent: 'root' });\n // pass in some children\n data = data.concat(children);\n });\n\n return data;\n};\n\n// create clusters\n\n\nfunction createClusters() {\n var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 4;\n var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'cluster_';\n\n var list = [].concat(_toConsumableArray(Array(amount).keys())).map(function (d) {\n return name + d;\n });\n return list;\n}\n\n// add some dummy data to each cluster\nfunction createChildren() {\n var amount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10;\n var cluster = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'c_1';\n\n var o = [].concat(_toConsumableArray(Array(amount).keys())).map(function (d, i) {\n return {\n name: cluster + ' | item_' + i,\n parent: cluster\n };\n });\n return o;\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy9kdW1teURhdGEuanM/NWI2MSJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBkMyA9IHdpbmRvdy5kM1xuXG5leHBvcnQgZGVmYXVsdCAoYW1vdW50ID0gNCkgPT4ge1xuICAvLyBsaXN0IG9mIGNsdXN0ZXJzXG4gIGNvbnN0IGNsdXN0ZXJzID0gY3JlYXRlQ2x1c3RlcnMoYW1vdW50KVxuICAvLyBoYXZlIGEgcm9vdCBub2RlIHRvIHN0YXJ0IHdpdGhcbiAgbGV0IGRhdGEgPSBbXG4gICAge25hbWU6ICdyb290JywgcGFyZW50OiBudWxsfVxuICBdXG5cbiAgY2x1c3RlcnMuZm9yRWFjaChkID0+IHtcbiAgICBsZXQgciA9IE1hdGguZmxvb3IoZDMucmFuZG9tVW5pZm9ybSgyLCA0MCkoKSlcbiAgICBsZXQgY2hpbGRyZW4gPSBjcmVhdGVDaGlsZHJlbihyLCBkKVxuICAgIC8vIHBhc3MgaW4gdGhlIHBhcmVudCBpdGVtc1xuICAgIGRhdGEucHVzaCh7bmFtZTogZCwgcGFyZW50OiAncm9vdCd9KVxuICAgIC8vIHBhc3MgaW4gc29tZSBjaGlsZHJlblxuICAgIGRhdGEgPSBkYXRhLmNvbmNhdChjaGlsZHJlbilcbiAgfSlcblxuICByZXR1cm4gZGF0YVxufVxuXG4vLyBjcmVhdGUgY2x1c3RlcnNcbmZ1bmN0aW9uIGNyZWF0ZUNsdXN0ZXJzIChhbW91bnQgPSA0LCBuYW1lID0gJ2NsdXN0ZXJfJykge1xuICBjb25zdCBsaXN0ID0gWy4uLkFycmF5KGFtb3VudCkua2V5cygpXS5tYXAoZCA9PiBuYW1lICsgZClcbiAgcmV0dXJuIGxpc3Rcbn1cblxuLy8gYWRkIHNvbWUgZHVtbXkgIGRhdGEgdG8gZWFjaCBjbHVzdGVyXG5mdW5jdGlvbiBjcmVhdGVDaGlsZHJlbiAoYW1vdW50ID0gMTAsIGNsdXN0ZXIgPSAnY18xJykge1xuICBjb25zdCBvID0gWy4uLkFycmF5KGFtb3VudCkua2V5cygpXS5tYXAoKGQsIGkpID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogYCR7Y2x1c3Rlcn0gfCBpdGVtXyR7aX1gLFxuICAgICAgcGFyZW50OiBjbHVzdGVyXG4gICAgfVxuICB9KVxuICByZXR1cm4gb1xufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIGR1bW15RGF0YS5qcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFJQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///0\n")},function(module,exports,__webpack_require__){"use strict";eval("\n\nvar _dummyData = __webpack_require__(0);\n\nvar _dummyData2 = _interopRequireDefault(_dummyData);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar d3 = window.d3;\n\nfunction enclosureDiagram(bind, flatData, config) {\n config = {\n width: 960,\n height: 800,\n radius: 5,\n padding: 5\n };\n\n var _config = config,\n width = _config.width,\n height = _config.height;\n\n var selection = d3.select(bind);\n\n // initialize tooltip after a destroy\n d3.selectAll('.d3-tip').remove();\n var tip = d3.tip().attr('class', 'd3-tip').html(function (d) {\n return d.data.id;\n }).offset([-10, 1]);\n // invoke the tip in the context of your visualization\n selection.call(tip);\n\n // convert the flat data into a hierarchy\n var data = d3.stratify().id(function (d) {\n return d.name;\n }).parentId(function (d) {\n return d.parent;\n })(flatData);\n\n var packLayout = d3.pack().size([width, height]).radius(function () {\n return config.radius;\n }).padding(config.padding);\n\n var rootNode = d3.hierarchy(data);\n\n // run .sum() on the hierarchy; return 1 for size of leaf nodes\n rootNode.sum(function () {\n return 1;\n });\n\n packLayout(rootNode);\n\n renderCircles(rootNode.descendants());\n\n function renderCircles(nodes) {\n var circles = selection.selectAll('circle').data(nodes, function (d) {\n return d.data.id;\n });\n circles.exit().remove();\n circles.enter().append('circle').attr('class', function (d) {\n if (d.depth === 0) {\n return 'root';\n } else if (d.depth === 1) {\n return 'cluster';\n } else {\n return 'item';\n }\n }).merge(circles).attr('cx', function (d) {\n return d.x;\n }).attr('cy', function (d) {\n return d.y;\n }).attr('r', function (d) {\n return d.r;\n })\n // .on('mouseover', tip.show)\n .on('mouseover', function (d) {\n // use a timeout/delay to stop crazy flickering\n var context = this;\n var args = [].slice.call(arguments);\n var timeout = null;\n args.push(this);\n clearTimeout(timeout);\n timeout = setTimeout(function () {\n tip.show.apply(context, args);\n }, 100);\n }).on('mouseout', tip.hide);\n }\n}\n\n// run the visualisation\nvar chart = enclosureDiagram;\nchart('g#vis', (0, _dummyData2.default)(27));\n\n// when the input range changes re-render (set in index.html)\nd3.select('#cluster-amount').on('input', function () {\n d3.select('#slider-amount').text(+this.value);\n chart('g#vis', (0, _dummyData2.default)(+this.value));\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy9zY3JpcHQuanM/OWE5NSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZHVtbXlEYXRhIGZyb20gJy4vZHVtbXlEYXRhJ1xuY29uc3QgZDMgPSB3aW5kb3cuZDNcblxuZnVuY3Rpb24gZW5jbG9zdXJlRGlhZ3JhbSAoYmluZCwgZmxhdERhdGEsIGNvbmZpZykge1xuICBjb25maWcgPSB7XG4gICAgd2lkdGg6IDk2MCxcbiAgICBoZWlnaHQ6IDgwMCxcbiAgICByYWRpdXM6IDUsXG4gICAgcGFkZGluZzogNVxuICB9XG5cbiAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSBjb25maWdcbiAgY29uc3Qgc2VsZWN0aW9uID0gZDMuc2VsZWN0KGJpbmQpXG5cbiAgLy8gaW5pdGlhbGl6ZSB0b29sdGlwIGFmdGVyIGEgZGVzdHJveVxuICBkMy5zZWxlY3RBbGwoJy5kMy10aXAnKS5yZW1vdmUoKVxuICBjb25zdCB0aXAgPSBkMy50aXAoKS5hdHRyKCdjbGFzcycsICdkMy10aXAnKS5odG1sKGQgPT4gZC5kYXRhLmlkKS5vZmZzZXQoWy0xMCwgMV0pXG4gIC8vIGludm9rZSB0aGUgdGlwIGluIHRoZSBjb250ZXh0IG9mIHlvdXIgdmlzdWFsaXphdGlvblxuICBzZWxlY3Rpb24uY2FsbCh0aXApXG5cbiAgLy8gY29udmVydCB0aGUgZmxhdCBkYXRhIGludG8gYSBoaWVyYXJjaHlcbiAgY29uc3QgZGF0YSA9IGQzLnN0cmF0aWZ5KClcbiAgICAuaWQoZCA9PiBkLm5hbWUpXG4gICAgLnBhcmVudElkKGQgPT4gZC5wYXJlbnQpKGZsYXREYXRhKVxuXG4gIGNvbnN0IHBhY2tMYXlvdXQgPSBkMy5wYWNrKClcbiAgICAuc2l6ZShbd2lkdGgsIGhlaWdodF0pXG4gICAgLnJhZGl1cygoKSA9PiBjb25maWcucmFkaXVzKVxuICAgIC5wYWRkaW5nKGNvbmZpZy5wYWRkaW5nKVxuXG4gIGNvbnN0IHJvb3ROb2RlID0gZDMuaGllcmFyY2h5KGRhdGEpXG5cbiAgLy8gcnVuIC5zdW0oKSBvbiB0aGUgaGllcmFyY2h5OyByZXR1cm4gMSBmb3Igc2l6ZSBvZiBsZWFmIG5vZGVzXG4gIHJvb3ROb2RlLnN1bSgoKSA9PiAxKVxuXG4gIHBhY2tMYXlvdXQocm9vdE5vZGUpXG5cbiAgcmVuZGVyQ2lyY2xlcyhyb290Tm9kZS5kZXNjZW5kYW50cygpKVxuXG4gIGZ1bmN0aW9uIHJlbmRlckNpcmNsZXMgKG5vZGVzKSB7XG4gICAgY29uc3QgY2lyY2xlcyA9IHNlbGVjdGlvblxuICAgICAgLnNlbGVjdEFsbCgnY2lyY2xlJylcbiAgICAgIC5kYXRhKG5vZGVzLCBkID0+IGQuZGF0YS5pZClcbiAgICBjaXJjbGVzLmV4aXQoKS5yZW1vdmUoKVxuICAgIGNpcmNsZXMuZW50ZXIoKS5hcHBlbmQoJ2NpcmNsZScpXG4gICAgICAuYXR0cignY2xhc3MnLCBkID0+IHtcbiAgICAgICAgaWYgKGQuZGVwdGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gJ3Jvb3QnXG4gICAgICAgIH0gZWxzZSBpZiAoZC5kZXB0aCA9PT0gMSkge1xuICAgICAgICAgIHJldHVybiAnY2x1c3RlcidcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gJ2l0ZW0nXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAubWVyZ2UoY2lyY2xlcylcbiAgICAgIC5hdHRyKCdjeCcsIGQgPT4gZC54KVxuICAgICAgLmF0dHIoJ2N5JywgZCA9PiBkLnkpXG4gICAgICAuYXR0cigncicsIGQgPT4gZC5yKVxuICAgICAgLy8gLm9uKCdtb3VzZW92ZXInLCB0aXAuc2hvdylcbiAgICAgIC5vbignbW91c2VvdmVyJywgZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgLy8gdXNlIGEgdGltZW91dC9kZWxheSB0byBzdG9wIGNyYXp5IGZsaWNrZXJpbmdcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXNcbiAgICAgICAgbGV0IGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cylcbiAgICAgICAgbGV0IHRpbWVvdXQgPSBudWxsXG4gICAgICAgIGFyZ3MucHVzaCh0aGlzKVxuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dClcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHRpcC5zaG93LmFwcGx5KGNvbnRleHQsIGFyZ3MpXG4gICAgICAgIH0sIDEwMClcbiAgICAgIH0pXG4gICAgICAub24oJ21vdXNlb3V0JywgdGlwLmhpZGUpXG4gIH1cbn1cblxuLy8gcnVuIHRoZSB2aXN1YWxpc2F0aW9uXG5jb25zdCBjaGFydCA9IGVuY2xvc3VyZURpYWdyYW1cbmNoYXJ0KCdnI3ZpcycsIGR1bW15RGF0YSgyNykpXG5cbi8vIHdoZW4gdGhlIGlucHV0IHJhbmdlIGNoYW5nZXMgcmUtcmVuZGVyIChzZXQgaW4gaW5kZXguaHRtbClcbmQzLnNlbGVjdCgnI2NsdXN0ZXItYW1vdW50Jykub24oJ2lucHV0JywgZnVuY3Rpb24gKCkge1xuICBkMy5zZWxlY3QoJyNzbGlkZXItYW1vdW50JykudGV4dCgrdGhpcy52YWx1ZSlcbiAgY2hhcnQoJ2cjdmlzJywgZHVtbXlEYXRhKCt0aGlzLnZhbHVlKSlcbn0pXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gc2NyaXB0LmpzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBQ0E7QUFGQTtBQUFBO0FBQUE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFkQTtBQWdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///1\n")}]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const d3 = window.d3 | |
export default (amount = 4) => { | |
// list of clusters | |
const clusters = createClusters(amount) | |
// have a root node to start with | |
let data = [ | |
{name: 'root', parent: null} | |
] | |
clusters.forEach(d => { | |
let r = Math.floor(d3.randomUniform(2, 40)()) | |
let children = createChildren(r, d) | |
// pass in the parent items | |
data.push({name: d, parent: 'root'}) | |
// pass in some children | |
data = data.concat(children) | |
}) | |
return data | |
} | |
// create clusters | |
function createClusters (amount = 4, name = 'cluster_') { | |
const list = [...Array(amount).keys()].map(d => name + d) | |
return list | |
} | |
// add some dummy data to each cluster | |
function createChildren (amount = 10, cluster = 'c_1') { | |
const o = [...Array(amount).keys()].map((d, i) => { | |
return { | |
name: `${cluster} | item_${i}`, | |
parent: cluster | |
} | |
}) | |
return o | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<title>d3js | enclosing diagram | circle pack</title> | |
<link href="//npmcdn.com/basscss@8.0.2/css/basscss.min.css" rel="stylesheet"> | |
<link href='dist.css' rel='stylesheet' /> | |
<body> | |
<header class="fixed top-0"> | |
<p class="">Number of clusters: <span id="slider-amount">27</span></p> | |
<input type="range" id="cluster-amount" value="27"> | |
</header> | |
<svg width="960" height="800"> | |
<g id="vis"></g> | |
</svg> | |
<script src='https://d3js.org/d3.v4.min.js'></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script> | |
<script src='dist.js'></script> | |
<script> | |
// set a min and max to to the range slider | |
document.getElementById('cluster-amount').max = '50' | |
document.getElementById('cluster-amount').min = '1' | |
// change frame height for bl.ocks | |
d3.select(self.frameElement).style('height', '800px') | |
</script> | |
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dummyData from './dummyData' | |
const d3 = window.d3 | |
function enclosureDiagram (bind, flatData, config) { | |
config = { | |
width: 960, | |
height: 800, | |
radius: 5, | |
padding: 5, | |
...config | |
} | |
const { width, height } = config | |
const selection = d3.select(bind) | |
// initialize tooltip after a destroy | |
d3.selectAll('.d3-tip').remove() | |
const tip = d3.tip().attr('class', 'd3-tip').html(d => d.data.id).offset([-10, 1]) | |
// invoke the tip in the context of your visualization | |
selection.call(tip) | |
// convert the flat data into a hierarchy | |
const data = d3.stratify() | |
.id(d => d.name) | |
.parentId(d => d.parent)(flatData) | |
const packLayout = d3.pack() | |
.size([width, height]) | |
.radius(() => config.radius) | |
.padding(config.padding) | |
const rootNode = d3.hierarchy(data) | |
// run .sum() on the hierarchy; return 1 for size of leaf nodes | |
rootNode.sum(() => 1) | |
packLayout(rootNode) | |
renderCircles(rootNode.descendants()) | |
function renderCircles (nodes) { | |
const circles = selection | |
.selectAll('circle') | |
.data(nodes, d => d.data.id) | |
circles.exit().remove() | |
circles.enter().append('circle') | |
.attr('class', d => { | |
if (d.depth === 0) { | |
return 'root' | |
} else if (d.depth === 1) { | |
return 'cluster' | |
} else { | |
return 'item' | |
} | |
}) | |
.merge(circles) | |
.attr('cx', d => d.x) | |
.attr('cy', d => d.y) | |
.attr('r', d => d.r) | |
// .on('mouseover', tip.show) | |
.on('mouseover', function (d) { | |
// use a timeout/delay to stop crazy flickering | |
const context = this | |
let args = [].slice.call(arguments) | |
let timeout = null | |
args.push(this) | |
clearTimeout(timeout) | |
timeout = setTimeout(function () { | |
tip.show.apply(context, args) | |
}, 100) | |
}) | |
.on('mouseout', tip.hide) | |
} | |
} | |
// run the visualisation | |
const chart = enclosureDiagram | |
chart('g#vis', dummyData(27)) | |
// when the input range changes re-render (set in index.html) | |
d3.select('#cluster-amount').on('input', function () { | |
d3.select('#slider-amount').text(+this.value) | |
chart('g#vis', dummyData(+this.value)) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* | |
box-sizing border-box | |
body | |
font-family:-apple-system,BlinkMacSystemFont,Consolas,monaco,monospace | |
width: 960px | |
margin: 0 auto | |
background: #2f292b | |
font-size: 14px | |
color: #a5a6a9 | |
letter-spacing: 3px | |
header | |
left: 15px | |
width: 250px | |
circle.item | |
fill: #2f292b | |
cursor: pointer | |
transition: fill 0.2s ease | |
circle.item:hover | |
fill: #e6c700 | |
circle.cluster | |
fill: #f45844 | |
circle.root | |
display: none | |
span | |
color: #f45844 | |
font-weight: 700 | |
input[type="range"] | |
-webkit-appearance:none | |
width: 100% | |
height:2px | |
background: #a5a6a9 | |
background-position:center | |
background-repeat:no-repeat | |
margin: auto | |
input[type="range"]::-webkit-slider-thumb | |
-webkit-appearance:none | |
width: 30px | |
height: 30px | |
border-radius: 100% | |
background: #a5a6a9 | |
position:relative | |
border: 3px solid #a5a6a9 | |
z-index: 2 | |
cursor: pointer | |
input:focus | |
outline: none | |
.d3-tip | |
font-weight: normal | |
line-height: 1.5 | |
padding: 12px | |
background: rgba(0, 0, 0, 0.8) | |
color: #f5f5f5 | |
border-radius: 2px | |
pointer-events: none | |
.d3-tip:after | |
box-sizing: border-box | |
display: inline | |
font-size: 10px | |
width: 100% | |
line-height: 1 | |
color: #231f20 | |
position: absolute | |
pointer-events: none | |
.d3-tip.n:after | |
content: "\25BC" | |
margin: -1px 0 0 0 | |
top: 100% | |
left: 0 | |
text-align: center | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment