Improve vertical positioning of wrapped text
Opened this issue · 7 comments
For example, in the bump chart (I've made the label for the United States longer to show how it looks when wrapped):
It might be nicer to centre the text like this:
This is the modified wrap()
function for the bump chart:
function wrap(text, width) {
text.each(function(d,i) {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y)
tspans = [tspan];
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).text(word);
tspans.push(tspan);
}
}
var dy = -(tspans.length - 1) * lineHeight / 2;
tspans.forEach(function(tspan) {
tspan.attr("dy", dy + "em")
dy += lineHeight;
});
});
}
Should I change the wrap functions in some of the templates?
How does it handle 3 lines of wrapping?
Here's an example:
That's with the slightly tweaked version below. (It reduces lineHeight to 0.9 ems if there are three or more lines.)
function wrap(text, width) {
text.each(function(d,i) {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
lineHeight3 = 0.9, // line height if there are 3 or more lines, ems
y = text.attr("y"),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y)
tspans = [tspan];
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).text(word);
tspans.push(tspan);
}
}
if (tspans.length >= 3) {
lineHeight = lineHeight3;
}
var dy = -(tspans.length - 1) * lineHeight / 2;
tspans.forEach(function(tspan) {
tspan.attr("dy", dy + "em")
dy += lineHeight;
});
});
}
It works, it still feels a not complete solution to have something for 2 lines and something different for 3 lines although it's something we've done in the past
I know, it feels a bit ugly. I can't think of anything better though!
Was wondering if you could do some .attr("transform","translate()")
, maybe even on the parent text
element?
Was wondering if you could do some
.attr("transform","translate()")
, maybe even on the parenttext
element?
Possibly. It might make the code more complicated though?
The decreased line height for 3 or more rows isn't really necessary. It just seemed to look nicer when you squeeze the lines closer together when there are lots of lines. Maybe there could just be a single lineHeight option in the config that you could play with until the chart looks right?
Just for reference, not necessarily the best way to do it: https://observablehq.com/@jtrim-ons/svg-text-wrapping