我想以一定的间隔在画布上绘图,但 setTimeout 不起作用

发布于 2024-11-04 02:52:47 字数 631 浏览 2 评论 0原文

这是代码中重要的部分:

function drawCircle(i, color1, color2) {
            var ctx = canvas.getContext("2d");
            if (i % 2 == 1) {
                ctx.fillStyle = color1;
            }
            else {
                ctx.fillStyle = color2;
            }
            ctx.beginPath();
            ctx.arc(110, 270, 10, 0, Math.PI * 2, true);
            ctx.closePath();
            ctx.fill();
        }
for (var i = 0; i < 10; i++) {
    setTimeout(drawCircle(i, color2, color5), 4000);
}

请注意,这只是我在更大的项目中使用与此类似的代码之前想要尝试的一个片段。这无法正常工作,图像仅绘制一次,也就是说,我只看到最后绘制的圆圈。我已经用谷歌搜索了这个,但到目前为止没有任何帮助我。

Here is the part of the code that matters:

function drawCircle(i, color1, color2) {
            var ctx = canvas.getContext("2d");
            if (i % 2 == 1) {
                ctx.fillStyle = color1;
            }
            else {
                ctx.fillStyle = color2;
            }
            ctx.beginPath();
            ctx.arc(110, 270, 10, 0, Math.PI * 2, true);
            ctx.closePath();
            ctx.fill();
        }
for (var i = 0; i < 10; i++) {
    setTimeout(drawCircle(i, color2, color5), 4000);
}

Note that this is just a snippet I wanted to try out before I use code similar to this on a larger project. This isn't working properly, the image is only drawn once, that is, I only see the last circle that is drawn. I have googled this to death but nothing has helped me so far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小巷里的女流氓 2024-11-11 02:52:47

您要使用的是setIntervalsetTimeout 仅触发该事件一次。他们有相同的参数列表。

另外,我认为您使用 setTimeout 的方式不正确。按照您现在编写的方式,该函数在实际将任何内容传递给 setTimeout/setInterval 之前被触发。所以你应该写:

setInterval(function() {              // GOOD. An actual function is passed 
    drawCircle(...);                  // as the first argument.
}, 4000);

or:

setInterval('drawCircle(...)', 4000); // GOOD. the JS statement is supplied as 
                                      // a string and later on will be evaluated 
                                      // and executed with eval().

NOT:

setInterval(drawCircle(...), 4000);   // BAD! drawCircle() is fired, its result 
                                      // evaluated and passed on to setInterval 
                                      // that doesn't know what to do with it.

EDIT

你在 JavaScript 中没有任何阻塞例程。它是一种单线程、事件驱动的语言。如果您调用类似 setInterval 的方法,它会立即成功。仅在 4 秒左右后,您的回调函数才会被调用。然而与此同时,JS 将忙于做各种不同的事情 - 例如对用户生成的其他事件做出反应。您想要做的是调用 setTimeout 一次,然后在回调函数内部,在返回之前使用相同的函数和不同的 i 参数集再次调用它。沿着这些思路:

function drawCircle(i, ...) {

    // ... do stuff ...

    if (i < 10) {                    // Check if the callback has been invoked 10 
                                     // times already.
        setTimeout(function() {      // Schedule the callback for execution
            drawCircle(i + 1, ...);  // again after anoter 4 seconds.
        }, 4000);
    }
}

setTimeout(function() {              // Invoke the callback the first time 
    drawCircle(1, ...);              // after first 4 seconds.
}, 4000);

What you want to use is setInterval. setTimeout just fires the event once. They have the same argument list.

Also I don't think the way you use setTimeout is correct. The way you've written it now, the function is fired before actually passing anything to setTimeout/setInterval. So you should write:

setInterval(function() {              // GOOD. An actual function is passed 
    drawCircle(...);                  // as the first argument.
}, 4000);

or:

setInterval('drawCircle(...)', 4000); // GOOD. the JS statement is supplied as 
                                      // a string and later on will be evaluated 
                                      // and executed with eval().

and NOT:

setInterval(drawCircle(...), 4000);   // BAD! drawCircle() is fired, its result 
                                      // evaluated and passed on to setInterval 
                                      // that doesn't know what to do with it.

EDIT

You don't have any blocking routines in JavaScript. It's a single threaded, event driven language. If you call something like setInterval it succeeds immediately. Only after 4 seconds or so your callback function will be invoked. However in the meantime JS will be busy doing all sort of different stuff - like for example reacting to other events generated by the user. What you want to do is to call setTimeout once and then inside the callback function, just before returning invoke it again with the same function and a different set of arguments of i. Something along these lines:

function drawCircle(i, ...) {

    // ... do stuff ...

    if (i < 10) {                    // Check if the callback has been invoked 10 
                                     // times already.
        setTimeout(function() {      // Schedule the callback for execution
            drawCircle(i + 1, ...);  // again after anoter 4 seconds.
        }, 4000);
    }
}

setTimeout(function() {              // Invoke the callback the first time 
    drawCircle(1, ...);              // after first 4 seconds.
}, 4000);
老街孤人 2024-11-11 02:52:47

实际上有一些因素会导致代码行为不当,而这些因素都与循环的编写方式有关。第一个问题是对 setTimeout 的调用,主要是您没有将函数对象作为第一个参数传递给它,大多数人会通过执行以下操作来解决此问题:

for (var i = 0; i < 10; i++) {
    setTimeout(function() {
        drawCircle(i, color2, color5);
    }, 4000);
}

这将导致 setTimeout 按您的预期延迟,但是它将最终以 10 作为第一个参数调用 drawCircle 10 次,这是因为每次调用都使用对“i”变量的相同引用。在调用之前,不会检索 i 的值...当 i 已经是 10 时,循环完成后 4 秒左右。

为了解决这个问题,您还需要一个函数:

function getDrawer(i, color2, color5) {
    return function() {
        drawCircle(i, color2, color5);
    }
}

for (var i = 0; i < 10; i++) {
    setTimeout(getDrawer(i, color2, color5), 4000);
}

getDrawer (一个可怕的名字,请不要使用't use it) 函数会立即被调用,因此 i 的值会被立即访问并被 getDrawer 返回的匿名函数记住。 setTimeout 将调用该匿名函数。

There are actually a couple of things that are causing your code to misbehave, and they're all in how your loop is written. The first problem is the call to setTimeout, mainly that you're not passing a function object to it as the first argument, and most people would fix that by doing something like this:

for (var i = 0; i < 10; i++) {
    setTimeout(function() {
        drawCircle(i, color2, color5);
    }, 4000);
}

That will cause the setTimeout to delay as you expected, but it will end up calling drawCircle with 10 as the first argument 10 times, and that is because of every call is using the same reference to the "i" variable. The value for i isn't retrieved until the call is made...4 seconds or so after the loop completed when i is already 10.

To get around that, you need one more function:

function getDrawer(i, color2, color5) {
    return function() {
        drawCircle(i, color2, color5);
    }
}

for (var i = 0; i < 10; i++) {
    setTimeout(getDrawer(i, color2, color5), 4000);
}

The getDrawer (a horrible name, please don't use it) function is called immediately, so the value of i is accessed immediately and remembered by the anonymous function that getDrawer returns. That anonymous function is what will be called by setTimeout.

听,心雨的声音 2024-11-11 02:52:47

这里的问题是您连续多次调用 setTimeout,而不是从回调中再次调用它。尝试将对 setTimeout 的调用移至 drawCircle 函数的末尾以查看动画。

The issue here is that you're calling setTimeout several times in a row, rather than calling it again from the callback. Try moving the call to setTimeout to the end of the drawCircle function to see the animation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文