0

我有 25 张图片想要快速显示,有点像没有效果的幻灯片。我的图像被命名为 0 到 26。

我尝试为延迟设置一个 for 循环和一个 setTimeout,但 setTimeout 仅在 for 循环结束时运行,在我的检查点显示 i = 25。

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);            
}

}

我遵循了这个解决方案如何在 JavaScript 循环中添加延迟?

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

它似乎像我想要的那样工作。

4

3 回答 3

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();
于 2013-04-05T01:45:27.120 回答
3

基于以下代码片段:

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

看来您误解了如何setTimeout工作。该setTimeout函数在返回之前不会等待。它立即返回并安排传递给它的代码/函数在以后执行(在您的情况下为 1 秒)。因此,您的循环所做的是创建 25 个 setTimeout,它们在循环执行后一秒钟同时执行。

围绕这个有两种解决方案。一,每晚一秒创建 25 个 setTimeouts:

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

或者以递归方式调用 setTimeout 来处理您的图像列表:

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

foo(24);

第二种形式更为常见。


除了 setTimeout 问题。您还需要阅读闭包在循环中的工作方式,因为在您的循环中,所有 setTimeouts 都将以值执行,i = 24而不是i值 1 到 24。

请参阅:请解释循环中 JavaScript 闭包的使用

于 2013-04-05T02:01:24.123 回答
2

与其使用 setTimeOut 和 for 循环,不如使用 setInterval 像这样...

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);
于 2013-04-05T01:59:37.513 回答