Last active
November 20, 2020 21:25
-
-
Save billdwhite/6243279 to your computer and use it in GitHub Desktop.
treemap with truncating labels
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
<html> | |
<head> | |
<title>Treemap with Wrapping and Truncated Labels</title> | |
<meta charset="utf-8"> | |
<!-- poor man's browser detection --> | |
<!--[if IE]><script type="text/javascript">window['isIE'] = true;</script><![endif]--> | |
<script type="text/javascript" src="./d3/d3.js" charset="utf-8"></script> | |
<style type="text/css"> | |
html, body { | |
overflow: hidden; | |
margin: 0; | |
font-family: "Helvetica Neue", Helvetica; | |
} | |
rect { | |
fill: none; | |
stroke: #FFFFFF; | |
} | |
.labelbody { | |
margin: 2px; | |
} | |
.foreignObject { | |
font: 9px sans-serif; | |
text-overflow: ellipsis; | |
text-align: left; | |
word-wrap: break-word; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="chart"></div> | |
<script type="text/javascript"> | |
var w = 550; | |
var h = 550; | |
var paddingAllowance = 2; | |
var color = d3.scale.category20c(); | |
var treemap = d3.layout.treemap() | |
.size([w, h]) | |
.padding([20, 4, 4, 4]) | |
.value(function(d) { | |
return d.size; | |
}); | |
var svg = d3.select("#chart").append("svg") | |
.style("position", "relative") | |
.style("width", w + "px") | |
.style("height", h + "px") | |
.append("g") | |
.attr("transform", "translate(-.5,-.5)"); | |
d3.json("../data/flare0.json", function(json) { | |
var cell = svg.data([json]).selectAll("g") | |
.data(treemap) | |
.enter().append("g") | |
.attr("class", "cell") | |
.attr("transform", function(d) { | |
return "translate(" + d.x + "," + d.y + ")"; | |
}); | |
cell.append("rect") | |
.attr("width", function(d) { | |
return d.dx; | |
}) | |
.attr("height", function(d) { | |
return d.dy; | |
}) | |
.style("fill", function(d) { | |
return d.children ? color(d.name) : null; | |
}); | |
if (window['isIE']) { // IE sucks so you have to manually truncate the labels here | |
cell.append("text") | |
.attr("class", "foreignObject") | |
.attr("transform", "translate(3, 13)") | |
.text(function(d) { | |
return (d.dy < 16 ? "" : d.name); | |
}) | |
.filter(function(d) { | |
d.tw = this.getComputedTextLength(); | |
return d.dx < 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.dx && 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 | |
cell.append("foreignObject") | |
.attr("class", "foreignObject") | |
.attr("width", function(d) { | |
return d.dx - paddingAllowance; | |
}) | |
.attr("height", function(d) { | |
return d.dy - paddingAllowance; | |
}) | |
.append("xhtml:body") | |
.attr("class", "labelbody") | |
.append("div") | |
.attr("class", "label") | |
.text(function(d) { | |
return d.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