HTML5/Javascript 超时未完成函数



我制作了一个循环函数来慢慢淡化图像。

var ctx; // this is the canvas already defined
function nextPic(i)
    {
        trans = 1; //resets transparent var to 1
        fadeloop('out'); //starts loop
        ctx.clearRect(0, 0, canvas.width, canvas.height); //clears canvas, this doesn't work
        alert("done"); //this doesn't work either
    }
    function fadeloop(f){ //loop that fades
        if(f == 'out'){ //make sure it wants to shade out
            setTimeout(function () { //timed delay for fading out
                fadeImgOut(); //calls function to fade out by .01
                if(trans>0.0){ //if faded out break out of loop
                    fadeloop('out'); //if not restart function
                }
            },10);
        }
    }
    function fadeImgOut(){ //function that fades out
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(img,0,0);
        ctx.globalAlpha = trans;
        trans = trans - .01;
    }

按钮调用nextpic。它会慢慢地使图像透明,然后在另一个图像中褪色。现在它将图像淡出,直到trans=.01。不继续警报("完成")或画布重置。任何想法我都看了一遍又一遍,不知道该怎么办。

我用类似的函数进行了测试。代码为:


    var j = 100;
    (function(){
        a();  // step 1;
        alert("hello world!"); // step 3; Fired without almost no time delay.
    })()
    function a(){
        setTimeout(function(){
           b();
           if(j>1){
              a();
           }
        }, 10); // step 2;  push the callback into a queue, and a() ends. 
    }
    function b(){
        if(j > 1){
            j--;
        }
    }

结果是:立即触发警报,没有任何延迟。结果是正确的。

因为setTimeout是异步函数。这意味着当第一次执行a()时,setTimeout中的回调函数将被推送到等待触发的队列中。然后触发expression function中的alert()。

我不知道你为什么不发出警报。可能出现了一些错误。

这可能不能解决您的问题,但可能会稍微简化它。

您正在递归地使用fadeloop,但您可以简单地通过while循环来实现这一点,这使得跟踪/调试更加容易。不必弄清楚递归的深度。

我唯一能想到的问题是setTimeout是否有setTimeout(函数,时间)的方法签名?其他一切看起来都是正确的。

trinity的答案是正确的,尽管没有触发警报听起来像是有其他错误干扰了发布的代码。FWIW,这里有一个包含代码的最小页面,它证明了它是按描述工作的:

<!doctype html>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = nextPic;
img.src = 'http://cdn.sstatic.net/careers/ads/img/careers2-ad-header-so-crop.png';
function nextPic(i) {
  trans = 1; //resets transparent var to 1
  fadeloop('out'); //starts loop
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  alert("done");
}
function fadeloop(f){ //loop that fades
  if(f == 'out'){ //make sure it wants to shade out
    setTimeout(function () { //timed delay for fading out
      fadeImgOut(); //calls function to fade out by .01
      if(trans>0.0){ //if faded out break out of loop
        fadeloop('out'); //if not restart function
      }
    },10);
  }
}
function fadeImgOut(){ //function that fades out
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(img,0,0);
  ctx.globalAlpha = trans;
  trans = trans - .01;
}
</script>

请注意,按照你的排序方式(你在绘图后从trans中减去,然后检查是否应该重复循环),你会在.01附近结束,这是正确的。您需要重新排序以确保达到0。

还要小心重复的浮点减法:你没有达到你认为的值(这个循环永远不会达到0)。一个非常小的变化会让你开始纠正它(这假设你的图像已经画过一次,所以在调用fadeImgOut之前可以从trans中减去):

function fadeloop(f){ //loop that fades
  if(f == 'out'){ //make sure it wants to shade out
    setTimeout(function () { //timed delay for fading out
      trans = Math.max(0, trans - .01);
      fadeImgOut(); //calls function to fade out by .01
      if(trans>0.0){ //if faded out break out of loop
        fadeloop('out'); //if not restart function
      }
    },10);
  }
}
function fadeImgOut(){ //function that fades out
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.globalAlpha = trans;
  ctx.drawImage(img,0,0);
}

最新更新