如何使用 vanilla 脚本相互反弹元素

use*_*446 5 html javascript css dom collision

我尝试添加顶部和左侧的更改,并且如果一个元素接近另一个元素,则每个元素的边距(也具有不同的定位更改)都会更改,但只有边距更改有效一次。有没有办法让他们工作更一致?

这是我使用函数来添加事件侦听器的地方:

var three = document.getElementById('three');
var test = document.getElementById('test');
var two = document.getElementById('two');
var obj = null;

function testmovea(object, event) {
    obj = document.getElementById(object.id);
    document.addEventListener("mousemove", move);
}

function move(event) {
    obj.innerText = event.clientX + ' ' + event.clientY;
    obj.style.position = 'absolute';
    obj.style.left = event.clientX + "px";
    obj.style.top = event.clientY + "px";
    three.addEventListener('mouseover', borders);
    three.addEventListener('mouseleave', bordersOff);
    two.addEventListener('mouseenter', bTwo);
    test.addEventListener('mouseenter', bTest);
    two.addEventListener('mouseleave', bTwoReset);
    test.addEventListener('mouseleave', bTestReset);
    document.addEventListener("mouseup", stopMove);
}
Run Code Online (Sandbox Code Playgroud)
var three = document.getElementById('three');
var test = document.getElementById('test');
var two = document.getElementById('two');
var obj = null;

function testmovea(object, event) {
    obj = document.getElementById(object.id);
    document.addEventListener("mousemove", move);
}

function move(event) {
    obj.innerText = event.clientX + ' ' + event.clientY;
    obj.style.position = 'absolute';
    obj.style.left = event.clientX + "px";
    obj.style.top = event.clientY + "px";
    three.addEventListener('mouseover', borders);
    three.addEventListener('mouseleave', bordersOff);
    two.addEventListener('mouseenter', bTwo);
    test.addEventListener('mouseenter', bTest);
    two.addEventListener('mouseleave', bTwoReset);
    test.addEventListener('mouseleave', bTestReset);
    document.addEventListener("mouseup", stopMove);
}
Run Code Online (Sandbox Code Playgroud)

这是我使用的鼠标停止事件:

    function bTwo() {
        two.style.margin = "10%";
    }
    
    function bTwoReset() {
        two.style.margin = "0%";

    }
    
    function bTest() {
        test.style.margin = "10%";
    }
    
    function bTestReset() {
        test.style.margin = "0%"
    }
Run Code Online (Sandbox Code Playgroud)

testmovea函数依赖于onmousedown为页面的 DOM 元素定义的属性

更新:我已经设法让它部分工作:

 function collide(el1, el2) {
    if(twoBoundX >= threeBoundY || threeBoundY >= twoBoundX) {
        two.style.margin = + event.clientX + "px";
        two.style.margin = + event.clientY + "px";
    }
 }
Run Code Online (Sandbox Code Playgroud)

其中,twoBoundX 和 ThreeBoundY 是相应元素的 getBoundingClientRect()

这是完整的代码片段:

    function stopMove() {
        document.removeEventListener('mousemove', move);
        test.removeEventListener('mouseover', bTest);
        two.removeEventListener('mouseover', bTwo);
        test.removeEventListener('mouseleave', bTestReset);
        two.removeEventListener('mouseleave', bTwoReset);
    }
Run Code Online (Sandbox Code Playgroud)

Laj*_*pad 2

碰撞检测

您需要定义一个function来检查两个形状是否发生碰撞。如果只有顶点与 OX 和 OY 顶点平行的矩形,它看起来像这样:

function areColliding(r1, r2) {
    return !(
           (r1.x > r2.x + r2.w) ||
           (r1.x + r1.w < r2.x) ||
           (r1.y > r2.y + r2.h) ||
           (r1.y + r1.h < r2.y)
           );
}
Run Code Online (Sandbox Code Playgroud)

当然,如果您的问题涉及一些旋转甚至其他形状,那么您需要相应地扩展/调整碰撞检测器。

共享功能

您需要创建一个function来接收元素的当前状态和发生的移动。它看起来像这样:

function handleMove(currentPositions, proposedPositions) {
    while (!validPositions(proposedPositions)) {
        proposedPositions = generateNewPositions(currentPositions, handleCollisions(proposedPositions));
    }
    refreshUI(proposedPositions);
}
Run Code Online (Sandbox Code Playgroud)
  • currentPositions是你的元素当前拥有的位置集
  • proposedPositions是在没有碰撞的情况下元素将具有的位置集
  • validPositions检查任何一对会发生碰撞的形状,如果这些形状中没有一个发生碰撞,则返回 true;如果至少有一个这样的形状对发生碰撞,则返回 false
  • proposedPositions正在刷新while仍有冲突
  • generateNewPositions是基于碰撞的更改的处理程序
  • handleCollisions进行更改以避免碰撞
  • refreshUI刷新用户界面

事件处理

您的鼠标事件应该通过加载元素的所有位置并调用此共享功能来处理更改更新。

注意:如果您还有其他问题,那么您可能需要创建一个可重现的示例,以便我们也可以看到您的确切结构、样式和代码。

function areColliding(r1, r2) {
    return !(
           (r1.x > r2.x + r2.w) ||
           (r1.x + r1.w < r2.x) ||
           (r1.y > r2.y + r2.h) ||
           (r1.y + r1.h < r2.y)
           );
}
Run Code Online (Sandbox Code Playgroud)