Skip to content
Advertisement

Setting variable to target all divs with same Class

When selecting a class with querySelectorAll i get an uncaught error Uncaught TypeError: b.getBoundingClientRect is not a function at overlaps is there a way to fix that?

function overlaps(a, b) {
    a = document.getElementById('char');
    b = document.querySelectorAll('.enemy');
    const rect1 = a.getBoundingClientRect();
    const rect2 = b.getBoundingClientRect();
    const isInHoriztonalBounds =
      rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x;
    const isInVerticalBounds =
      rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y;
    const isOverlapping = isInHoriztonalBounds && isInVerticalBounds;
    return isOverlapping;
  }

I have div being generated with an ID ‘enemy’ and want to detect overlapping with my div ID “char”, but the function only targets the first div with ID ‘enemy'(the console log(overlaps) fires only on the first div with ID’enemy’ overlapping with ID ‘char’). Applying a class to the div with ID’enemy’ and selecing getElementsByClassName returns ‘TypeError: b.getBoundingClientRect is not a function at overlaps’. Is there a way to select all divs with the same ID to detect overlapping?

function generateObstacles() {
  function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (100 - 1 + 1)) + 1;
  }
  let randomTime = Math.random() * 2000;
  let obstaclePos = 100;
  const obstacle = document.createElement('div');
  obstacle.classList.add('character');
  obstacle.classList.add('enemy');
  obstacle.classList.add('pixelart');
  obstacle.id = 'enemy';
  document.querySelector('.bg').appendChild(obstacle);
  let obsprite = document.createElement('img');
  obsprite.src = './sprites/chars/spritesheet1.png';
  obsprite.style.height = '576px';
  obsprite.style.width = '384px';
  obsprite.id = 'mainchar';
  obstacle.appendChild(obsprite);
  obstacle.style.left = obstaclePos + '%';
  obstacle.style.top = getRandomInt() + '%';

  let timerId = setInterval(function () {
    if (overlaps()) {
      clearInterval(timerId);
      console.log('overlaps');
    }
    obstaclePos -= 1;
    obstacle.style.left = obstaclePos + '%';
    obsprite.classList.add('faceleft');
    obsprite.classList.add('animation');
  }, 150);
  setTimeout(generateObstacles, randomTime);
  function overlaps(a, b) {
    a = document.getElementById('char');
    b = document.getElementById('enemy');
    const rect1 = a.getBoundingClientRect();
    const rect2 = b.getBoundingClientRect();
    const isInHoriztonalBounds =
      rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x;
    const isInVerticalBounds =
      rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y;
    const isOverlapping = isInHoriztonalBounds && isInVerticalBounds;
    return isOverlapping;
  }
}

Advertisement

Answer

As @Andreas has pointed out in a comment ids should be unique. When you use:

 b = document.getElementById('enemy');

the system will (most likely) find the first instance of id enemy and stop there.

If you convert all the enemies to have class enemy then you can do:

  let enemies = document.querySelectorAll('.enemy');

Note: this gives you a collection of all the elements it’s found with class=”enemy” – the syntax of the selector is the same as you’d use in CSS, hence the . before enemy to indicate it’s looking for things with that class.

You can then step through enemies as though it were an array (it isn’t exactly, but some things work like for (let i = 0; i < enemies.length; i++) so the ith enemy element is enemies[i]

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement