简体   繁体   中英

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.

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 want, you can use the .each() method paired with d3.select(this) to have more fine-grained control of your selection:

 svg.selectAll('g.data-point')
    .data(dataset)
    .each(function (d) {
      if (d.someCondition == "something") {
        d3.select(this)
        .transition()
        .duration(1000)
        .attr("transform", "translate(100,100)
      }
      else {
        d3.select(this).attr("transform", "translate(100,100)
      }

 })

Obviously, it's a bit more verbose.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM