I was trying to break long lines of y-axis labels. My bar chart is like this but with longer labels (usually more than 10 words with spaces). This is my code (it works and I see the chart, the only 'error' is the text, i load the JSON dinamically, this data is only for SO):
HTML:
<svg id='table1'></svg>
<script>
var window_width = $(window).width();
var main_width = (window_width / 100 ) * 80;
var w = main_width - 400;
var data = {
labels: [
'the text to be splitted 1', 'the text to be splitted 2'
],
series: [
{
label: '2012',
values: [4, 8]
},
{
label: '2013',
values: [12, 43]
}
]
};
var chartWidth = w,
barHeight = 25,
groupHeight = barHeight * data.series.length,
gapBetweenGroups = 10,
spaceForLabels = 175,
spaceForLegend = 0;
// Zip the series data together (first values, second values, etc.)
var zippedData = [];
for (var i=0; i<data.labels.length; i++) {
for (var j=0; j<data.series.length; j++) {
zippedData.push(data.series[j].values[i]);
}
}
var chartHeight = barHeight * zippedData.length + gapBetweenGroups * data.labels.length;
var x = d3.scale.linear()
.domain([0, d3.max(zippedData)])
.range([0, chartWidth]);
var y = d3.scale.linear()
.range([chartHeight + gapBetweenGroups, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.tickFormat('')
.tickSize(0)
.orient("left");
// Specify the chart area and dimensions
var chart = d3.select("#table"+ambit)
.attr("width", spaceForLabels + chartWidth + spaceForLegend)
.attr("height", chartHeight);
// Create bars
var bar = chart.selectAll("g")
.data(zippedData)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" + spaceForLabels + "," + (i * barHeight + gapBetweenGroups * (0.5 + Math.floor(i/data.series.length))) + ")";
});
// Create rectangles of the correct width
bar.append("rect")
.attr("fill", function(d,i) { return color(i % data.series.length); })
.attr("class", "bar")
.attr("width", x)
.attr("height", barHeight - 1);
// Add text label in bar
bar.append("text")
.attr("class", "label_txt1")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) { return d; });
// Draw labels
bar.append("text")
.attr("class", "label_txt")
.attr("x", function(d) { return - 10; })
.attr("y", groupHeight / 2)
.attr("dy", ".35em")
.text(function(d,i) {
if (i % data.series.length === 0)
return data.labels[Math.floor(i/data.series.length)];
else
return ""});
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + spaceForLabels + ", " + -gapBetweenGroups/2 + ")")
.call(yAxis);
</script>
I follow multiple examples to solve this, like: How do I include newlines in labels in D3 charts? and Adding a line break to D3 graph y-axis labels and Wrapping Long Labels.
First attempt:
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');
}
};
chart.selectAll('g.y.axis text').each(insertLinebreaks);
and:
bar.selectAll('.label_txt1').each(insertLinebreaks);
Also I tried:
bar.append("text")
.attr("class", "label_txt1")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) { return d; });
chart.selectAll(".label_txt1").call(wrap, 40)
function wrap(text, width) {
alert(JSON.stringify(text));
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
lineHeight = 1.1, // ems
tspan = text.text(null).append("tspan").attr("x", function(d) { return d.children || d._children ? -10 : 10; }).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
var textWidth = tspan.node().getComputedTextLength();
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
++lineNumber;
tspan = text.append("tspan").attr("x", function(d) { return d.children || d._children ? -10 : 10; }).attr("y", 0).attr("dy", lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
I changed text()
to html()
as I read at: How do I include newlines in labels in D3 charts?
In the browser I see the <text>
created with class label_txt1
. When I try to select the text with selectAll(".label_txt1")
I get the values of the line, not the text.
Can someone help me?