javascript - I want to draw on a canvas with a certain interval and setTimeout isn't working - Stack Overflow

Here is the part of the code that matters:function drawCircle(i, color1, color2) {var ctx = canvas.getC

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.

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.

Share Improve this question asked May 1, 2011 at 17:53 AsgeirAsgeir 7573 gold badges9 silver badges21 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

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

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 pleted 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.

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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744194734a4562600.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信