heydeer
heydeer

Reputation: 15

for loop not performing with object

I'm using Canvas to play and learn with Javascript. Currently I'm creating a circle and have it display in random areas on the screen. I was able to complete that exercise completely; everything ran smoothly in one function.

Now I would like to create an object for the circle and call it in the for loop. I created the object, but something is still wrong. I'm only seeing one circle instead of 40. I banged my head on this for awhile before coming here for help. Take a look at the code below.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

if (!ctx) {
  alert('HTML5 Canvas is not supported in you browser');
}

function Circle(posX, posY, radius, startAngle, endAngle, anticlockwise) {
    this.posX = posX;
    this.posY = posY;
    this.radius = radius;
    this.startAngle = startAngle;
    this.endAngle = endAngle;
    this.anticlockwise = anticlockwise;

    this.test = function() {
        ctx.beginPath();
        ctx.arc(posX, posY, radius, startAngle, endAngle, anticlockwise);
        ctx.fill();
  }
}

var cir = new Circle(
    (Math.random() * canvas.width),
    (Math.random() * canvas.height),
    20,
    0,
    Math.PI*2,
    true
);

function drawCircle() {
        for(var i = 0; i < 40; i++){
        cir.test(); 

        }
}

/*setInterval(drawCircle, 400)*/
 drawCircle();

Upvotes: 1

Views: 67

Answers (3)

Edwin Reynoso
Edwin Reynoso

Reputation: 1531

Please read the comments, if you need more help understanding this just comment below.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

if (!ctx) {
  alert('HTML5 Canvas is not supported in you browser');
}
//The only thing I can see perhaps changing is radius so use radius as parameter
function Circle(radius) {
    this.posX = Math.random() * canvas.width; //This is always going to be the same so no need to pass as an argument
    this.posY = Math.random() * canvas.height; //So will this
    this.test = function() {
        ctx.beginPath();
        ctx.arc(this.posX, this.posY, radius, 0, Math.PI*2, true); //So will Math.PI*2, and true
        ctx.fill();
    }
    this.test();
}

function drawCircle() {
    for(var i = 0; i < 40; i++){
        new Circle(i); //This passes i as the radius so you can see the differences
    }
}

drawCircle();

Upvotes: 0

Anonymous
Anonymous

Reputation: 1

Currently your drawCircle() function is running a single test function on the same 'cir' variable 40 times. What you want to do is to fill an array with 40 new items using the for-loop. Then, use another for-loop to define those items as new Circle objects and call the test function on each new circle. Here is the code I would use:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

if (!ctx) {
  alert('HTML5 Canvas is not supported in you browser');
}

function Circle(posX, posY, radius, startAngle, endAngle, anticlockwise) {
  this.posX = posX;
  this.posY = posY;
  this.radius = radius;
  this.startAngle = startAngle;
  this.endAngle = endAngle;
  this.anticlockwise = anticlockwise;

  this.test = function() {
    ctx.beginPath();
    ctx.arc(posX, posY, radius, startAngle, endAngle, anticlockwise);
    ctx.fill();
  }
}

/*Create an array to hold your circles*/
var circleArray = [];

function drawCircle() {
  for (var i = 0; i < 40; i++) {
    circleArray.push('cirlce' + i); /*Push circle variable into circleArray*/
  }
  for (var i = 0; i < circleArray.length; i++) {
    /*Create a new circle object for every iteration of the circleArray*/
    circleArray[i] = new Circle(
      (Math.random() * canvas.width), (Math.random() * canvas.height),
      20,
      0,
      Math.PI * 2,
      true
    );
    circleArray[i].test(); /*Run the test function for every item in the circle array*/
  }
}

/*setInterval(drawCircle, 400)*/
drawCircle();
<canvas id='canvas'></canvas>

Upvotes: 0

Bassem
Bassem

Reputation: 3175

You are calling cir.test() 40 times without having 40 instances of Circle. It is the same circle being drawn 40 times on top of itself.

This might be an immediate fix to your problem:

function drawCircle() {
        for(var i = 0; i < 40; i++){
            // Mind you that doing this
            // Will not allow you to reference
            // your circles after they are
            // created. The best method is 
            // to put them in an array
            // of circles
            var cir = new Circle(
                (Math.random() * canvas.width),
                (Math.random() * canvas.height),
                20,
                0,
                Math.PI*2,
                true
            );

            cir.test();
        }
}

/*setInterval(drawCircle, 400)*/
 drawCircle();

However, I would recommend the following changes to your code:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

if (!ctx) {
  alert('HTML5 Canvas is not supported in you browser');
}

function Circle(posX, posY, radius, startAngle, endAngle, anticlockwise) {
    this.posX = posX;
    this.posY = posY;
    this.radius = radius;
    this.startAngle = startAngle;
    this.endAngle = endAngle;
    this.anticlockwise = anticlockwise;

    // Using better function names
    // is always a good idea
    this.testDraw = function() {
        ctx.beginPath();
        ctx.arc(posX, posY, radius, startAngle, endAngle, anticlockwise);
        ctx.fill();
  }
}

// Create an array to fill
// with Circle instances
var circlesArray = []

// Changed drawCircle to drawCircles
// it is clearer
function drawCircles() {
    for(var i = 0; i < 40; i++){
        // Create new Circle objects
        // and add them to the circlesArray
        // this will allow you to have a
        // each circle later on
        circlesArray.push(new Circle(
            (Math.random() * canvas.width),
            (Math.random() * canvas.height),
            20,
            0,
            Math.PI*2,
            true
        ));

        // Go through each item of the array
        // and call the test function
        circlesArray[i].testDraw();
    }
}

/*setInterval(drawCircle, 400)*/
 drawCircles();

Upvotes: 1

Related Questions