score:2

Accepted answer

If you tell the object to translate from min to max it will only respect those two values and as you said it will skip any funny jumps in between.

I guess you currently draw the chart once by pushing in all the data. Instead you could push the data to the chart step by step:

var data = [{id: o1, v: []}, {id: o2, v: []}]; // values for 2 objects

function getTransform(d) {
    return "translate(" + d.v[d.v.length-1] + ")";
}

function update() {
  var elems = d3.selectAll(...).data(data, function(d) {return d.id;})
  elems.enter()
      .append(...) //append DOM/SVG objects and
      .attr(...)   //initalize their start values and
      .attr("transform", getTransform )  //their start animation values

  // animate the existing elements to move to their new values
  elems.transition().attr("transform", getTransform )
}

function play(){
    // pushing in "crazy" values
    data[0].v.push( Math.random()*10 );
    data[1].v.push( Math.random()*10 );
    update();
}

setTimeout(play, 500)
setTimeout(play, 1000)
setTimeout(play, 1500)

The basic idea is to not throw all data at d3 at once, but add the data in the order and timeliness that you want it to be animated.

In addition, or alternatively you could set a time index and use it in the getTransform function to animate to any state you want. If you do this step by step, you make the animation use your "crazy" values.

var time = 0;
var maxTime = 2;

function getTransform(d) {
    return "translate(" + d.v[time] + ")";
}

function next(){
    update();
    if(time++ < maxTime) setTimeout(next, 500)
}

play(); play(); play(); // add some data ;)
next()   // start index based playback from `time` to `maxTime`

You may need to match the timeout value 500 with your desired animation duration(..) speed to make the animation hit your crazy spikes. Otherwise d3 might smooth the animation path (if you update faster than you animate).


Related Query