Sneaky Wombat
Sneaky Wombat

Reputation: 1848

transitioning multiple elements with d3

I'm having a heck of a time with transitions in D3js. I posted a fiddle here: dynamic area graph. The problem that I run into is that when trying to follow this tutorial path transitions, I run into sync problems with the xAxis. Bostock indicates that the domain should be skewed slightly so that the data appears to "shift" in from the side. However, when I do that, the data reflected will be listed under a tick mark that is "2 minutes" behind the actual time it should be listed. If I just update the data as-is, without doing the tricky stuff with the clip-path, it works fine. All of the data is in sync. Just for reference, the xAxis is an integer, linear scale. Dealing with date strings was madding, even though d3 has great time manipulation, I just find dealing with epoch easier. If someone could check out the fiddle and let me know how to transition the entire drawing...I want it to be smooth like in the examples that bostock has.

Since SO requires some code, here's the data structure that I'm generating. The rest is in the fiddle:

    setInterval(function(){
  lastTime = lastTime.add('m',1);
  var data = {"apikey":"FOO",
    "description":"a dumb description",
    "beg_effective_dt_tm":lastTime,
    "data":{
      "sum":getRandomInt(385,4000),
      }
    };
    tick(data);
},1000)

Upvotes: 2

Views: 1045

Answers (1)

musically_ut
musically_ut

Reputation: 34288

I think this is close to what you are after: http://jsfiddle.net/JJ7Rj/1/ It is close because the graph is delayed by one value.

Most of the architecture was already there, and your concern that you might lose the sync between the xAxis and the data was correct. Mike gets around it by changing his range of the scales. The other (and better, IMO) way is to do it by changing the domains. I made the following two primary changes.

The domain of the axis

I have modified the minMax function such that it does not include the latest and the last point in the domain of the xAxis. Note that this means that the most recent value (as well as the oldest value) is actually displayed outside the visible region. This is an unfortunate limitation of using the monotone interpolation, which Mike talks about at the bottom of his post.

function minMax(pd) {
  return [
      d3.min(pd.slice(1).slice(0, -1),function(d){ return d.beg_effective_dt_tm; }),
      d3.max(pd.slice(1).slice(0, -1),function(d){ return d.beg_effective_dt_tm; })
    ];
}

If you want to have all the values visible, then you'll get the wiggling effect of the discontinuous tangent suddenly forming when the new value comes in. You can obtain that by removing the .slice(0, -1).

The initial transform

For each element, I have initially placed the DOM element one step to the right.

var step = x(newVal.beg_effective_dt_tm) - x(pd[pd.length - 1].beg_effective_dt_tm);
// ...
           .attr("transform", 'translate(' + step + ')');
// ...

Then finally, I have transitioned everything back to their rightful place:

    clipPath.selectAll("path,circle,.dp").transition()
      .ease("linear")
      .attr("transform", "translate(" + 0 + ",0)");

Also, I have enabled the transition for the xAxis.

Upvotes: 1

Related Questions