最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Trying to loop through images with a delay in canvas - Stack Overflow

programmeradmin1浏览0评论

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.

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.

Share Improve this question edited May 23, 2017 at 12:14 CommunityBot 11 silver badge asked Apr 5, 2013 at 1:31 BatmanBatman 6,39322 gold badges88 silver badges161 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4
//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();

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


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

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);
发布评论

评论列表(0)

  1. 暂无评论