在 Javascript 中旋转时对象从容器中出来? [英] Objects going out of container while rotation in Javascript?

查看:33
本文介绍了在 Javascript 中旋转时对象从容器中出来?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动画,就像有一些盒子(实际上它们是 div)随机移动,如果任何盒子碰到父容器的壁,它们会反弹并改变方向,直到这里一切正常.当我给盒子旋转时,问题就出现了,通过给盒子旋转,盒子会离开父容器而不与父容器的壁碰撞.所以我想知道为什么会发生这种情况以及如何解决这个问题,比如盒子在旋转时必须与墙壁容器碰撞.

这是我的代码

document.addEventListener("DOMContentLoaded", e => {const test = document.querySelectorAll(".test")test.forEach(function(many) {让 rect = many.getBoundingClientRect(),rectBox = many.parentNode.getBoundingClientRect(),xMax = rectBox.width + rectBox.x - rect.width,yMax = rectBox.height + rectBox.y - rect.height,最大速度 = 1;让 x = rect.x,y = rect.y,xDelta,yDelta;设置速度();many.addEventListener("click", setSpeed);window.requestAnimationFrame(移动);many.classList.toggle("move", true);功能移动(时间戳){x = x + xDelta;y = y + yDelta;如果 (x  xMax) {xDelta = -xDelta;x = x 

html,身体 {高度:100%;边距:0;填充:0;用户选择:无;}.盒子 {宽度:500px;高度:500px;边框:2px纯红色;边距:0 自动;位置:相对;边距顶部:50px;}* {box-sizing: 边框框;}身体 {背景色:#fff;文本对齐:居中;}.bgcolor {背景颜色:黑色;颜色:RGBA(255、255、255、0.8);}.测试 {宽度:100px;高度:100px;边距:0 自动;显示:弹性;flex-wrap: 包裹;背景色:#FCD757;}.移动 {边距:0;位置:绝对;}.查看 {边框:2px纯黑色;宽度:50px;高度:105px;}.大 {宽度:120px;}

<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>

解决方案

.box 类中移除 position:relative;.它将包含父级中的框,但是因为 rectmove 函数之外使用,它包含框的非旋转尺寸,它不能正确渲染框碰撞:

document.addEventListener("DOMContentLoaded", e => {const test = document.querySelectorAll(".test")test.forEach(function(many) {让 rect = many.getBoundingClientRect(),rectBox = many.parentNode.getBoundingClientRect(),xMax = rectBox.width + rectBox.x - rect.width,yMax = rectBox.height + rectBox.y - rect.height,最大速度 = 1;//虚线框const boundBox = document.createElement("div");boundBox.className = "boundBox";boundBox.addEventListener("click", setSpeed);document.body.appendChild(boundBox);让 x = rect.x,y = rect.y,xDelta,yDelta;设置速度();many.addEventListener("click", setSpeed);window.requestAnimationFrame(移动);many.classList.toggle("move", true);功能移动(时间戳){x = x + xDelta;y = y + yDelta;如果 (x  xMax) {xDelta = -xDelta;x = x 

html,身体 {高度:100%;边距:0;填充:0;用户选择:无;}.盒子 {宽度:500px;高度:500px;边框:2px纯红色;边距:0 自动;/* 位置:相对;*/边距顶部:50px;}* {box-sizing: 边框框;}身体 {背景色:#fff;文本对齐:居中;}.bgcolor {背景颜色:黑色;颜色:RGBA(255、255、255、0.8);}.测试 {宽度:100px;高度:100px;边距:0 自动;显示:弹性;flex-wrap: 包裹;背景色:#FCD757;}.移动 {边距:0;位置:绝对;}.查看 {边框:2px纯黑色;宽度:50px;高度:105px;}.大 {宽度:120px;}.boundBox{位置:绝对;边框:1px 黑色虚线;}

<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>

为了解决这个问题,我们需要为每一帧以及旋转前后获取框rect:

document.addEventListener("DOMContentLoaded", e =>{const test = document.querySelectorAll(".test");test.forEach(功能(很多){const rectBox = many.parentNode.getBoundingClientRect(),rect = many.getBoundingClientRect(),最大速度 = 1;//虚线框const boundBox = document.createElement("div");boundBox.className = "boundBox";boundBox.addEventListener("click", setSpeed);document.body.appendChild(boundBox);让 x = rect.x,y = rect.y,xDelta,yDelta;设置速度();many.addEventListener("click", setSpeed);window.requestAnimationFrame(移动);many.parentNode.classList.toggle("move", true);功能移动(时间戳){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;如果 (x < xMin || x > xMax){xDelta = -xDelta;x = x <最小 ?xMin : xMax;}如果 (y < yMin || y > yMax){yDelta = -yDelta;y = y 

html, body{高度:100%;边距:0;填充:0;用户选择:无;}.盒子{宽度:500px;高度:500px;边框:2px 纯红色;边距:0 自动;/* 位置:相对;*/边距顶部:50px;}*{box-sizing:border-box;}身体 {背景色:#fff;文本对齐:居中;}.bgcolor {背景颜色:黑色;颜色:RGBA(255、255、255、0.8);}.测试{宽度:100px;高度:100px;保证金:0 自动;显示:弹性;弹性包裹:包裹;背景色:#FCD757;}.移动 .test{边距:0;位置:绝对;}.查看{边框:2px纯黑色;宽度:50px;高度:105px;}.大{宽度:120px;}.boundBox{位置:绝对;边框:1px 黑色虚线;}

<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>

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>

解决方案

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>

这篇关于在 Javascript 中旋转时对象从容器中出来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆