Skip to content

Instantly share code, notes, and snippets.

@bentedder
Forked from guypursey/.block
Created March 19, 2018 14:49
Show Gist options
  • Save bentedder/3e046c23b9c0c31f7ffeb356600228ac to your computer and use it in GitHub Desktop.
Save bentedder/3e046c23b9c0c31f7ffeb356600228ac to your computer and use it in GitHub Desktop.
Wrapping long labels with D3 v4 (sample data)
license: gpl-3.0

This is a fork of Mike Bostock's Block/Gist showing how to wrap long labels in D3. However, I've adapted it to use D3 v4 (latest version of D3 at time of writing).

This demonstration uses satirical data from The Onion.

The changes to Bostock's code are not substantial.

  • Some method names and usages had to change to be compatible with D3 v4.
  • I decluttered most of the JavaScript semicolons.
  • I replaced many of the pure function declarations with easier-to-read arrow functions.
name value
Family in feud with Zuckerbergs .17
Committed 671 birthdays to memory .19
Ex is doing too well .10
High school friends all dead now .15
Discovered how to “like” things mentally .27
Not enough politics .12
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.title {
font: bold 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
var margin = {top: 80, right: 180, bottom: 80, left: 180},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom
var x = d3.scaleBand()
.range([0, width])
.paddingInner(.1)
.paddingOuter(.3)
var y = d3.scaleLinear()
.range([height, 0])
var xAxis = d3.axisBottom(x)
var yAxis = d3.axisLeft(y)
.ticks(8, "%")
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`)
d3.tsv("data.tsv", d => { d.value = +d.value; return d }, function(error, data) {
x.domain(data.map(d => d.name))
y.domain([0, d3.max(data, d => d.value)])
svg.append("text")
.attr("class", "title")
.attr("x", x(data[0].name))
.attr("y", -26)
.text("Why Are We Leaving Facebook?")
svg.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0, ${height})`)
.call(xAxis)
.selectAll(".tick text")
.call(wrap, x.bandwidth())
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", d => x(d.name))
.attr("width", x.bandwidth())
.attr("y", d => y(d.value))
.attr("height", d => height - y(d.value))
})
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em")
while (word = words.pop()) {
line.push(word)
tspan.text(line.join(" "))
if (tspan.node().getComputedTextLength() > width) {
line.pop()
tspan.text(line.join(" "))
line = [word]
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", `${++lineNumber * lineHeight + dy}em`).text(word)
}
}
})
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment