【问题标题】:JavaScript & CSS: How to log position of a div between css translate start and endJavaScript & CSS:如何在 css 转换开始和结束之间记录 div 的位置
【发布时间】:2018-10-11 13:14:50
【问题描述】:

基本上我需要为一个框架/容器内随机移动的三个球执行碰撞和反弹动画,放置类似于下图。

要检查球是否与任何东西发生碰撞,我需要使用 javascript 在 css 中的翻译状态期间跟踪 div 的每个位置。 使用getBoundingClientRect()我只会得到div的最终位置,但是当我们使用css translate时,我需要跟踪/记录div后面的路径的每个点。

我将使用纯角度动画,我不打算为此任务添加额外的 jQuery。

这是我在浏览器控制台上尝试的示例演示,它帮助我随机移动球,但它们有时会重叠,当球接触容器边缘或另一个球表面时,我需要反弹。

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

var anim2 = document.getElementsByClassName("animation1")[0];
var anim1 = document.getElementsByClassName("animation2")[0];
var anim4 = document.getElementsByClassName("animation3")[0];

function action() {

  var randomNumMin1 = getRandomInt(-100, 100);
  var randomNumMin2 = getRandomInt(-100, 100);
  var randomNumMin3 = getRandomInt(-100, 100);

  var randomNumMax1 = getRandomInt(-100, 100);
  var randomNumMax2 = getRandomInt(-100, 100);
  var randomNumMax3 = getRandomInt(-100, 100);

  var num1 = `translate(${randomNumMin1}px, ${randomNumMax1}px)`;
  var num2 = `translate(${randomNumMin2}px, ${randomNumMax2}px)`;
  var num4 = `translate(${randomNumMin3}px, ${randomNumMax3}px)`;

  anim1.style.transition = 'all 3s';
  anim1.style.transform = num1;

  anim2.style.transition = 'all 3s';
  anim2.style.transform = num2;

  anim4.style.transition = 'all 3s';
  anim4.style.transform = num4;
}

action()
var interval = setInterval(() => {
  action()
}, 3000)
[class*=animation] {
    width: 50px;
    height: 50px;
    background: red;
    border-radius: 50%;
}
<div class="animation1"></div>
<div class="animation2"></div>
<div class="animation3"></div>

需要帮助。

提前致谢。

【问题讨论】:

    标签: javascript html css angular


    【解决方案1】:

    您可能可以做一些类似轮询的事情来检查两个球是否相互碰撞/相交?

    function collides(ball1, ball2){
      var obj1 = ball1.getBoundingClientRect();
      var obj2 = ball2.getBoundingClientRect();
    
      if (obj1.left < obj2.left + obj2.width  && obj1.left + obj1.width  > obj2.left &&
            obj1.top < obj2.top + obj2.height && obj1.top + obj1.height > obj2.top) {
        // change transform / reverse etc.
      }
      else{
        // not collided yet
      }
    }
    

    Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。 MDN Web Docs

    【讨论】:

      【解决方案2】:

      所以基本上你需要用 JS 而不是 CSS 为球设置动画,并检测每个动画帧上的碰撞。所以你的代码应该是这样的:

      const balls = [{
          $el: document.getElementsByClassName("animation1")[0],
          r: 25, // ball radius
          vs: 0.1, // speed in pixels per frame
        },
        {
          $el: document.getElementsByClassName("animation2")[0],
          r: 25, // ball radius
          vs: 0.3, // speed in pixels per frame
        },
        {
          $el: document.getElementsByClassName("animation3")[0],
          r: 25, // ball radius
          vs: 0.5, // speed in pixels per frame
        }
      ];
      
      function isColliding(ball1, ball2) {
        const a = ball1.r + ball2.r;
        const dx = ball1.$el.offsetLeft - ball2.$el.offsetLeft;
        const dy = ball1.$el.offsetTop - ball2.$el.offsetTop;
        return a > Math.sqrt((dx ** 2) + (dy ** 2));
      }
      
      function tick() {
        // Change positions
        balls.forEach((ball) => {
          ball.$el.style.y += ball.vs;
        });
      
        // Detect collisions
        for (let i = 0; i < balls.length - 1; i++) {
          for (let j = i + 1; j < balls.length; j++) {
            if (isColliding(balls[i], balls[j])) {
              // Collision detected
            }
          }
        }
        
        requestAnimationFrame(tick);
      }
      
      requestAnimationFrame(tick);
      [class*=animation] {
        width: 50px;
        height: 50px;
        background: red;
        border-radius: 50%;
      }
      <div class="animation1"></div>
      <div class="animation2"></div>
      <div class="animation3"></div>

      【讨论】:

      • 嗨,您的解决方案对我来说看起来不错,让我试试。顺便说一句,我已经更新了这个问题。
      • @AnkitKumarSingh 这只是一种常见的方法。基本上,您有一些实体列表,甚至可能是管理器,并且在每个屏幕框架上,您都在执行一些计算或只是应用一个状态(如果您在刻度函数之外的某个地方更改它,例如,在某些 setTimeout 回调或用户交互中)跨度>
      猜你喜欢
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2014-11-23
      • 2020-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多