5

I have a D3 Bar chart which X-Axis label is overlapping onto each other. I have the following:

// word wrapping for x axis

svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)

attempted to follow http://bl.ocks.org/mbostock/7555321 by adding the necessary function but to no valid. Anyone able to advise?

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);
      }
    }
  });

thank you.

kenAu89
  • 101
  • 1
  • 11
  • What happened when you used that function? Were the labels still too long, not broken into seperate lines? What do your labels look like? – Lars Kotthoff Mar 23 '14 at 13:41
  • 5
    Yes, if you provide the complete piece where you are calling the wrap function we should be able to help you. I have just recently applied it with success. – FernOfTheAndes Mar 24 '14 at 02:11

1 Answers1

0

Instead of just setting position even width has to be set but there is no way you can set width like html tag in svg text tag rather you could simply add multiple tspan and the relative top should be changed that's why in your function dy of tspan is set to lineNumber * lineHeight + dy.

In the bellow code .selectAll(".tick text") will select all text tags inside tag with tick class.

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis)
.selectAll(".tick text")
  .call(wrap, x.rangeBand());

look at your code, you are having wrap function but its not bean called. it should be called to format the text.

The call will call the function with first argument the svg object selected and the second the parameter you pass.

Hence for each text tag inside tag with class tick the wrap function will be called with first attribute svg text object and second the value of x.rangeBand().

Your wrap function copy the string inside text object by spiting it into list of words and then empty the text tag content by text.text(null).

Once the text object is empty it adds a tspan tag and sets the text such that the length doesn't exceed given width and if still more words left then it appends another tspan and it repeats untill all words are added.

You can find multiple tspan tags inside text tag and each one will have text less than or equal to the width (just inspect element).

Mr. A
  • 1,221
  • 18
  • 28