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 秒)。したがって、ループが行うことは、ループが実行されてから 1 秒後にすべて同時に実行される 25 個の setTimeouts を作成することです。

これには 2 つの解決策があります。1 つは、1 秒ごとに 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);

2 番目の形式がより一般的です。


setTimeout の問題に加えて。また、ループ内ですべての setTimeouts が1 から 24 の値ではi = 24なく の値で実行されるため、ループ内でクロージャがどのように機能するかを読む必要があります。i

参照:ループでの 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 に答える