Last active
January 4, 2016 15:19
-
-
Save owendall/8639903 to your computer and use it in GitHub Desktop.
D3 Zoomable Treemap - Need tooltip boxes
This file contains hidden or 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
| filename | sloc | |
|---|---|---|
| NonFormula/SBIR/8.5 | 1945177 | |
| NonFormula/SLBCD/NK | 3819473 | |
| NonFormula/TCEG/KX | 3084423 | |
| NonFormula/ES/AAG | 5341485 | |
| NonFormula/AFRI/A1131 | 1999679 | |
| NonFormula/AFRI/A1341 | 62510 | |
| NonFormula/COOP/FFI | 2077827 | |
| NonFormula/AFRI/92523 | 4168 | |
| NonFormula/AFRI/A1401 | 12177407.8 | |
| NonFormula/AFRI/A2101 | 10506613 | |
| NonFormula/AFRI/A2141 | 9945180 | |
| NonFormula/AFRI/A3101 | 15998499 | |
| NonFormula/AFRI/A5112 | 2016373 | |
| NonFormula/RHSE/LX | 1325066 | |
| NonFormula/RIPM/QQ.W | 617201 | |
| NonFormula/NLGCA/NLGCA | 4130960 | |
| NonFormula/OP/MEACA | 1250000 | |
| NonFormula/AFRI/A1241 | 5000000 | |
| NonFormula/AFRI/A4141 | 2465116.19 | |
| NonFormula/SBIR/8.3 | 1292228 | |
| NonFormula/SLBCD/MB | 764654 | |
| NonFormula/SAECP/UV | 557185 | |
| NonFormula/COOP/FFG | 1222270 | |
| NonFormula/EXCA/FFF | 272727 | |
| NonFormula/COOP/FFO | 147143 | |
| NonFormula/ICGP/112.D | 3510953 | |
| NonFormula/SLBCD/QQIPM | 7997452 | |
| NonFormula/WAMS/WAM | 708172 | |
| NonFormula/EXCA/FARAD | 885777 | |
| NonFormula/AFRI/A1111 | 300392 | |
| NonFormula/AFRI/A2121 | 6750066 | |
| NonFormula/AFRI/A1141 | 8833084 | |
| NonFormula/SBIR/8.12 | 2204200 | |
| NonFormula/OP/AAR | 1372956 | |
| NonFormula/SBIR/8.2 | 397632 | |
| NonFormula/RIPM/QQ.NC | 687966 | |
| NonFormula/RIPM/QQ.S | 752850 | |
| NonFormula/AFRI/A7301 | 4499998 | |
| NonFormula/AFRI/A6122 | 623116 | |
| NonFormula/AFRI/A3121 | 5000000 | |
| NonFormula/AFRI/A3141 | 10977435 | |
| NonFormula/AFRI/A5122 | 3241666 | |
| NonFormula/AFRI/A5123 | 1425000 | |
| NonFormula/SBIR/8.8 | 1777533 | |
| NonFormula/EF47/LS | 17475271 | |
| NonFormula/ERRD/UU.R | 875983 | |
| NonFormula/SLBCD/QQ.E | 176523 | |
| NonFormula/AFRI/91312 | 354997.39 | |
| NonFormula/AFRI/92120 | 660451.61 | |
| NonFormula/AFRI/A1211 | 6845598 | |
| NonFormula/AFRI/A4161 | 2000000 | |
| NonFormula/AFRI/A5113 | 1261748 | |
| NonFormula/SRGP/FPR | 1413885 | |
| NonFormula/AFRI/A6123 | 1464899 | |
| NonFormula/SRGP/AN | 1158155 | |
| NonFormula/CBGP/EP | 5913990 | |
| NonFormula/OP/MA.1 | 12373061.68 | |
| NonFormula/SRGP/MX | 1195967 | |
| NonFormula/CGP/ER | 5665691 | |
| NonFormula/BRAP/HX | 4193244 | |
| NonFormula/AFRI/A3151 | 5203456 | |
| NonFormula/AFRI/A1231 | 20900 | |
| NonFormula/EXCA/FFL | 20328673 | |
| NonFormula/AFRI/94540 | 121062.91 | |
| NonFormula/AFRI/A1201 | 4009957 | |
| NonFormula/TCRGP/ZY | 1351978 | |
| NonFormula/RIPM/QQ.NE | 546233 | |
| NonFormula/AFRI/A6141 | 2925000 | |
| NonFormula/AFRI/A7201 | 3623881.6 | |
| NonFormula/SBIR/8.4 | 2145321 | |
| NonFormula/SLBCD/LP | 2688054 | |
| NonFormula/ARPA/OC | 4555200 | |
| NonFormula/AFRI/A1331 | 2885303 | |
| NonFormula/ICGP/110.C | 2567000 | |
| NonFormula/CBGP/EWE | 4795689 | |
| NonFormula/AHSI/RD | 2827111 | |
| NonFormula/AFRI/A3142 | 966288 | |
| NonFormula/OP/MM.2 | 1914998 | |
| NonFormula/OP/CA | 3455590 | |
| NonFormula/HEMS/KF | 991000 | |
| NonFormula/ICGP/112.C | 1748251 | |
| NonFormula/AFRI/A4121 | 4994637 | |
| NonFormula/AFRI/A7101 | 1679089.23 | |
| NonFormula/RIGP/DEG | 610059 | |
| NonFormula/SBIR/8.1 | 1399908 | |
| NonFormula/COOP/FFM | 4056715 | |
| NonFormula/SBIR/8.6 | 2198054 | |
| NonFormula/CFP/LN.B | 419290 | |
| NonFormula/CFP/LN.C | 9180710 | |
| NonFormula/AFRI/A1222 | 3050000 | |
| NonFormula/AFRI/A6124 | 444258 | |
| NonFormula/AFRI/A5141 | 10345077 | |
| NonFormula/AFRI/A6101 | 31489667 | |
| NonFormula/EXCA/CCC | 4545455 | |
| NonFormula/SBIR/8.7 | 2520672.8 | |
| NonFormula/SLBCD/MC | 6775496.71 | |
| NonFormula/COOP/MN.2 | 11098 | |
| NonFormula/SRGP/MY | 130894 | |
| NonFormula/OP/HW | 711815 | |
| NonFormula/ICGP/112.E | 4219676.95 | |
| NonFormula/AFRI/A1521 | 5825170 | |
| NonFormula/COOP/FFQ | 225000 | |
| NonFormula/FBMB/FBMB | 1251076 | |
| NonFormula/AFRI/A1101 | 1123668 | |
| NonFormula/SAECP/OW | 420882 | |
| NonFormula/HSI/NJ | 8141617 | |
| NonFormula/RIGP/AAQ | 849959 | |
| NonFormula/SBIR/8.13 | 2399429 | |
| NonFormula/AFRI/A6125 | 498786 | |
| NonFormula/AFRI/A5102 | 3153300 | |
| NonFormula/AFRI/A4181 | 2406873 | |
| NonFormula/AFRI/A6121 | 733884.36 | |
| NonFormula/AFRI/A6126 | 2500000 | |
| NonFormula/SLBCD/LQ | 3781786 | |
| NonFormula/CBGP/EQ | 6759041 | |
| NonFormula/SLBCD/RB | 300000 | |
| NonFormula/SLBCD/QX | 4159613 | |
| NonFormula/F4HN/AAH | 645732 | |
| NonFormula/AFRI/A1121 | 10000 | |
| NonFormula/EXCA/FFH | 150000 | |
| NonFormula/EXCA/FFP | 35000 | |
| NonFormula/ICGP/110.A | 1376058 | |
| NonFormula/SCRI/SCRI | 2790862.38 | |
| NonFormula/AFRI/91113 | 392685.31 | |
| NonFormula/AFRI/93232 | 559650.57 | |
| NonFormula/AFRI/A1221 | 14693179.27 | |
| NonFormula/AFRI/A1511 | 1958642 | |
| NonFormula/HEP/KK | 2940000 | |
| NonFormula/SRGP/RR | 10225994 | |
| NonFormula/AFRI/A6151 | 2000000 | |
| NonFormula/AFRI/A3161 | 592547.49 | |
| NonFormula/AFRI/A4171 | 1649830 | |
| NonFormula/AFRI/A3131 | 500000 | |
| NonFormula/AFRI/A6131 | 1948733 | |
| NonFormula/SGP/SGP | 2159744 |
This file contains hidden or 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 url(http://fonts.googleapis.com/css?family=PT+Serif|PT+Serif:b|PT+Serif:i|PT+Sans|PT+Sans:b); | |
| html { | |
| min-width: 1040px; | |
| } | |
| body { | |
| background: #fcfcfa; | |
| color: #333; | |
| font-family: "PT Serif", serif; | |
| margin: 1em auto 4em auto; | |
| position: relative; | |
| width: 1040px; // Owen Dall - changed from 960 | |
| } | |
| header, | |
| footer, | |
| h1, | |
| h2, | |
| h3, | |
| h4, | |
| aside { | |
| color: #000; | |
| font-family: "PT Sans", sans-serif; | |
| } | |
| h1 { | |
| font-size: 64px; | |
| font-weight: 300; | |
| letter-spacing: -2px; | |
| margin: .3em 0 .1em 0; | |
| } | |
| h2 { | |
| margin-top: 2em; | |
| } | |
| h1, h2 { | |
| text-rendering: optimizeLegibility; | |
| } | |
| h2 a { | |
| color: #ccc; | |
| left: -20px; | |
| position: absolute; | |
| width: 740px; | |
| } | |
| footer { | |
| font-size: small; | |
| margin-top: 8em; | |
| } | |
| header aside { | |
| margin-top: 40px; | |
| } | |
| header aside, | |
| footer aside { | |
| color: #636363; | |
| text-align: right; | |
| } | |
| aside { | |
| font-size: small; | |
| right: 0; | |
| position: absolute; | |
| width: 180px; | |
| } | |
| .attribution { | |
| font-size: small; | |
| margin-bottom: 2em; | |
| } | |
| body > p, li > p { | |
| line-height: 1.5em; | |
| } | |
| body > p { | |
| width: 960px; | |
| } | |
| body > blockquote { | |
| width: 640px; | |
| } | |
| blockquote q { | |
| display: block; | |
| font-style: oblique; | |
| } | |
| li { | |
| width: 680px; | |
| } | |
| a { | |
| color: steelblue; | |
| } | |
| a:not(:hover) { | |
| text-decoration: none; | |
| } | |
| pre, code, textarea { | |
| font-family: "Menlo", monospace; | |
| } | |
| code { | |
| line-height: 1em; | |
| } | |
| textarea { | |
| font-size: 100%; | |
| } | |
| body > pre { | |
| border-left: solid 2px #ccc; | |
| padding-left: 18px; | |
| margin: 2em 0 2em -20px; | |
| } | |
| .html .value, | |
| .javascript .string, | |
| .javascript .regexp { | |
| color: #756bb1; | |
| } | |
| .html .tag, | |
| .css .tag, | |
| .javascript .keyword { | |
| color: #3182bd; | |
| } | |
| .comment { | |
| color: #636363; | |
| } | |
| .html .doctype, | |
| .javascript .number { | |
| color: #31a354; | |
| } | |
| .html .attribute, | |
| .css .attribute, | |
| .javascript .class, | |
| .javascript .special { | |
| color: #e6550d; | |
| } | |
| svg { | |
| font: 11px sans-serif; | |
| } | |
| .axis path, .axis line { | |
| fill: none; | |
| stroke: #000; | |
| shape-rendering: crispEdges; | |
| } | |
| sup, sub { | |
| line-height: 0; | |
| } | |
| q:before { | |
| content: "“"; | |
| } | |
| q:after { | |
| content: "”"; | |
| } | |
| blockquote:before { | |
| position: absolute; | |
| left: 2em; | |
| } | |
| blockquote:after { | |
| position: absolute; | |
| } | |
This file contains hidden or 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> | |
| <html> | |
| <meta charset="utf-8"> | |
| <title>Zoomable Treemap</title> | |
| <style> | |
| @import url(./base-style.css); | |
| @import url(./treemap-style.css); | |
| </style> | |
| <header> | |
| <em>Click any cell to zoom in. Click on the top orange label to zoom out.</em> | |
| <aside>Last Updated January 20, 2014</aside> | |
| </header> | |
| <h3>Zoomable Treemap of NIFA 2013 Grant Awards</h3> | |
| <p id="chart"> | |
| <p>The treemap above uses interaction to reveal the hierarchy incrementally: clicking on a node zooms in. Only two levels of the hierarchy are visible at a time. | |
| <footer> | |
| Original D3 Zoomable Treemap Design by Mike Bostock in 2012 | |
| </footer> | |
| </html> | |
| <script src="http://d3js.org/d3.v3.min.js"></script> | |
| <script> | |
| var margin = {top: 20, right: 0, bottom: 0, left: 0}, | |
| width = 960, | |
| height = 500 - margin.top - margin.bottom, | |
| formatNumber = d3.format(",d"), | |
| transitioning; | |
| var x = d3.scale.linear() | |
| .domain([0, width]) | |
| .range([0, width]); | |
| var y = d3.scale.linear() | |
| .domain([0, height]) | |
| .range([0, height]); | |
| var treemap = d3.layout.treemap() | |
| .children(function(d, depth) { return depth ? null : d._children; }) | |
| .sort(function(a, b) { return a.value - b.value; }) | |
| .ratio(height / width * 0.5 * (1 + Math.sqrt(5))) | |
| .round(false); | |
| var svg = d3.select("#chart").append("svg") | |
| .attr("width", width + margin.left + margin.right) | |
| .attr("height", height + margin.bottom + margin.top) | |
| .style("margin-left", -margin.left + "px") | |
| .style("margin.right", -margin.right + "px") | |
| .append("g") | |
| .attr("transform", "translate(" + margin.left + "," + margin.top + ")") | |
| .style("shape-rendering", "crispEdges") ; | |
| var grandparent = svg.append("g") | |
| .attr("class", "grandparent"); | |
| grandparent.append("rect") | |
| .attr("y", -margin.top) | |
| .attr("width", width) | |
| .attr("height", margin.top); | |
| grandparent.append("text") | |
| .attr("x", 6) | |
| .attr("y", 6 - margin.top) | |
| .attr("dy", ".75em"); | |
| // *** start of the replacement of the d3.json function with d3.csv code from Mark Fink. *** | |
| // data is in the format of | |
| // grandparent/parent/child, 102345 | |
| // first line of csv file contains: | |
| // filename,sloc | |
| d3.csv("2013_nifa_non_formula_awards.csv", function(data) { | |
| // convert csv data into flare.json format | |
| function level(nodes) { | |
| return d3.nest() | |
| .key(function(d) { | |
| // console.log('key for: ' + JSON.stringify(d)); | |
| if (d.filename.indexOf('/') === -1) return d.filename; | |
| else return d.filename.substr(0, d.filename.indexOf('/')); | |
| }) | |
| .rollup(function(v) { | |
| // console.log('rollup: ' + JSON.stringify(v)); | |
| // leaf | |
| if (v.length === 1 && v[0].filename.indexOf('/') === -1) { | |
| return {'value': parseInt(v[0].sloc)}; | |
| } | |
| // node | |
| v.map(function(d) { d.filename = d.filename.substring(d.filename.indexOf('/')+1); return d; }); | |
| return {'children': level(v)}; | |
| }) | |
| .entries(nodes) | |
| .map(function(d) { | |
| d.values['name'] = d.key; | |
| return d.values; | |
| }); | |
| }; | |
| var root = {'name': 'ALL NON-FORMULA AWARDS', 'children': level(data)}; | |
| // console.log('root: ' + JSON.stringify(root)); | |
| initialize(root); | |
| accumulate(root); | |
| layout(root); | |
| display(root); | |
| function initialize(root) { | |
| root.x = root.y = 0; | |
| root.dx = width; | |
| root.dy = height; | |
| root.depth = 0; | |
| } | |
| // *** end of replacement of the d3.json function with d3,csv | |
| // Aggregate the values for internal nodes. This is normally done by the | |
| // treemap layout, but not here because of our custom implementation. | |
| // We also take a snapshot of the original children (_children) to avoid | |
| // the children being overwritten when when layout is computed. | |
| function accumulate(d) { | |
| return (d._children = d.children) | |
| ? d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0) | |
| : d.value; | |
| } | |
| // Compute the treemap layout recursively such that each group of siblings | |
| // uses the same size (1×1) rather than the dimensions of the parent cell. | |
| // This optimizes the layout for the current zoom state. Note that a wrapper | |
| // object is created for the parent node for each group of siblings so that | |
| // the parent’s dimensions are not discarded as we recurse. Since each group | |
| // of sibling was laid out in 1×1, we must rescale to fit using absolute | |
| // coordinates. This lets us use a viewport to zoom. | |
| function layout(d) { | |
| if (d._children) { | |
| treemap.nodes({_children: d._children}); | |
| d._children.forEach(function(c) { | |
| c.x = d.x + c.x * d.dx; | |
| c.y = d.y + c.y * d.dy; | |
| c.dx *= d.dx; | |
| c.dy *= d.dy; | |
| c.parent = d; | |
| layout(c); | |
| }); | |
| } | |
| } | |
| function display(d) { | |
| grandparent | |
| .datum(d.parent) | |
| .on("click", transition) | |
| .select("text") | |
| .text(name(d)); | |
| var g1 = svg.insert("g", ".grandparent") | |
| .datum(d) | |
| .attr("class", "depth"); | |
| var g = g1.selectAll("g") | |
| .data(d._children) | |
| .enter().append("g"); | |
| g.filter(function(d) { return d._children; }) | |
| .classed("children", true) | |
| .on("click", transition); | |
| g.selectAll(".child") | |
| .data(function(d) { return d._children || [d]; }) | |
| .enter().append("rect") | |
| .call(rect); | |
| g.append("rect") | |
| .attr("class", "parent") | |
| .call(rect) | |
| .append("title") | |
| .text(function(d) { return "TITLE: " + d.name + " $" + formatNumber(d.value); }) | |
| // .text(function(d) { return formatNumber(d.value); }); | |
| // Modified by Owen Dall 2014-01-20 to add Dollars to the labels | |
| g.append("text") | |
| .attr("dy", ".75em") | |
| .text(function(d) { return d.name + " ($" + formatNumber(d.value)+")"; }) // Modified by Owen Dall | |
| .call(text); | |
| function transition(d) { | |
| if (transitioning || !d) return; | |
| transitioning = true; | |
| var g2 = display(d), | |
| t1 = g1.transition().duration(750), | |
| t2 = g2.transition().duration(750); | |
| // Update the domain only after entering new elements. | |
| x.domain([d.x, d.x + d.dx]); | |
| y.domain([d.y, d.y + d.dy]); | |
| // Enable anti-aliasing during the transition. | |
| svg.style("shape-rendering", null); | |
| // Draw child nodes on top of parent nodes. | |
| svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; }); | |
| // Fade-in entering text. | |
| g2.selectAll("text").style("fill-opacity", 0); | |
| // Transition to the new view. | |
| t1.selectAll("text").call(text).style("fill-opacity", 0); | |
| t2.selectAll("text").call(text).style("fill-opacity", 1); | |
| t1.selectAll("rect").call(rect); | |
| t2.selectAll("rect").call(rect); | |
| // Remove the old node when the transition is finished. | |
| t1.remove().each("end", function() { | |
| svg.style("shape-rendering", "crispEdges"); | |
| transitioning = false; | |
| }); | |
| } | |
| return g; | |
| } | |
| function text(text) { | |
| text.attr("x", function(d) { return x(d.x) + 6; }) | |
| .attr("y", function(d) { return y(d.y) + 6; }); | |
| } | |
| function rect(rect) { | |
| rect.attr("x", function(d) { return x(d.x); }) | |
| .attr("y", function(d) { return y(d.y); }) | |
| .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); }) | |
| .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); }) | |
| .attr("class", "child"); | |
| // OBD - Is this the place to add the mouseover events? | |
| } | |
| function name(d) { | |
| return d.parent | |
| ? name(d.parent) + "." + d.name | |
| : d.name; | |
| } | |
| // Added by Owen Dall | |
| }); | |
| </script> |
This file contains hidden or 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
| // Removed from the treemap.html file | |
| #chart { | |
| width: 960px; | |
| height: 500px; | |
| background: #ddd; | |
| } | |
| text { | |
| pointer-events: none; | |
| } | |
| .grandparent text { | |
| font-weight: bold; | |
| } | |
| rect { | |
| fill: #bbb; | |
| stroke: #fff; | |
| } | |
| rect.parent, | |
| .grandparent rect { | |
| stroke-width: 3px; | |
| } | |
| .grandparent rect { | |
| fill: #2EB8E6; | |
| } | |
| .grandparent:hover rect { | |
| fill: #ee9700; | |
| } | |
| .children rect.parent, | |
| .grandparent rect { | |
| cursor: pointer; | |
| } | |
| .children rect.parent { | |
| fill: #bbb; | |
| fill-opacity: .5; | |
| } | |
| .children:hover rect.child { | |
| fill: #bbb; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment