0

The Situation

I have a function which is called on button click and which should draw an animated chart, updating the chart every 2 seconds. When the user clicks that button again, while the animation is still running, the animation should stop.

My current solution

Right now I have the following script which stops the animation visually, but the underlying for-loop continues until the end in the background:

var animRun = false;
$("#animateButton").on("click", function() {
    if (animRun === false) {
        redraw(data.slice(0,30))
        //some CSS...

    } else {
        //Some CSS...
        animRun = false;
    }
});

function redraw(data) {
    animRun = true;

    for (var i=0; i<data.length;i++){

        (function(i){
            setTimeout(function(){
                if(animRun === true) {
                    //draw the chart
                    return draw(data[i])
                }
            },2000*(i))

            if (i === data.length -1) {
                //reset animRun
                if(animRun === true) {
                     //Some CSS things
                     //...
                     animRun = false;
                 }
            }
        })(i);
    }


}

Question

What would be the correct way of stopping the for-loop when the user clicks the button again while the animation is still executing?

5
  • 1
    developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented May 22, 2019 at 3:43
  • So it is not possible? What could be a workaround? Commented May 22, 2019 at 3:49
  • Almost: developer.mozilla.org/en-US/docs/Web/API/Animation Commented May 22, 2019 at 3:53
  • The animation I use is made with the d3.js library... In my case I actually stop the animation because the variable animRun is set to false on the second click, thus the draw() function is not executed Commented May 22, 2019 at 3:54
  • In all seriousness, with some significant rewrite, you should employ requestAnimationFrame for this purpose. Commented May 22, 2019 at 3:57

1 Answer 1

1

Did you try clearTimeout. Store your draw timeout to an array, and stop it when you done

var animRun = false;
var drawArr = [];
$("#animateButton").on("click", function() {
    if (animRun === false) {
        redraw(data.slice(0,30))
        //some CSS...

    } else {
        //Some CSS...
        animRun = false;

        drawArr.forEach(d=>clearTimeout(d));
    }
});

function redraw(data) {
    animRun = true;

    for (var i=0; i<data.length;i++){

        (function(i){
            drawArr[i] = setTimeout(function(){
                if(animRun === true) {
                    //draw the chart
                    return draw(data[i])
                }
            },2000*(i))

            if (i === data.length -1) {
                //reset animRun
                if(animRun === true) {
                     //Some CSS things
                     //...
                     animRun = false;
                 }
            }
        })(i);
    }


}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! This worked like a charm! I just don't get why it should be a list. because the list is filled after each iteration, isn't it? So if the user stops the animation after the first run of draw() there is only one element in drawArr. How is it that it clears all following iterations as well?
Just reinit that array when you click start again drawArr = []

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.