Last active
March 20, 2019 13:55
-
-
Save jbothma/2a01ee66d5ac64aa285a00f1724814d3 to your computer and use it in GitHub Desktop.
d3 v4 treemap with wrapping
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> | |
| <meta charset="utf-8"> | |
| <head> | |
| <title>Treemap layout (with labels)</title> | |
| </head> | |
| <style> | |
| rect { | |
| fill: cadetblue; | |
| opacity: 0.3; | |
| stroke: white; | |
| } | |
| text { | |
| font-family: "Helvetica Neue", Helvetica, sans-serif; | |
| fill: white; | |
| font-size: 10px; | |
| } | |
| html, body { | |
| overflow: hidden; | |
| margin: 0; | |
| font-family: "Helvetica Neue", Helvetica; | |
| } | |
| .labelbody { | |
| margin: 2px; | |
| } | |
| foreignObject { | |
| font: 10px sans-serif; | |
| text-overflow: ellipsis; | |
| text-align: left; | |
| word-wrap: break-word; | |
| } | |
| </style> | |
| <body> | |
| <svg width="420" height="220"> | |
| <g></g> | |
| </svg> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.js"></script> | |
| <script> | |
| var data = { | |
| children: [ | |
| { | |
| name: "Social Development", | |
| value: 400 | |
| }, | |
| { | |
| name: "Police", | |
| value: 300 | |
| }, | |
| { | |
| name: "Cooperative Governance & Traditional Affairs", | |
| value: 300 | |
| }, | |
| { | |
| name: "Basic Edication", | |
| value: 100 | |
| }, | |
| { | |
| name: "Higher Education & Training & something & something else", | |
| value: 50 | |
| } | |
| ] | |
| }; | |
| var treemapLayout = d3.treemap().size([400, 200]); | |
| var rootNode = d3.hierarchy(data); | |
| rootNode.sum(function(d) { | |
| return d.value; | |
| }); | |
| treemapLayout(rootNode); | |
| var paddingAllowance = 2; | |
| var nodes = d3 | |
| .select("svg g") | |
| .selectAll("g") | |
| .data(rootNode.descendants()) | |
| .enter() | |
| .append("g") | |
| .attr("transform", function(d) { | |
| return "translate(" + [d.x0, d.y0] + ")"; | |
| }); | |
| nodes | |
| .append("rect") | |
| .attr("width", function(d) { | |
| return d.x1 - d.x0; | |
| }) | |
| .attr("height", function(d) { | |
| return d.y1 - d.y0; | |
| }); | |
| if (window["isIE"]) { | |
| // IE sucks so you have to manually truncate the labels here | |
| nodes | |
| .append("text") | |
| .attr("class", "foreignObject") | |
| .attr("transform", "translate(3, 13)") | |
| .text(function(d) { | |
| return (d.y1 - d.y0) < 16 ? "" : d.data.name; | |
| }) | |
| .filter(function(d) { | |
| d.tw = this.getComputedTextLength(); | |
| return (d.x1 - d.x0) < d.tw; | |
| }) | |
| .each(function(d) { | |
| // ridiculous routine where we test to see if label is short enough to fit | |
| var proposedLabel = d.name; | |
| var proposedLabelArray = proposedLabel.split(""); | |
| while (d.tw > (d.x1 - d.x0) && proposedLabelArray.length) { | |
| // pull out 3 chars at a time to speed things up (one at a time is too slow) | |
| proposedLabelArray.pop(); | |
| proposedLabelArray.pop(); | |
| proposedLabelArray.pop(); | |
| if (proposedLabelArray.length === 0) { | |
| proposedLabel = ""; | |
| } else { | |
| proposedLabel = proposedLabelArray.join("") + "..."; // manually truncate with ellipsis | |
| } | |
| d3.select(this).text(proposedLabel); | |
| d.tw = this.getComputedTextLength(); | |
| } | |
| }); | |
| } else { | |
| // normal browsers use these labels; | |
| // using foreignObject inside SVG allows use of wrapping text inside | |
| // divs rather than less-flexible svg-text labels | |
| nodes | |
| .append("foreignObject") | |
| .attr("class", "foreignObject") | |
| .attr("width", function(d) { | |
| return (d.x1 - d.x0) - paddingAllowance; | |
| }) | |
| .attr("height", function(d) { | |
| return (d.y1 - d.y0) - paddingAllowance; | |
| }) | |
| .append("xhtml:body") | |
| .attr("class", "labelbody") | |
| .append("div") | |
| .attr("class", "label") | |
| .text(function(d) { | |
| return d.data.name; | |
| }) | |
| .attr("text-anchor", "middle"); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment