Reputation: 3706
Can someone please help me here with centering the wrapped text value on the bar. Right now the first line is centered but all new appended lines are below it. Is there a way to re-center it after they were wrapped?
http://jsbin.com/qajejahiqi/edit?js,output
Thanks!
Upvotes: 0
Views: 142
Reputation: 102194
Using a ternary operator, change the y
position of your labels according to the length of the text:
.attr("y", function(d){
return d.month.length > 50 ? y(d.month) + 8 : y(d.month) + (y.rangeBand() / 2);
})
I don't like to use magic numbers, this is just an example for you to see how to create your actual function, in which you can change the magic numbers I'm using here for computed positions.
The logic of this ternary operator is quite simple. First, we get the length of the text:
d.month.length > 50
You can change 50
for any computed value, according to your left margin and the font size. If the text is bigger than that, you set the y
position:
y(d.month) + 8
Again, 8
is just a magic number here, you have to create a function to calculate the adequate number according to the width of the bars, size of the texts etc...
Also, if you have different numbers of lines, you can concatenate several ternary operators:
condition1 ? actionA : condition2 ? actionB : condition3? actionC : actionD;
If condition1
is true, actionA
is done. If it's false, condition2
is evaluated. If it's true, actionB
is done, if it's false, condition3
is evaluated, and so on...
Check the demo:
var temperatures = [
{temp: 32, month: 'January is really a long month.', color: 0},
{temp: 38, month: 'February is really a cold month.', color: 1},
{temp: 47, month: 'March, i dont know what to think', color: 1},
{temp: 59, month: 'April. What if I wanted to test a really long string here that will span.', color: 2},
{temp: 70, month: 'May', color: 2},
{temp: 80, month: 'June', color: 2},
{temp: 90, month: 'July', color: 2},
{temp: 83, month: 'Auguest', color: 0},
{temp: 76, month: 'September', color: 3},
{temp: 64, month: 'October', color: 4},
{temp: 49, month: 'November', color: 4},
{temp: 37, month: 'December', color: 4}
];
var margin = {top: 5, right: 60, bottom: 50, left: 150},
width = 700 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var y = d3.scale.ordinal()
.domain(temperatures.map(function (d) { return d.month; }))
.rangeBands([0, height], 0.1, 0.35);
var x = d3.scale.linear()
.domain([0, d3.max(temperatures, function(d){return d.temp;})])
.range([0, width]);
var color = d3.scale.category20c();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.innerTickSize(-(height-5))
var barChart = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
barChart.selectAll("#bar")
.data(temperatures)
.enter().append("rect")
.attr("id", "bar")
.attr("x", 0)
.attr("width", function(d){return x(d.temp);})
.attr("y", function (d) { return y(d.month); })
.attr("fill", function(d){ return color(d.color); })
.attr("height", y.rangeBand())
.on("mouseover", function(){
d3.select(this).attr("fill", "red");
})
.on("mouseout", function(){
d3.select(this).attr("fill", function(d) { return color(d.color); });
});
barChart.append("g")
.attr("class", "x axisHorizontal")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.style("text-anchor", "end")
.attr("x", width - 3)
.attr("y", -5)
.text("Label")
barChart.append("g")
.selectAll("axisLabels")
.data(temperatures)
.enter()
.append("text")
.attr("x", 0)
.attr("y", function(d){return d.month.length > 50 ? y(d.month) + 8 : y(d.month) + (y.rangeBand() / 2);})
.attr("text-anchor", "end")
.attr("dy", ".35em")
.attr("dx", -5)
.text(function(d){return d.month;})
.call(wrap, margin.left);
barChart.append("g")
.selectAll("valueLabels")
.data(temperatures)
.enter()
.append("text")
.attr("x", function(d){return x(d.temp);})
.attr("y", function(d){return y(d.month) + (y.rangeBand() / 2);})
.attr("dx", 5)
.attr("dy", ".35em")
.text(function(d){return d.temp;})
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("dx", -5).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("dx", -5).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
body {
font: 10px Arial;
}
.axis path {
fill: none;
stroke: grey;
shape-rendering: crispEdges;
}
.axis text {
font-family: Arial;
font-size: 10px;
}
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
svg{
display: block;
margin: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Upvotes: 1