I have a visualization that normally animates (using transition()) when the document resizes but whenever the user prints the visualization, I'd like to be able to set the dimensions of the visualization immediately by setting .duration(0) when the window.matchMedia('print') event fires. However, because the update doesn't happen immediately (in the current JS execution cycle) the resize never makes it to the printed rendering of the document.
Here's a quick little demo that shows the current behavior:
var body = d3.select('body')
.style('background-color', 'blue')
.style('width', '100%')
.style('height', '100%')
.transition()
.duration(0)
.style('background-color', 'green');
alert('test'); // => body background color is still blue (would like this to already be green.)
setTimeout(function(){ alert('test'); }); // body background color is now green.
It wasn't too hard to come up with a workaround for now but I wanted to see what others think about this proposed behavior and if it sounded desirable, I'd be happy to submit a diff.
The workaround:
function transition(sel) {
if(shouldTransition) return sel.transition();
return sel;
}
Duplicate of #48. The solution is to call d3.timer.flush() after any zero-duration transitions to flush the timer queue synchronously.
Another related technique is to use d3.transition(selection):
function changeBackground(color) {
d3.transition(d3.select("body")).style("background-color", color);
}
// Set background color to green, immediately.
changeBackground("green");
// Fade background to red.
d3.transition().each(function() {
changeBackground("red");
});
@jasondavies, sorry, can't find any example on this. Should i do is as follows?
myCircles.transition()
.duration(playing?500:0)
.ease("linear")
// if playing is true, these should animate
// if playing is false, these should not animate
.attr("cy", function(d) { return d.y; })
.attr("cx", function(d) { return d.x; })
.attr("r", function(d) { return d.r; });
d3.timer.flush();
Thanks!
Yes.
Most helpful comment
Yes.