I'm using D3 to generate a bar chart (I adapted the code from this example). The labels I'm using on the x-axis are a couple of words long each, and since this makes all of the labels overlap I need to break these labels across lines. (It'll be fine if I can replace all of the spaces in each label with newlines.)
I originally tried this by replacing the spaces with literal newlines (

) and setting xml:space="preserve"
on the labels' <text>
elements. Unfortunately, it turns out that SVG doesn't respect this property. Next I tried to wrap each word in a <tspan>
that I could later style. I passed each label through this function:
function (text) { return '<tspan>' + text.replace(/ /g, '</tspan><tspan>') + '</tspan>'; }
but this just puts literal <tspan>
s into the output. How can I wrap my text labels in tspan
s (or do something else) so that my labels don't overlap?
I ended up using the following code to break each x-axis label across lines:
var insertLinebreaks = function (d) { var el = d3.select(this); var words = d.split(' '); el.text(''); for (var i = 0; i < words.length; i++) { var tspan = el.append('tspan').text(words[i]); if (i > 0) tspan.attr('x', 0).attr('dy', '15'); } }; svg.selectAll('g.x.axis g text').each(insertLinebreaks);
Note that this assumes that the labels have already been created. (If you follow the canonical histogram example then the labels will have been set up in just the way you need.) There also isn't any real line-breaking logic present; the function converts every space into a newline. This fits my purposes fine but you may need to edit the split()
line to be smarter about how it partitions the parts of the string into lines.
SVG text element does not support text-wrapping, so there are two options:
See Mike Bostock's comment on this here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With