【问题标题】:Detecting if two divs are too close or collide/overlap检测两个 div 是否太近或碰撞/重叠
【发布时间】:2013-08-27 00:11:13
【问题描述】:

我正在尝试检测两个给定的div 是否太靠近或碰撞/重叠。

我有下面的代码笔,它尝试生成 20 个随机的 div,并且只有在它们的位置不太靠近其他现有 div 时才将它们附加到正文。

这就是想法,但它没有按预期工作,我得到div 的位置与现有divs 的位置接近/重叠。 (如果第一次是完美的,请多次运行它并且你应该遇到它)。

http://codepen.io/anon/pen/fHLzj

任何人都可以看到错误和使它起作用的方法吗?

【问题讨论】:

  • 嘿@op,看来你正在学习我学习的方式......我在 2013 年 3 月做到了 lastnoob.com 看看

标签: javascript jquery overlap


【解决方案1】:

这有点难以解释和理解..但这里是:

通过运行 for 循环检查每个 div 与每个 div

x,y,h,w

  • x 是左上角到左边的距离。
  • y 是左上角到顶部的距离。
  • h 是 div 的高度。
  • w 是 div 的宽度。

要考虑的点...您实际上并不需要检查每个 div ..考虑一下

有 10 个 div...

  • 首先,您将检查 1 与 9。
  • 二一对八。
  • ......
  • 八一对二。
  • 九一对一。
  • 不要最后一个。

在将它们分配给 dom 之前,分配值并检查数据中的冲突也是一个好主意。 Dom 应该只用于渲染最终结果。

我假设你不想保留两个冲突的 div。

预览 http://jsfiddle.net/techsin/m4fSf/6/

正如预期的那样,代码很大

var
div={},
number=10,
size=20,
m = ele('main');
mw= parseFloat(getComputedStyle(m).getPropertyValue("width"))-size,
mh= parseFloat(getComputedStyle(m).getPropertyValue("height"))-size,
f=true,
nn;    

var i
for (i = 0; i < number; i++) {
    div[i] = {};
    var t = true, newX, newY, nn;
   if (i!=0){ 
       while (t) {

        newX = rand(mw);
        newY = rand(mh);

        for (nn = 0; nn < i; nn++) {
            if (!(((newX > div[nn].x + size+5) || (newY > div[nn].y + size+5)) ||
             ((newX + size+5 < div[nn].x) || (newY + size+5 < div[nn].y)))) {
                    break;
                }
                if (nn == i-1) t = false;
            }}} else {
        newX = rand(mw);
        newY = rand(mh);
            }


console.log(newX);
    div[i].x = newX;
    div[i].y = newY;
}

for (i = 0; i < number; i++) {
render(div[i]);
}


console.log(div);
function render(x){
var d=document.createElement('div');
    d.style.position='absolute';
    d.style.left=(x.x+'px');
    d.style.top=(x.y+'px');
    m.appendChild(d);
}
function rand(x) { return Math.random()*x;} 
function ele(x){return document.getElementById(x);}

这段代码来自我的碰撞站点...我试着把它放在上面的代码中,但这是避免碰撞和缩小差距所需要的。

if (xpost+30>xx.left && xx.left>xpost && xx.top+30>ypost  && xx.top<ypost+30)  { xspeed = -speed; }
            if (xpost<xx.left+30 && xx.left<xpost && xx.top+30>ypost  && xx.top<ypost+30)  { xspeed = speed; }
            if (ypost+30>xx.top && xx.top>ypost && xx.left+30>xpost  && xx.left<xpost+30)  { yspeed = -speed; }
            if (ypost<xx.top+30 && xx.top<ypost && xx.left+30>xpost  && xx.left<xpost+30)  { yspeed = speed; }

【讨论】:

  • 当您检查第 9 个 div 是否有碰撞时,您不会将其与之前的 div 进行检查。因为如果他们不与它发生碰撞,那么这不会与其他任何人发生碰撞。但它可能会与下一个发生碰撞,而当它没有发生时。那么这意味着最后一个也没有与其他任何人发生碰撞。
  • @Muhammad Umer 能否请您在 codepen.io 上发布演示。 jsFiddle 在这里被我屏蔽了。
  • @Muhammad Umer 你的代码只能避免碰撞,对吗?并且它不关心在渲染 div 之前,当前 div 的位置与相邻 DIV 的位置之间的间隙(顶部/左侧)是否足够。还是我读错了代码?
  • 是的,但要做到这一点,您需要做的就是在这样的大 if 语句中添加一个数字 + size ..div[nn].x + size+5
  • 是的,它不完整,需要更多地更改 if 语句。
【解决方案2】:

使用这些库之一为您检测碰撞如何?

http://sourceforge.net/projects/jquerycollision/

http://gamequeryjs.com/

【讨论】:

  • 第二个链接似乎有点矫枉过正。我认为实现起来并不困难,所以没有考虑使用外部库。为了学习和关注问题,我宁愿不必使用外部库。请注意,我有两件事要考虑,它不仅是碰撞检测,还包括两个给定 DIV 之间的 GAP,即它们不能重叠,并且它们不能比特定的 TOP 和 LEFT 更接近其相邻 DIV。
  • jquerycollision 还可以告诉您 2 个元素之间的差距以及它是否发生碰撞,这听起来像是您可能想要解决一个优化问题,这是解决给定约束的最佳方式。最好使用某种人工智能(如遗传算法)来解决它们。查看最后的小演示程序ai-junkie.com/ga/intro/gat3.html
【解决方案3】:

我改变了碰撞逻辑。它通过比较对象之间的距离来检测对象是否靠近另一个对象。我也将逻辑封装在一个 do-while 循环中,以便它会不断尝试找到放置方格的位置,而您将正好有 20 个方格。

这行得通:

var positions = [];  //stroe positions of appended divs
var divsize = 20; 
var topGap = 40;  // gap from top
var leftGap = 80;  //gap from left

function generateRandomPositionedDiv(){
    for(var c = 0; c < 20; c++){
        var color = '#'+ Math.round(0xffffff * Math.random()).toString(16);

            $newdiv = $('<div/>').css({
                'width':divsize+'px',
                'height':divsize+'px',
                'background-color': color
            }); 



                var posLeft;
                var posTop;
                var checkObj;
                var collide = false;

                posLeft = Math.floor((Math.random() * ($(document).width() - divsize)));//.toFixed();
                posTop = Math.floor((Math.random() * ($(document).height() - divsize)));//.toFixed();
                checkObj = {x: posLeft, y: posTop};

                collide = checkForCollisions(checkObj);

            if(!collide) {

                positions.push({x: posLeft, y: posTop});

                $newdiv.css({
                    'position':'absolute',
                    'left':posLeft+'px',
                    'top':posTop+'px'
                });

                $('body').append($newdiv);
            }

    }
}

/*function getPositions(box) {
  var $box = $(box);
  var pos = $box.position();
  var width = $box.width();
  var height = $box.height();
  return [ [ pos.left, pos.left + width + leftGap ], [ pos.top, pos.top + height + topGap ] ];
}*/


function comparePositions(obj1, obj2) { 
    if(Math.abs(obj1.x - obj2.x) <= (divsize + leftGap) && Math.abs(obj1.y - obj2.y) <= (divsize + topGap)) {
        return true;
    } else {
        return false;
    }
}

function checkForCollisions(posObj){
    for(var i = 0; i < positions.length; i++){
        var match = comparePositions(positions[i], posObj);
        if (match) { 
                //return true if two positions are close or overlapping
                return match;
            }
    }
}

generateRandomPositionedDiv();

【讨论】:

  • #CodePupper 您的代码似乎没有考虑到两个 DIV (var topGap = 40; var leftGap = 80; ) 之间的 LEFT 或 TOP 间隙。你能做到,只有当它们正确地与基于顶部和左侧的现有位置分开时,它才会放置 div?
  • 我猜你的意思是没有两个正方形可以在 x 轴上 80 像素和 y 轴上 40 像素之间。我已经编辑了我的代码以反映这种变化。让我知道这是否有效:)
  • 我试过你的代码 - 它在第二次/第三次运行时冻结。我猜它会陷入无限循环,试图永远找到合适的间隙!
  • 你是对的,代码可能会进入无限循环。我更新了代码,使其尝试 20 次,而不是尝试准确放置 20 个方格。
猜你喜欢
  • 2018-10-26
  • 1970-01-01
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多