Objects going out of container while rotation in Javascript? Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Objects going out of container while rotation in Javascript? without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I have an animation like there are some boxes (actually they are divs) that are moving randomly and if any box hits with the walls of the parent container they bounce back and change their direction, everything works fine till here. The problem comes when I give the rotation to the boxes, by giving the rotation the boxes are going out of the parent container and not colliding with the walls of the parent container. So I want to know why this is happening and how to fix that like boxes have to collide with the walls container while rotating.

Here is my code

document.addEventListener("DOMContentLoaded", e => {

  const test = document.querySelectorAll(".test")
  
  test.forEach(function(many) {

    let rect = many.getBoundingClientRect(),
      rectBox = many.parentNode.getBoundingClientRect(),
      xMax = rectBox.width + rectBox.x - rect.width,
      yMax = rectBox.height + rectBox.y - rect.height,
      maxSpeed = 1;

    let x = rect.x,
      y = rect.y,
      xDelta,
      yDelta;

    setSpeed();
    many.addEventListener("click", setSpeed);
    window.requestAnimationFrame(move);
    many.classList.toggle("move", true);

    function move(timestamp) {
      x = x + xDelta;
      y = y + yDelta;
      if (x < rectBox.x || x > xMax) {
        xDelta = -xDelta;
        x = x < rectBox.x ? rectBox.x : xMax;
      }
      if (y < rectBox.y || y > yMax) {
        yDelta = -yDelta;
        y = y < rectBox.y ? rectBox.y : yMax;
      }
      many.style.transform = `rotate(${x/2}deg)`
      many.style.left = x + "px";
      many.style.top = y + "px";
      window.requestAnimationFrame(move);
    };
    //console.log(xDelta)

    function setSpeed() {
      xDelta = rand(-maxSpeed, maxSpeed);
      yDelta = rand(-maxSpeed, maxSpeed);
    }

    function rand(min, max) {
      return Math.random() * (max - min + 1) + min;
    }

  })

});
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
  user-select: none;
}

.box {
  width: 500px;
  height: 500px;
  border: 2px solid red;
  margin: 0 auto;
  position: relative;
  margin-top: 50px;
}

* {
  box-sizing: border-box;
}

body {
  background-color: #fff;
  text-align: center;
}

.bgcolor {
  background-color: black;
  color: rgba(255, 255, 255, 0.8);
}

.test {
  width: 100px;
  height: 100px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  background-color: #FCD757;
}

.move {
  margin: 0;
  position: absolute;
}

.check {
  border: 2px solid black;
  width: 50px;
  height: 105px;
}

.big {
  width: 120px;
}
<div class="box">
  <div id="test" class="test"></div>
  <div class="test"></div>
  <div class="test"></div>
  <div class="test big"></div>
  <div class="test big"></div>
  <div class="test big"></div>
  <div class="test"></div>
</div>

Answer

Remove position:relative; from .box class. It will contain the boxes within the parent, however because rect is used outside of move function it contains non-rotated dimensions of the box which does not properly render box collision:

document.addEventListener("DOMContentLoaded", e => {

  const test = document.querySelectorAll(".test")
  
  test.forEach(function(many) {

    let rect = many.getBoundingClientRect(),
      rectBox = many.parentNode.getBoundingClientRect(),
      xMax = rectBox.width + rectBox.x - rect.width,
      yMax = rectBox.height + rectBox.y - rect.height,
      maxSpeed = 1;
//dotted box
const boundBox = document.createElement("div");
boundBox.className = "boundBox";
boundBox.addEventListener("click", setSpeed);
document.body.appendChild(boundBox);

    let x = rect.x,
      y = rect.y,
      xDelta,
      yDelta;

    setSpeed();
    many.addEventListener("click", setSpeed);
    window.requestAnimationFrame(move);
    many.classList.toggle("move", true);

    function move(timestamp) {
      x = x + xDelta;
      y = y + yDelta;
      if (x < rectBox.x || x > xMax) {
        xDelta = -xDelta;
        x = x < rectBox.x ? rectBox.x : xMax;
      }
      if (y < rectBox.y || y > yMax) {
        yDelta = -yDelta;
        y = y < rectBox.y ? rectBox.y : yMax;
      }
      many.style.transform = `rotate(${x/2}deg)`
      many.style.left = x + "px";
      many.style.top = y + "px";

boundBox.style.left = x + "px";
boundBox.style.top = y + "px";
boundBox.style.width = rect.width + "px";
boundBox.style.height = rect.height + "px";

      window.requestAnimationFrame(move);
    };
    //console.log(xDelta)

    function setSpeed() {
      xDelta = rand(-maxSpeed, maxSpeed);
      yDelta = rand(-maxSpeed, maxSpeed);
    }

    function rand(min, max) {
      return Math.random() * (max - min + 1) + min;
    }

  })

});
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
  user-select: none;
}

.box {
  width: 500px;
  height: 500px;
  border: 2px solid red;
  margin: 0 auto;
/*  position: relative;*/
  margin-top: 50px;
}

* {
  box-sizing: border-box;
}

body {
  background-color: #fff;
  text-align: center;
}

.bgcolor {
  background-color: black;
  color: rgba(255, 255, 255, 0.8);
}

.test {
  width: 100px;
  height: 100px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  background-color: #FCD757;
}

.move {
  margin: 0;
  position: absolute;
}

.check {
  border: 2px solid black;
  width: 50px;
  height: 105px;
}

.big {
  width: 120px;
}

.boundBox
{
  position: absolute;
  border: 1px dotted black;
}
<div class="box">
  <div id="test" class="test"></div>
  <div class="test"></div>
  <div class="test"></div>
  <div class="test big"></div>
  <div class="test big"></div>
  <div class="test big"></div>
  <div class="test"></div>
</div>

To fix that, we need to get box rect for each frame and for both before and after it was rotated:

document.addEventListener("DOMContentLoaded", e =>
{
  const test = document.querySelectorAll(".test");

  test.forEach(function(many){
    
    
    const rectBox = many.parentNode.getBoundingClientRect(),
          rect = many.getBoundingClientRect(),
          maxSpeed = 1;

//dotted box
const boundBox = document.createElement("div");
boundBox.className = "boundBox";
boundBox.addEventListener("click", setSpeed);
document.body.appendChild(boundBox);

    let x = rect.x,
        y = rect.y,
        xDelta,
        yDelta;

    setSpeed();
    many.addEventListener("click", setSpeed);
    window.requestAnimationFrame(move);
    many.parentNode.classList.toggle("move", true);
    function move(timestamp)
    {
      x = x + xDelta;
      y = y + yDelta;

      many.style.transform = "";
      const rectInit = many.getBoundingClientRect();

      many.style.transform = `rotate(${x/2}deg)`;
      const rectBox = many.parentNode.getBoundingClientRect(),
            rect = many.getBoundingClientRect(),
            xDif = rect.x - rectInit.x,
            yDif = rect.y - rectInit.y,
            xMin = rectBox.x - xDif,
            yMin = rectBox.y - yDif,
            xMax = rectBox.width + rectBox.x - rect.width - xDif,
            yMax = rectBox.height + rectBox.y - rect.height - yDif;

      if (x < xMin || x > xMax)
      {
        xDelta = -xDelta;
        x = x < xMin ? xMin : xMax;
      }
      if (y < yMin || y > yMax)
      {
        yDelta = -yDelta;
        y = y < yMin ? yMin : yMax;
      }
      many.style.left = x + "px";
      many.style.top = y + "px";

boundBox.style.left = x + xDif + "px";
boundBox.style.top = y + yDif + "px";
boundBox.style.width = rect.width + "px";
boundBox.style.height = rect.height + "px";

      window.requestAnimationFrame(move);
    } //move()
    //console.log(xDelta)


    function setSpeed()
    {
      xDelta = rand(-maxSpeed, maxSpeed);
      yDelta = rand(-maxSpeed, maxSpeed);
    }
    function rand(min, max)
    {
      return Math.random() * (max - min + 1) + min;
    }

  }) //forEach
    
});
html, body
{
  height: 100%;
  margin: 0;
  padding: 0;
  user-select: none;
}
.box
{
  width: 500px;
  height: 500px;
  border:2px solid red;
  margin: 0 auto;
/*  position:relative;*/
  margin-top: 50px;

}
*{
  box-sizing:border-box;
}
body {
  background-color: #fff;
  text-align: center;
}
.bgcolor {
  background-color: black;
  color: rgba(255, 255, 255, 0.8);
}
.test
{
  width:100px;
  height:100px;
  margin:0 auto;
  display:flex;
  flex-wrap:wrap;
  background-color: #FCD757;
  
}
.move .test
{
  margin: 0;
  position: absolute;
}
.check{
  border:2px solid black;
  width:50px;
  height:105px;
}
.big{
  width:120px;
}

.boundBox
{
  position: absolute;
  border: 1px dotted black;
}
<div class="box">
  <div id="test" class="test"></div>
  <div class="test"></div>
  <div class="test"></div>
  <div class="test big"></div>
  <div class="test big"></div>
  <div class="test big"></div>
  <div class="test"></div>
</div>
We are here to answer your question about Objects going out of container while rotation in Javascript? - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji