使用setTimeout在画布中设置动画的问题

时间:2014-11-29 04:52:28

标签: javascript html5 animation canvas settimeout

我试图为重复出现的垂直行设置动画,一次一行。每行圆圈从浏览器底部开始,然后转到顶部。但是,我一直无法使用setTimeout来保持重复,一次只有一个新的圆圈。我当前的代码具有重复的圆圈,但每次都会添加额外的圆圈,并且每次都会加速动画。如何避免加速并添加额外的圆圈?

这里是fiddle

var newLine = function(){
        var posX = Math.random() * canvas.width;
            posY = canvas.height;

        setInterval(function() {
            posY -= 40;

            c.fillStyle = "rgba(23, 23, 23, 0.05)";
            c.fillRect(0, 0, canvas.width, canvas.height);

            c.fillStyle = "white";
            c.beginPath();
            c.arc(posX, posY, Math.random() * 20, 0, twoPi, false);
            c.fill();

        }, 30);
        setTimeout(newLine, 2000);
    };  
    newLine();

1 个答案:

答案 0 :(得分:3)

问题在于每次调用newLine()时都会创建一个新的间隔计时器。因此,在多次调用该函数后,您可以同时运行多个间隔计时器。

修复只是在开始新的间隔计时器之前清除间隔计时器:

    var timer;

    var newLine = function(){
        clearInterval( timer );
        var posX = Math.random() * canvas.width;
            posY = canvas.height;

        timer = setInterval(function() {
            posY -= 40;

            c.fillStyle = "rgba(23, 23, 23, 0.05)";
            c.fillRect(0, 0, canvas.width, canvas.height);

            c.fillStyle = "white";
            c.beginPath();
            c.arc(posX, posY, Math.random() * 20, 0, twoPi, false);
            c.fill();

        }, 30);
        setTimeout(newLine, 2000);
    };  
    newLine();

Updated fiddle

关于评论中的问题...您遇到的一个问题是一个非常微妙的JavaScript陷阱。在做一些调试之前我没有注意到它。

仔细看看这些行:

        var posX = Math.random() * canvas.width;
            posY = canvas.height;

现在问问自己这些问题:posX是一个局部变量吗? posY是局部变量吗?你确定它们都是局部变量吗?

如果您在测试中看到一些结果,其中两个或更多线动画以锁定步进向上移动,这将解释原因。

问题的另一部分很简单。忽略我之前关于将timer变量移到newLine()函数之外的建议,以便取消它!相反,在timer中使newLine()成为本地变量,并在完成后让newLine()的每个实例取消自己的计时器。

一旦这样做,其余代码就可以正常工作:

    var newLine = function(){
        var posX = Math.random() * canvas.width;
        var posY = canvas.height;

        var timer = setInterval(function() {
            posY -= 10;
            if( posY <= 0 ) {
                clearInterval( timer );
                return;
            }

            c.fillStyle = "rgba(23, 23, 23, 0.05)";
            c.fillRect(0, 0, canvas.width, canvas.height);

            c.fillStyle = "white";
            c.beginPath();
            c.arc(posX, posY, Math.random() * 5, 0, twoPi, false);
            c.fill();

        }, 30);

        setTimeout( newLine, Math.random() * 2000 );
    };

    newLine();

New fiddle