Skip to content

Instantly share code, notes, and snippets.

@ivanlanin
Forked from mbostock/.block
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivanlanin/9030183 to your computer and use it in GitHub Desktop.
Save ivanlanin/9030183 to your computer and use it in GitHub Desktop.
Wrapping long text with bar transition

This example, using satirical data from The Onion, demonstrates how to wrap long axis labels to fit on multiple lines.

Forked from Mike's Gist as a personal journey to study various aspects of D3. Some additional features added:

It turns out that some features (tooltip, alert) can only be used by using open in new window in bl.ocks.

id name value notes
7 Family in feud with Zuckerbergs .17 Well, there's nothing else we can do about that, eh?
12 Committed 671 birthdays to memory .19 Or hire a secretary to do that
11 Ex is doing too well .10 I can't stand reading her happy statuses everyday
8 High school friends all dead now .15 I left alone
3 Discovered how to “like” things mentally .27 And the first thing I like is marshmellow
1 Not enough politics .12 Better watch TV or sit around cafes
<!DOCTYPE html>
<html>
<head>
<title>Vertical bar chart with D3</title>
<meta charset="utf-8" />
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://rawgithub.com/Caged/d3-tip/master/index.js"></script>
<style>
body {
font: normal 10px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.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;
}
.d3-tip {
line-height: 1;
padding: 5px;
background: #eee;
border: 1px solid #999;
color: black;
width: 100px;
border-radius: 2px;
}
.d3-tip .notes {
border-bottom: 1px solid #999;
padding-bottom: 5px;
margin-bottom: 5px;
}
</style>
</head>
<body>
<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.scale.ordinal()
.rangeRoundBands([0, width], .1, .3);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(8, "%");
var tip = d3.tip()
.attr('class', 'd3-tip')
.direction('n')
.offset([-5, 0])
.html(function(d) {
return '<div class="notes">' + d.notes + '</div>' +
'<div class="attrib">Pct: ' + d.value * 100 + '%' +
'<br />ID: ' + d.id + '</div>';
})
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 + ")");
// Read TSV data. All functions that depends on the data should be put
// inside this function
d3.tsv("data.tsv", type, function (error, data) {
x.domain(data.map(function (d) { return d.name; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]);
// Title
svg.append("text")
.attr("class", "title")
.attr("x", x(data[0].name))
.attr("y", -26)
.text("Why Are We Leaving Facebook?");
// Axes
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis)
.selectAll(".tick text")
.call(wrap, x.rangeBand());
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// Data bars
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function (d) { return x(d.name); })
.attr("y", function (d) { return height; })
.attr("width", x.rangeBand())
.attr("height", function (d) { return 0; })
.call(tip)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.on("click", function(d) {
alert(d.name + ' clicked!');
// window.location = ...; // Can be use to go to certain pages
})
.transition()
.duration(1000)
.delay(500)
.attr("y", function (d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value) });
});
/**
* Wrap text
*
* @param string text Text to be wrapped
* @param int width Wrap width
*/
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);
}
}
});
}
/**
* What's this for?
*/
function type(d) {
d.value = +d.value;
return d;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment