问题
I have data that has long labels, i.e:
values:
[
{ x : "This is a really looong label", y : 40 },
{ x : "Short label", y : 30 }
]
and only a small portion of the text is shown and the rest is hidden
Here is a jsfiddle to demonstrate the issue.
Ideally I would like to set a custom width for the labels and/or make them able to use multiple lines if they overflow.
Is this possible?
回答1:
Why not just add margins?
var chart = nv.models.multiBarHorizontalChart()
.margin({top: 30, right: 20, bottom: 50, left: 175});
回答2:
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:
- http://jsfiddle.net/datashaman/rBfy5/4/light/
- http://bl.ocks.org/mbostock/1389927
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.
回答3:
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.
来源:https://stackoverflow.com/questions/26546731/nvd3-horizontal-bar-chart-labels-too-long