Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I include newlines in labels in D3 charts?

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 (&#xA;) 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 tspans (or do something else) so that my labels don't overlap?

like image 583
bdesham Avatar asked Nov 05 '12 22:11

bdesham


2 Answers

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.

like image 143
bdesham Avatar answered Sep 23 '22 09:09

bdesham


SVG text element does not support text-wrapping, so there are two options:

  • split the text into multiple SVG text elements
  • use an overlay HTML div on top of the SVG

See Mike Bostock's comment on this here.

like image 25
Ilya Boyandin Avatar answered Sep 21 '22 09:09

Ilya Boyandin