Home > database >  Can only get one of two canvas backgrounds to animate
Can only get one of two canvas backgrounds to animate

Time:12-10

So I've created a "falling snow" effect using canvas and JS, it starts with a small amount on the screen and as the user clicks more are added - they're animated to gently fall and it all works fine and looks great.

The problem came when I tried to add a second canvas underneath without the interactivity but still with some of the moving snow effects, just to make it look a bit better and have some continuity throughout the page. I re-used the code for the first effect while changing the array, identifiers and function names etc.

I just can't seem to get the second effect to animate no matter what I try. It's getting the correct amount of "snowflakes" on screen but they're just static. The same animation code works on the first one so I can't see why it isn't on the second. No errors in the console either since everything is named separately and it can read both arrays. I've been stuck on this for the best part of two days so any help would be great!

The top canvas JS which animates perfectly:

const canvas = document.getElementById("topCanvas");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const c = canvas.getContext("2d");


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

  this.draw = function() {
    c.beginPath();
    c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
    c.strokeStyle = "#E2EAFC";
    c.fill();
    c.fillStyle = "#EDF2FB";
    c.stroke();
  }

  this.update = function() {

    if (this.x   this.radius > innerWidth ||
      this.x - this.radius < 0) {
      this.dx = -this.dx;
    }

    this.x  = this.dx;
    this.y  = this.dy;

    this.draw();
  }
}


const circleArray = [];

for (i = 0; i < 100; i  ) {
  radius = (Math.random() * 1);
  x = Math.random() * (innerWidth - radius * 2)   radius;
  y = Math.random() * (innerHeight - radius * 2)   radius;
  dx = (Math.random() - 0.1) * 0.05;
  dy = (Math.random() - 0.2) * 0.1;
  circleArray.push(new Circle(x, y, dx, dy, radius));
}

console.log(circleArray);

function animate() {
  requestAnimationFrame(animate);
  c.clearRect(0, 0, innerWidth, innerHeight);

  for (i = 0; i < circleArray.length; i  ) {
    circleArray[i].update();
  }
}

canvas.addEventListener('click', function() {
  for (i = 0; i < 80; i  ) {
    radius = (Math.random() * 2);
    x = Math.random() * (innerWidth - radius * 2)   radius;
    y = Math.random() * (innerHeight - radius * 2)   radius;
    dx = (Math.random() - 0.2) * 0.05;
    dy = (Math.random() - 0.2) * 0.1;
    circleArray.push(new Circle(x, y, dx, dy, radius));
  }
});

animate();

And the second one which doesn't:

const background = document.getElementById("backgroundEffect");

background.width = window.innerWidth;
background.height = window.innerHeight;

const b = background.getContext("2d");


function Drawing(x, y, dx, dy, radius) {
  this.x = x;
  this.y = y;
  this.dx = dx;
  this.dy = dy;
  this.radius = radius;

  this.draw = function() {
    b.beginPath();
    b.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
    b.strokeStyle = "#E2EAFC";
    b.fill();
    b.fillStyle = "#EDF2FB";
    b.stroke();
  }

  this.update = function() {

    if (this.x   this.radius > innerWidth ||
      this.x - this.radius < 0) {
      this.dx = -this.dx;
    }

    this.x  = this.dx;
    this.y  = this.dy;

    this.draw();
  }
}


const backgroundArray = [];

for (i = 0; i < 200; i  ) {
  radius = (Math.random() * 2);
  x = Math.random() * (innerWidth - radius * 2)   radius;
  y = Math.random() * (innerHeight - radius * 2)   radius;
  dx = (Math.random() - 0.2) * 0.1;
  dy = (Math.random() - 0.2) * 0.4;
  backgroundArray.push(new Drawing(x, y, dx, dy, radius));
}

console.log(backgroundArray);

function animateBackground() {
  requestAnimationFrame(animate);
  b.clearRect(0, 0, innerWidth, innerHeight);

  for (i = 0; i < backgroundArray.length; i  ) {
    backgroundArray[i].update();
  }
}

background.addEventListener('click', function() {
  for (i = 0; i < 80; i  ) {
    radius = (Math.random() * 2);
    x = Math.random() * (innerWidth - radius * 2)   radius;
    y = Math.random() * (innerHeight - radius * 2)   radius;
    dx = (Math.random() - 0.2) * 0.1;
    dy = (Math.random() - 0.2) * 0.4;
    backgroundArray.push(new Circle(x, y, dx, dy, radius));
  }
});

animateBackground();

These are in different JS files and both are being read and executed fine aside from the animation itself. To try and illustrate I've attached two pictures - before clicking and after clicking. Top canvas the particles move about but bottom one they don't

Before

After

CodePudding user response:

Are you sure you get no errors on the console?

If I run them in isolation on the second I get:
message": "Uncaught ReferenceError: animate is not defined",

Your code on the second animation should be:

function animateBackground() {
  requestAnimationFrame(animateBackground);
  ...

But you have:

function animateBackground() {
  requestAnimationFrame(animate);
  ...

So your error is that both animations are calling the same requestAnimationFrame function, instead of each calling their own, I did not see any other issues...

  • Related