Pep Pep - 1 month ago 13
Javascript Question

D3.js: Pause button not working (in a callback function used for animation)

I'm trying to add the capability of pausing and resuming to my animation:
enter image description here

It shows the positions of trains (yellow) on a line. My data is nested, where the key is time period. It currently calls

render(t)
function every
interval
milliseconds.
I've read this guide and this question about this, but I'm still lost as to how to apply it to my case.

I'd like to pause the animation, inspect trains attributes, then resume it.
Any help is appreciated!

currentTime = 0;
interval = 100;
var trainsHolder = svg.append('g')

function render(t){

trains = trainsHolder
.selectAll('circle')
.data(nested_train_data[t], function(d){ return d.car_id})

// enter
trains
.enter()
.append("circle")
.each(setAttributes)

// update
trains
.transition()
.duration(interval)
.each(setAttributes)

// exit
trains.exit().remove();

// update timer
timer_holder
.select("text")
.transition()
.duration(interval)
// .text("Time : " + String(t/60))
.text(String(nested_train_data[t][0].Date.getHours()) + ":" + String( nested_train_data[t][0].Date.getMinutes()))

};

render(currentTime);

var callback = function () {
return function () {
// my time increments are 60 seconds

currentTime = currentTime + 60;
// console.log(currentTime);
if (currentTime <= maxTime) {
render(currentTime);
d3.timer(callback(), interval);
}
return true;
}
}



d3.timer(callback(), interval);
// NOT WORKING
$("#pauseBtn").click(function() {
trainsHolder.selectAll('circle').transition().duration( 0 );
});

Answer

Taking "pause" out of the picture, does the animation run properly? If so, the issue appears to be with your callback function. That is what drives the animation.

You want something like the following. The basic idea is that you only advance the animation timer if and only if the simulation is not paused and hasn't exceeded the maxTime:

return function(elapsed) {
    paused = getPausedState();
    //use the elapsed time to set instead of a fixed interval, so the animation plays at a constant rate
    //only advance the animation timer if the simulation is not paused
    //and we haven't exceeded the max
    nextTime = paused || currentTime > maxTime ? currentTime : currentTime + elapsed;
    render(nextTime);
    d3.timer(callback(), interval);
Comments