Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 Optional Transitions

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?

EDIT:

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.

like image 261
Nathan Rutman Avatar asked Mar 16 '26 17:03

Nathan Rutman


2 Answers

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(/* .. */);
like image 97
musically_ut Avatar answered Mar 18 '26 07:03

musically_ut


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)
like image 40
Adam Pearce Avatar answered Mar 18 '26 05:03

Adam Pearce



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!