Batman
Batman

Reputation: 6353

Trying to loop through images with a delay in canvas

I have 25 images I want to show really quickly, kinda like a slideshow without effects. My images are named 0 to 26.

I've tried setting a for loop and a setTimeout for the delay but the setTimeout runs only at the end of the for loop showing i = 25 at my Checkpoint.

JS:

function startAnimation(){
for(var i=0; i<25; i++){
    setTimeout(function(){
       img = new Image();
       img.src = 'images/canvas/'+[i]+'.jpg';
       img.onload = function(){ctx.drawImage(img,0,0, 850,194)} 

       alert('CP. In setTimeout. i= '+i);
    },1000);
    ctx.clearRect(0,0,canvas.width, canvas.height); //clear image after 1 sec, loop to show next.
    alert('CP outside. i = '+i);            
}

}

I followed this solution How do I add a delay in a JavaScript loop?:

function startAnimation(){
    setTimeout(function(){
        img = new Image();
        img.src = 'images/canvas/'+[counter]+'.jpg';
        img.onload = function(){ctx.drawImage(img,0,0, canvas.width,canvas.height)};
        counter++;
        if(counter<26){
            startAnimation();
        }
    },150)
}

It seems to be working like I want it to.

Upvotes: 0

Views: 2625

Answers (3)

Givi
Givi

Reputation: 1734

Instead of using setTimeOut and for loop, it would be better if you use setInterval Like so...

var i = 0,
    img;

function startAnimation() {
    if (i >= 24) {
        clearInterval(timer); // or i = 0;
    }
    i++;
    img = new Image();
    img.src = 'images/canvas/' + [i] + '.jpg';
    img.onload = function () {
        ctx.drawImage(img, 0, 0, 850, 194);
    };

    alert('CP. In setTimeout. i= ' + i);

    ctx.clearRect(0, 0, canvas.width, canvas.height); //clear image after 1 sec, loop to show next.
    alert('CP outside. i = ' + i);
}

var timer = setInterval(startAnimation, 1000);

Upvotes: 2

Joseph
Joseph

Reputation: 119837

//preload your images into an array first for smoother animation

function getImages(callback) {

  var imgs = [],
    loaded = 0,
    length = 25,
    i;

  for (i = 0; i < length; i++) {
    (function (i) {
      //create image
      var img = new Image();
      //set a callbacl
      img.onload = function () {
        //add to array
        imgs[i] = img;
        //increment loaded count
        loaded++;
        //if we loaded all of them, call the callback passing in the images
        if (loaded === length) callback(imgs);
      }
      //load
      img.src = 'images/canvas/' + [i] + '.jpg';
    }(i));
  }
}

function startAnimation(i) {

  //get all images
  getImages(function (imgs) {

    var i = 0;

    //run through ueach in an interval
    var animationInterval = setInterval(function () {

      ctx.clearRect(0, 0, canvas.width, canvas.height);

      if (i < imgs.length) {
        ctx.drawImage(img[i++], 0, 0, 850, 194)
      } else {
        clearInterval(animationInterval);
      }

    }, 1000);

  });
}

//call
startAnimation();

Upvotes: 4

slebetman
slebetman

Reputation: 113866

Based on the following snippet of code:

//clear image after 1 sec, loop to show next.

It appears that you have misunderstood how setTimeout works. The setTimeout function does not wait before returning. It returns immediately and schedules the code/function passed to it to execute at a later time (1 second in your case). So what your loop does is to create 25 setTimeouts that all simultaneously execute one second after the loop is executed.

There are two solutions around this. One, to create 25 setTimeouts each one second later than the other:

for(var i=0; i<25; i++){
    setTimeout(function(){/* ... */}, 1000 * i);
}

Alternatively to call setTimeout recursively to process your image list:

function foo (i) {
    /* ... */
    if (i >= 0) {
        setTimeout(foo(i-1),1000);
   }
}

foo(24);

The second form is more common.


In addition to the setTimeout issue. You also need to read up on how closures work inside loops because in your loop all the setTimeouts will execute with the value of i = 24 instead of i being the values 1 to 24.

See: Please explain the use of JavaScript closures in loops

Upvotes: 3

Related Questions