user14070533
user14070533

Reputation:

Why I'm getting only one rectangle?

let canvas, ctx, W, H;
canvas = document.createElement('canvas');
document.body.appendChild(canvas);
ctx = canvas.getContext('2d');
let objArr = [];

const init = () => {
  canvas.width = W = innerWidth;
  canvas.height = H = innerHeight;
  canvas.style.background = '#dedfda';

  for (let i = 0; i <= 5; i++) {
    let r = (i + 1) * 20;
    objArr.push(new Rectangle(W / 2, H / 2, 10, 10, "red", innerWidth / 2, innerHeight / 2, r));
    objArr[0].draw();

  }

  animate();
}

const random = (min = 0, max = 1) => Math.random() * (max - min) + min;

class Rectangle {
  constructor(posX, posY, w, h, color, cx, cy, r) {
    this.posX = posX;
    this.posY = posY;
    this.w = w;
    this.h = h;
    this.color = color;
    this.cx = cx;
    this.cy = cy;
    this.r = r;
    this.angle = 0;
  }
  draw() {
    ctx.clearRect(0, 0, innerWidth, innerHeight);
    ctx.fillStyle = this.color;
    ctx.fillRect(this.posX, this.posY, this.w, this.h);
  }
  update() {
    this.angle += 0.1;
    this.posX = this.cx + this.r * Math.cos(this.angle);
    this.posY = this.cy + this.r * Math.sin(this.angle);
    this.draw();
  }
}



const animate = () => {
  objArr.forEach(e => {
    e.update();
  })
  requestAnimationFrame(animate);
}

window.onload = init;

In this code, I'm expecting an output having 5 rectangles revolving around the center point of the window in different radius like the planets revolving around the Sun in solar system.

But I am getting only one rectangle and it's not even revolving.

Stucked and not getting why it's not working.

Upvotes: 0

Views: 64

Answers (2)

ddrdy
ddrdy

Reputation: 111

You are just drawing one rectangle. Pay attention to

objArr[0].draw()

Which should be

objArr[i].draw()

Also, I think everytime an Rectange object's draw method is called the whole canvas is cleared in this line

ctx.clearRect(0, 0, innerWidth, innerHeight);

Hence, only one rectangle appears at all times.

A solution would be to move the calls to clearRect and update from Rectangle to the animate function. This way it fits better with the program logic. A Rectangle being an object should only know how to draw itself not clearing the canvas and updating its position on the canvas.

Below is my solution.

let canvas, ctx, W, H;
canvas = document.createElement('canvas');
document.body.appendChild(canvas);
ctx = canvas.getContext('2d');
let objArr = [];

const init = () => {
  canvas.width = W = innerWidth;
  canvas.height = H = innerHeight;
  canvas.style.background = '#dedfda';

  for (let i = 0; i <= 5; i++) {
    let r = (i + 1) * 20;
    objArr.push(new Rectangle(W / 2, H / 2, 10, 10, "red", innerWidth / 2, innerHeight / 2, r));
    objArr[i].draw();

  }

  animate();
}

const random = (min = 0, max = 1) => Math.random() * (max - min) + min;

class Rectangle {
  constructor(posX, posY, w, h, color, cx, cy, r) {
    this.posX = posX;
    this.posY = posY;
    this.w = w;
    this.h = h;
    this.color = color;
    this.cx = cx;
    this.cy = cy;
    this.r = r;
    this.angle = 0;
  }
  draw() {
    ctx.fillStyle = this.color;
    ctx.fillRect(this.posX, this.posY, this.w, this.h);
  }

  // Should be moved outside of this class.
  update() {
    this.angle += 0.1;
    this.posX = this.cx + this.r * Math.cos(this.angle);
    this.posY = this.cy + this.r * Math.sin(this.angle);
    ctx.fillRect(this.posX, this.posY, this.w, this.h)
  }
}

const animate = () => {
  ctx.clearRect(0, 0, innerWidth, innerHeight);
  objArr.forEach(e => {
    e.update();
  })
  requestAnimationFrame(animate);
}

window.onload = init;

Upvotes: 1

GenericUser
GenericUser

Reputation: 3230

Your draw function is clearing every time and you are only referencing the first element of the array. Adjusting for both shows 6 objects revolving. Your loop runs from 0 to 5. If you want 5 objects, you'll need to set the upper bound to 4 instead.

let canvas, ctx, W, H;
canvas = document.createElement('canvas');
document.body.appendChild(canvas);
ctx = canvas.getContext('2d');
let objArr = [];

const init = () => {
  canvas.width = W = innerWidth;
  canvas.height = H = innerHeight;
  canvas.style.background = '#dedfda';

  // adjusted range
  for (let i = 0; i <= 4; i++) {
    let r = (i + 1) * 20;
    objArr.push(new Rectangle(W / 2, H / 2, 10, 10, "red", innerWidth / 2, innerHeight / 2, r));
    objArr[i].draw();
  }

  animate();
}

const random = (min = 0, max = 1) => Math.random() * (max - min) + min;

class Rectangle {
  constructor(posX, posY, w, h, color, cx, cy, r) {
    this.posX = posX;
    this.posY = posY;
    this.w = w;
    this.h = h;
    this.color = color;
    this.cx = cx;
    this.cy = cy;
    this.r = r;
    this.angle = 0;
  }
  draw() {
    ctx.fillStyle = this.color;
    ctx.fillRect(this.posX, this.posY, this.w, this.h);
  }
  update() {
    this.angle += 0.1;
    this.posX = this.cx + this.r * Math.cos(this.angle);
    this.posY = this.cy + this.r * Math.sin(this.angle);
    this.draw();
  }
}

const animate = () => {
  // moved clear here to happen just once on each animate
  ctx.clearRect(0, 0, innerWidth, innerHeight);
  objArr.forEach(e => {
    e.update();
  })
  requestAnimationFrame(animate);
}

window.onload = init;

Upvotes: 1

Related Questions