Reputation:
I have an heatmap that shows some data. If user clicks on a label (x
or y
axis), data are correctly sort.
My problem is the correct positioning of the labels before and after the sorting of the data.
This is the PLUNKER.
As you can see, initially the chart is like this:
The labels on the y
axis are correct, those on the x
axis are not, because they should all be at the same height. Instead they come down.
When I click on ddd
it becomes:
Same problem.
when I click on 2001
it becomes:
Now it's all a mess.
The code that controls the positioning of the labels is this:
var rowLabels = svg.append('g')
.attr('class', 'rowLabels')
.selectAll('.rowLabels')
.data(regionsName)
.enter().append('text')
.text(function(d) {
return d;
})
.attr('x', 0)
.attr('y', function(d, i) {
return i * cellSize;
})
.attr('transform', function(d, i) {
return 'translate(-25, 11)';
})
.attr('class', 'rowLabel mono')
.attr('id', function(d) {
return 'rowLabel_' + regionsName.indexOf(d);
})
.attr('font-weight', 'normal')
.on('mouseover', function(d) {
d3.select(this).attr('font-weight', 'bold').style('fill', 'red');
})
.on('mouseout', function(d) {
d3.select(this).attr('font-weight', 'normal').style('fill', 'black');
})
.on('click', function(d, i) {
rowSortOrder = !rowSortOrder;
sortByValues('r', i, rowSortOrder);
});
var colLabels = svg.append('g')
.attr('class', 'colLabels')
.selectAll('.colLabels')
.data(yearsName)
.enter().append('text')
.text(function(d) {
return d;
})
.attr('x', 0)
.attr('y', function(d, i) {
return i * cellSize;
})
.attr('transform', function(d, i) {
return 'translate(0, -3) rotate(-65)';
})
.attr('class', 'colLabel mono')
.attr('id', function(d) {
return 'colLabel_' + yearsName.indexOf(d);
})
.attr('font-weight', 'normal')
.style('text-anchor', 'left')
.attr('dx', '.8em')
.attr('dy', '.5em')
.on('mouseover', function(d) {
d3.select(this).attr('font-weight', 'bold').style('fill', 'red');
})
.on('mouseout', function(d) {
d3.select(this).attr('font-weight', 'normal').style('fill', 'black');
})
.on('click', function(d, i) {
colSortOrder = !colSortOrder;
sortByValues('c', i, colSortOrder);
});
and:
t.selectAll('.colLabel')
.attr('y', function(d, i) {
return sorted.indexOf(i) * cellSize;
})
.attr('transform', function(d, i) {
return 'translate(-10, 2) rotate(-65) rotate(0, 0, ' + (sorted.indexOf(i) * cellSize) + ')';
});
and:
t.selectAll('.rowLabel')
.attr('y', function(d, i) {
return sorted.indexOf(i) * cellSize;
})
.attr('transform', function(d, i) {
return 'translate(-5, 0)';
});
I changed it a thousand times, thinking about it, but nothing. Would anyone know how to help me?
Upvotes: 2
Views: 422
Reputation: 38161
You are over complicating how you set the axis labels. When rotating labels, labels are rotated from the coordinate system origin - not the text anchor. We can see this better if we compare the labels as is and if we remove the transform and just use the x,y attributes you specify:
.attr('x', 0)
.attr('y', function(d, i) {
return i * cellSize;
})
//.attr('transform', function(d, i) {
// return 'translate(-25, 11)';
//})
We can see all labels being rotated together around a common point. A hint that something might be awry in the label placement also comes from the code that dynamically sets a y
value and a fixed x
value for to place values that differ only in x
values.
We can simplify this, instead of setting x, y, and transform, let's just set transform. First we'll modify the coordinate system so that the origin of each labels coordinate system is where it is anchored. Then we'll rotate:
.attr('transform', function(d, i) {
return 'translate('+(i*cellSize)+',2) rotate(-65)';
})
We'll also want to update the update function:
t.selectAll('.colLabel')
.attr('transform', function(d, i) {
return 'translate('+(sorted.indexOf(i)*cellSize)+',2) rotate(-65)';
})
Giving us:
The other issue, the spacing of the y axis labels, you are updating the x position of the labels when you sort. This is un-necessary, the labels only need to move vertically, we can remove the transform change and just use:
t.selectAll('.rowLabel')
.attr('y', function(d, i) {
return sorted.indexOf(i) * cellSize;
})
Here's an updated plunkr.
Upvotes: 1