Smajl
Smajl

Reputation: 8015

jQuery setInterval in for loop

I am trying to create an application in jQuery (I am new to in this) where circles appear randomly in canvas every second. I generate them in a for loop but dont know how to make them appear after some elapsed time. I tried using setInterval() and delay() but it didnt work (I think my syntax wasnt well written). Sorry if this question is too basic.

Here is my code:

var canvas, ctx;
var circles = [];
var selectedCircle;
var hoveredCircle;

function Circle(x, y, radius){
    this.x = x;
    this.y = y;
    this.radius = radius;
}

function clear() { // clear canvas function
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}

function drawCircle(ctx, x, y, radius) { // draw circle function
    ctx.fillStyle = 'rgba(255, 35, 55, 1.0)';
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fill();
}

$(function(){
    canvas = document.getElementById('scene');
    ctx = canvas.getContext('2d');

    var circleRadius = 15;
    var width = canvas.width;
    var height = canvas.height;

    var circlesCount = 60; // we will draw 60 circles randomly
    for (var i=0; i<circlesCount; i++) {
        var x = Math.random()*width;
        var y = Math.random()*height;    
        circles.push(new Circle(x,y,circleRadius));
        drawCircle(ctx, circles[i].x, circles[i].y, circleRadius);
    }
});

Thanks for any help!

EDIT: Here are few examples that didnt work:

delay(1000) // after drawing function
drawCircle(ctx, circles[i].x, circles[i].y, circleRadius).delay(1000);
setInterval(drawCircle(ctx, circles[i].x, circles[i].y, circleRadius) {
}, 2000);
drawCircle(ctx, circles[i].x, circles[i].y, circleRadius).delay(1000).setInterval(1000);

Upvotes: 0

Views: 2864

Answers (3)

jfriend00
jfriend00

Reputation: 708036

You need to restructure your code (can't use a for loop) so that each circle can be drawn from the setInterval() callback function like this:

$(function(){
    canvas = document.getElementById('scene');
    ctx = canvas.getContext('2d');

    var circlesCount = 60; // we will draw 60 circles randomly
    var circleRadius = 15;
    var width = canvas.width;
    var height = canvas.height;

    function makeCircle() {
        var x = Math.random()*width;
        var y = Math.random()*height;    
        var c = new Circle(x,y,circleRadius);
        circles.push(c);
        drawCircle(ctx, c.x, c.y, circleRadius);
        if (circles.length >= circlesCount) {
            clearInterval(interval);
        }
    }

    var interval = setInterval(makeCircle, 1000);
    makeCircle();
});

The amount of delay time goes as the second argument to setInterval(). I've made it 1000ms here (1 second), but you can use any value you want. If you want the delay time to be random, then you would use repeated calls to setTimeout() instead of setInterval() and you would generate a random amount of time for each setInterval() call.

A random integer number between two values can be generated like this:

function randomBetween(low, high) {
    return (Math.floor(Math.random() * (high - low)) + low);
}

So, if you wanted circles to appear at random times between 100ms and 1000ms, then your code would look like this:

$(function(){
    canvas = document.getElementById('scene');
    ctx = canvas.getContext('2d');

    var circlesCount = 60; // we will draw 60 circles randomly
    var circleRadius = 15;
    var width = canvas.width;
    var height = canvas.height;

    function makeCircle() {
        var x = Math.random()*width;
        var y = Math.random()*height;    
        var c = new Circle(x,y,circleRadius);
        circles.push(c);
        drawCircle(ctx, c.x, c.y, circleRadius);
        if (circles.length < circlesCount) {
            setTimeout(makeCircle, randomBetween(100, 1000));
        }
    }

    makeCircle();
});

Note: in both code blocks, I restructured how you keep track of the number of circles by just looking at circles.length since it's a natural, pre-existing counter of how many circles you have created.

Upvotes: 2

phnkha
phnkha

Reputation: 7892

Try below solution. Read the comment for more details

$(function(){
    canvas = document.getElementById('scene');
    ctx = canvas.getContext('2d');

    var circleRadius = 15;
    var width = canvas.width;
    var height = canvas.height;
    var timer, index = 0;

    var circlesCount = 60; // we will draw 60 circles randomly
    for (var i=0; i<circlesCount; i++) {
        var x = Math.random()*width;
        var y = Math.random()*height;    
        circles.push(new Circle(x,y,circleRadius));
    }

    // draw one circle per second
    timer = setInterval(function(){
        // exit loop when there's no more circles to draw
        if(index >= circles.length) {
             // also clear the timer
             clearInterval(timer);
             return;
        }

        drawCircle(ctx, circles[index ].x, circles[index ].y, (hoveredCircle == index) ? 25 : 15);
        // go to next circle
        index += 1;
    }, 1000);
});

Upvotes: 1

chrisbradbury
chrisbradbury

Reputation: 327

Assuming the circles are adding to the canvas correctly, you need to put the timeout inside the for loop. For loops will execute everything as close to at once as they can, so randomly spacing them out may be your answer:

setTimeout(function(){
    //-- code that adds circles here --//
}, ( Math.floor(Math.random()*11) * 1000 ) );

( Math.floor(Math.random()*11) * 1000 ) makes a random number between 0 and 10, times' it by 1000 and then delays the circle for that amount of time.

Give that a go.

Upvotes: 1

Related Questions