Reputation: 1712
In my transition, an axis rotates 90 degree and then the labels rotate in the opposition direction in order to remain upright. Below is a minimal example of what I want, except the transition is not as smooth as it could be. If you watch closely, you can see the labels shift (translate) up before rotating into place. How can I get rid of this shift? I've fiddled with rotate
and translate
to no avail.
(If you think this isn't too bad, I agree, but the shift is actually significantly more noticeable in my actual plot for some reason.)
Update. The culprit is the text-anchor
property's getting switched back and forth between middle
and start
. Since these are discrete values, I can't think of a simple way to transition between them.
var width = 170;
var scale = d3.scaleLinear().domain([0, 5])
.range([0, width]);
var axis = d3.axisBottom()
.scale(scale)
.ticks(6);
var graph = d3.select('svg').append('g')
.attr('transform', 'translate(10,10)');
graph.append('g')
.attr('transform', 'translate(0,' + width + ')')
.call(axis);
var tickLabels = d3.selectAll('text');
var toggle = false;
d3.select('button').on('click', function() {
toggle = !toggle;
if (toggle) {
graph.transition().duration(1000)
// .attr('transform','rotate(-90)');
.attr('transform', 'rotate(-90 ' + (width / 2 + 10) + ' ' + (width / 2 + 10) + ')');
tickLabels.transition().duration(1500).delay(1000)
.attr("y", 0)
.attr("x", 9)
.attr("dy", ".3em")
.attr("transform", "rotate(90)")
.style("text-anchor", "start");
} else {
graph.transition().duration(1000)
.attr('transform', 'rotate(0) translate(10,10)');
tickLabels.transition().duration(1500).delay(1000)
.attr('y', 9)
.attr('x', 0.5)
.attr('dy', '0.71em')
.attr('transform', 'rotate(0)')
.style('text-anchor', null);
}
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='200' height='200'>
</svg>
<div>
<button>Rotate</button>
</div>
Upvotes: 1
Views: 633
Reputation: 1712
Found the solution, which is actually fairly simple. The key is to alter the x
attribute to offset the text-anchor
shift before rotating the labels. The result is actually quite nice.
var width = 170;
var scale = d3.scaleLinear().domain([0, 5])
.range([0, width]);
var axis = d3.axisBottom()
.scale(scale)
.ticks(6);
var graph = d3.select('svg').append('g')
.attr('transform', 'translate(10,10)');
graph.append('g')
.attr('transform', 'translate(0,' + width + ')')
.call(axis);
var tickLabels = d3.selectAll('text');
var toggle = false;
d3.select('button').on('click', function() {
toggle = !toggle;
if (toggle) {
graph.transition().duration(1000)
// .attr('transform','rotate(-90)');
.attr('transform', 'rotate(-90 ' + (width / 2 + 10) + ' ' + (width / 2 + 10) + ')');
tickLabels.transition().duration(0).delay(1000)
.attr('x', -3)
.style("text-anchor", "start")
.transition().duration(1000)
.attr("y", 0)
.attr("x", 9)
.attr("dy", ".3em")
.attr("transform", "rotate(90)");
} else {
graph.transition().duration(1000)
.attr('transform', 'rotate(0) translate(10,10)');
tickLabels.transition().duration(0).delay(1000)
.attr('x', 12)
.style('text-anchor', null)
.transition().duration(1000)
.attr('y', 9)
.attr('x', 0.5)
.attr('dy', '0.71em')
.attr('transform', 'rotate(0)');
}
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='200' height='200'>
</svg>
<div>
<button>Rotate</button>
</div>
Upvotes: 1