简体   繁体   中英

Transitions with circles in D3

I have set up a D3 circle animation with a transition. I'm using the min date as the initial data point and the max date as the final data point for the transition. My questions is:

I'm using a rather large dataset, I'm afraid that since I'm only telling the transition to go from min to max, it will miss all the other points in between, for example what if circle A has a crazy jump in between? When I tested it out, it seemed as if it had just skipped the jump.

Is there a better way to set the transition to account for all the points in between?

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).

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