I have a D3 chart that transitions plot points. Sometimes I want these to be animated transitions, and sometimes I want them to be instantaneous. Is there a DRY way to do this kind of stuff in D3?
For example:
svg.selectAll('g.data-point')
.data(dataset)
.transition()
.duration(transitionTime)
.attr({
class: function(d) {
return getClassesForPoint(d);
},
transform: function(d) {
return ('translate(' + ((d.x) ? xScale(d.x) : xScale(0)) + ', ' + yScale(d.y) + ')');
}
});
If I only want to do the animated transition based on a condition, do I need to repeat that block without lines 3-4 via an if-else structure, or is there a better way to do that? The chaining is throwing me a bit. I've already tried giving it a duration of 0 and it still goes through the animation engine.
Any thoughts?
Turns out my selector was defunct and, as Lars mentioned, using duration(0) works fine. However, I have come across this kind of situation a couple of different times, where it seems like there's enough commonality in two chains, but I can't figure out how to properly or dynamically add / remove calls to the chain.
Since the transition object supports most of the methods supported by the selection object (except functions like append), you can conditionally choose one of those to operate on:
var selection = svg.selectAll('g.data-point').data(dataset).enter();
if (condition) { selection = selection.transition().duration(transitionTime); }
selection.attr(/* .. */);
I would use .call:
function transformationAndSetClass(selection){
selection.attr({
class: function(d) {
return getClassesForPoint(d);
},
transform: function(d) {
return ('translate(' + xScale(d.x ? d.x : 0) + ', ' + yScale(d.y) + ')');
}
});
}
Then, when you need to reuse those lines of code:
svg.selectAll('g.data-point')
.data(dataset)
.transition()
.duration(transitionTime)
.call(transformationAndSetClass)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With