NVD3 Horizontal Bar Chart labels too long

喜欢而已 提交于 2019-12-01 23:12:11
Martin Peschke

Why not just add margins?

var chart = nv.models.multiBarHorizontalChart()
               .margin({top: 30, right: 20, bottom: 50, left: 175});
Eric S. Bullington

What you're wanting to do is likely beyond the capabilities of nvd3 as written.

Actually, I just found an approach with d3 that -- with some difficulty -- could perhaps be applied to nvd3 here. It involves calculating the sentence length and size on the fly, and then wrapping it by positioning the calculated segments using absolute and relative coordinates. See here for an example:

http://bl.ocks.org/mbostock/7555321

That said, when you want to get this level of customization, it's probably best to go with d3. If you're using nvd3 in your project for another charts, you already have access to d3. And there are a number of examples of horizontal bar charts using d3 available online. For example, here is a great tutorial by d3 creator Mike Bostock in which he takes you through the steps needed to make a horizontal bar chart with d3, step by step:

http://bost.ocks.org/mike/bar/

And a few examples of a horizontal bar chart using d3:

Even with d3, where you have easy access to the underlying svg references, it's difficult to get text to wrap in svg. In fact, the version of svg that most browsers use doesn't even have support for svg text wrapping.

To work around this limitation, you could use the approach I linked to above, which involves calculating the sentence length on the fly, and dynamically positioning 1 or more segments using the coordinate system. However, the easiest approach is probably to embed an HTML element inside of the svg element using the foreignObject element. Once you've got that HTML div, you can easily set the width and the text will wrap automatically.

For more details on how to do this:

Auto line-wrapping in SVG text

If you have any trouble getting your text to wrap using this approach, please ask about it in another question and I'll be happy to help.

The answer might be a late but hopefully it helps. I've used Mike Bostock’s Wrapping long labels example with the question.

Here's what I've done differently to your code.

Added margins to the chart to make it pretty:

var chart = nv.models.multiBarHorizontalChart().margin({
  top: 30, right: 20, bottom: 50, left: 100
});

Finally I selected all the xAxis ticks on the chart and applied Mike Bostock’s Wrapping long labels function wrap to it.

d3.selectAll(".nv-x.nv-axis .tick text").each(function(i, e) {
  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(" "));
    // TDOD : Make 80 a dynamic value based on the bar width/height
    if (tspan.node().getComputedTextLength() > 80) {
      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);
    }
  }
});

Final output

Here's a working version of the example.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!