Josh Robertson
Josh Robertson

Reputation: 131

(canvas) Push a new item every couple seconds

Hello and thank you for your help in advance.

I am trying to push/create a new "ring" every couple seconds. I have a ring with a couple variables for the X and Y. The problem I am encountering is, how do I get a new ring and also increment the variables? I need a new variable name for every ring? Here is how far I have gotten so far:

http://codepen.io/hossman/pen/AfwkF

You can see in the demo how 1 ring goes out, but I want more than 1 ring to go out of my eyes. So for instance 1 ring goes and then it waits a second and then shoots out another ring, so now there are 2 rings on the canvas, then 3, then 4, etc.... I have thought of multiple ways like using arrays and setTimeouts, but I cant put my finger on it. The only other idea I have is to create multiple variables with different names and have each ring be incremented, but thats not very D.R.Y.

Anyhelp?

Please ask questions if I didn't explain it good enough. Thanks again!

Upvotes: 0

Views: 84

Answers (2)

prograhammer
prograhammer

Reputation: 20590

Add this to your global vars at the top (and set to whatever you want the distance to be between circles):

var distanceApart = 40;

Then update your main loop like this:

requestAnimationFrame(function print() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    var leftRing = new Ring(x, y);
    var rightRing = new Ring(x2, y2);
    var temp = startRadius;
    var temp2 = 0;

    while(temp > 0){
         leftRing.draw(ctx, startRadius - temp2 , 'red');
         rightRing.draw(ctx, startRadius - temp2 , 'red');   
         temp2 = temp2 + distanceApart;
         temp = temp - distanceApart;
    }

    startRadius += increase;

    requestAnimationFrame(print);
});

Forked here: http://codepen.io/anon/pen/plBmj (Looks very memorizing!)

Upvotes: 2

Aadit M Shah
Aadit M Shah

Reputation: 74204

I would rewrite parts of your code to enable this. For example I would rewrite your Ring class as follows:

var Ring = defclass({
    constructor: function (x, y, r) {
        this.x = x;
        this.y = y;
        this.r = r;
    },
    draw: function (context) {
        context.beginPath();
        context.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        context.stroke();
        return this;
    },
    addRadius: function (r) {
        return new Ring(this.x, this.y, this.r + r);
    }
});

Your Ring class constructor now takes x, y and a radius r. The addRadius function returns a new Ring instead of mutating the original one. This is good because immutability makes your code easier to work with. Oh, and defclass is declared as:

function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

Then we create the two rings for your eyes:

var radius = 10;
var delta = 0.1;

var left = new Ring(cx - (cx / 3.6), cy - 5, radius);
var right = new Ring(cx + (cx / 3.6), cy - 10, radius);

After that we call the animation loop:

var interval = 50 / 3;
var start = Date.now();
loop(start, [left, right]);

Since we want to playback at 60 FPS the interval is 1000 / 60 which can be simplified to 50 / 3. The animation loop is defined as follows:

function loop(last, rings) {
    var next = last + interval;

    context.clearRect(0, 0, width, height);

    var newRings = rings.map(function (ring) {
        return ring.draw(context).addRadius(delta);
    });

    var now = Date.now();

    setTimeout(loop, next - now, next,
        Math.floor((now - start) / 1000) === rings.length / 2 ?
            [left, right].concat(newRings) : newRings);
}

Here's what's happening:

  1. First we clear the screen.
  2. Then we draw all the rings and increase their size.
  3. If one second has elapsed we add two new rings to the array.
  4. Finally we calculate when to call loop again so that it fires after the correct interval.

See the demo: http://jsfiddle.net/LAr76/

Upvotes: 2

Related Questions