D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
mpmckenna8
Full window
Github gist
hacky solution for friends' problem
<!DOCTYPE html > <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> .node circle { fill: #999; } .node text { font: 10px sans-serif; } .node--internal circle { fill: #555; } .node--internal text { text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff; } .link { fill: none; stroke: #555; stroke-opacity: 0.4; stroke-width: 1.5px; } </style> </head> <body> <svg class = 'squares'></svg> <svg class= 'treemap' width = "800" height = "896" ></svg> <script> var data = [ { 'name': 'request-promise', "dependencies": { "name": "request-promise", "children": [{ "name": "dependency", "children": [{ "name": "request-promise-core" }, { "name": "bluebird" }, { "name": "stealthy-require" }, { "name": "tough-cookie" }] }, { "name": "devDependency", "children": [{ "name": "body-parser" }, { "name": "chai" }, { "name": "chalk" }, { "name": "gulp" }, { "name": "gulp-coveralls" }, { "name": "gulp-eslint" }, { "name": "gulp-istanbul" }, { "name": "gulp-mocha" }, { "name": "lodash" }, { "name": "publish-please" }, { "name": "request" }, { "name": "rimraf" }, { "name": "run-sequence" }] }, { "name": "peerDependency", "children": [{ "name": "request" }] }] }}, { 'name': 'webpack', "dependencies": { "name": "webpack", "children": [{ "name": "dependency", "children": [{ "name": "acorn" }, { "name": "acorn-dynamic-import" }, { "name": "ajv" }, { "name": "ajv-keywords" }, { "name": "async" }, { "name": "enhanced-resolve" }, { "name": "interpret" }, { "name": "json-loader" }, { "name": "json5" }, { "name": "loader-runner" }, { "name": "loader-utils" }, { "name": "memory-fs" }, { "name": "mkdirp" }, { "name": "node-libs-browser" }, { "name": "source-map" }, { "name": "supports-color" }, { "name": "tapable" }, { "name": "uglify-js" }, { "name": "watchpack" }, { "name": "webpack-sources" }, { "name": "yargs" }] }, { "name": "devDependency", "children": [{ "name": "beautify-lint" }, { "name": "benchmark" }, { "name": "bundle-loader" }, { "name": "codacy-coverage" }, { "name": "codecov.io" }, { "name": "coffee-loader" }, { "name": "coffee-script" }, { "name": "coveralls" }, { "name": "css-loader" }, { "name": "es6-promise-polyfill" }, { "name": "eslint" }, { "name": "eslint-plugin-node" }, { "name": "express" }, { "name": "extract-text-webpack-plugin" }, { "name": "file-loader" }, { "name": "i18n-webpack-plugin" }, { "name": "istanbul" }, { "name": "jade" }, { "name": "jade-loader" }, { "name": "js-beautify" }, { "name": "less" }, { "name": "less-loader" }, { "name": "lodash" }, { "name": "mocha" }, { "name": "mocha-lcov-reporter" }, { "name": "nsp" }, { "name": "raw-loader" }, { "name": "react" }, { "name": "react-dom" }, { "name": "script-loader" }, { "name": "should" }, { "name": "simple-git" }, { "name": "sinon" }, { "name": "style-loader" }, { "name": "url-loader" }, { "name": "val-loader" }, { "name": "vm-browserify" }, { "name": "webpack-dev-middleware" }, { "name": "worker-loader" }] }] }}, { 'name': 'yargs', "dependencies": { "name": "yargs", "children": [{ "name": "dependency", "children": [{ "name": "camelcase" }, { "name": "cliui" }, { "name": "decamelize" }, { "name": "get-caller-file" }, { "name": "os-locale" }, { "name": "read-pkg-up" }, { "name": "require-directory" }, { "name": "require-main-filename" }, { "name": "set-blocking" }, { "name": "string-width" }, { "name": "which-module" }, { "name": "y18n" }, { "name": "yargs-parser" }] }, { "name": "devDependency", "children": [{ "name": "chai" }, { "name": "chalk" }, { "name": "coveralls" }, { "name": "cpr" }, { "name": "cross-spawn" }, { "name": "es6-promise" }, { "name": "hashish" }, { "name": "mocha" }, { "name": "nyc" }, { "name": "rimraf" }, { "name": "standard" }, { "name": "standard-version" }, { "name": "which" }, { "name": "yargs-test-extends" }] }] } }, { "name": 'bluebird', "dependencies": { "name": "bluebird", "children": [{ "name": "devDependency", "children": [{ "name": "acorn" }, { "name": "baconjs" }, { "name": "bluebird" }, { "name": "body-parser" }, { "name": "browserify" }, { "name": "cli-table" }, { "name": "co" }, { "name": "cross-spawn" }, { "name": "glob" }, { "name": "grunt-saucelabs" }, { "name": "highland" }, { "name": "istanbul" }, { "name": "jshint" }, { "name": "jshint-stylish" }, { "name": "mkdirp" }, { "name": "mocha" }, { "name": "open" }, { "name": "optimist" }, { "name": "rimraf" }, { "name": "rx" }, { "name": "serve-static" }, { "name": "sinon" }, { "name": "uglify-js" }, { "name": "kefir" }] }] } }]; ////////////////////////////////////////////////// // Clicking the black boxes will render the dependency tree map // The bug is in the node data join // The paths seem to render fine but old nodes are not removed //////////////////////////////////////////////// const dependencies = d3.select('.treemap'), width = window.innerHeight- 250, height = window.innerWidth- 250; const treemap = d3.tree() .size([height, width]); const buildDependencies = function(pkg){ console.log(pkg) d3.selectAll('g.node').remove() const stratify = d3.stratify() .parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); }); let nodes = d3.hierarchy(pkg.dependencies, function(d) { return d.children; }); nodes = treemap(nodes); //here is where stratify is called const updateLinks = dependencies.selectAll(".link") .data(nodes.descendants().slice(1)) const enterLinks = updateLinks.enter().append("path") .attr("class", "link") const exitLink = updateLinks.exit().remove(); updateLinks.merge(enterLinks).attr("d", function(d) { return "M" + d.y + "," + d.x + "C" + (d.y + d.parent.y) / 2 + "," + d.x + " " + (d.y + d.parent.y) / 2 + "," + d.parent.x + " " + d.parent.y + "," + d.parent.x; }); const updateNodes = dependencies.selectAll("g.nodes") .data(nodes.descendants(), d => d) const enterNodes = updateNodes.enter().append("g") .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); }) .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) enterNodes.append("circle") .attr("r", function(d) { return 15; }) .style("stroke", function(d) { return 'yellow'; }) .style("fill", function(d) { return 'green'; }); enterNodes.append("text") .attr("dy", ".35em") .attr("x", function(d) { return 25 }) .style("text-anchor", function(d) { return d.children ? "end" : "start"; }) .text(function(d) { return d.data.name; }); updateNodes.merge(enterNodes) const exitNode = updateNodes.exit().remove(); } const squares = d3.select('svg.squares') .attr('height', 400).attr('width', 400) squares.append('g').selectAll('rects') .data(data).enter() .append('rect').attr('x', (d, i) => { return i * 100 }).attr('y', (d, i) => { console.log(d) return 100 }) .attr('width', 50).attr('height', 50) .attr('fill', 'black') .on('click', (d) => { console.log(d) buildDependencies(d) }) </script> </body>
https://d3js.org/d3.v4.min.js