Div重叠和碰撞位置

3
我正在尝试查看我的两个div何时会重叠并接触彼此。这个例子中的两个黄色div。
为什么在div甚至没有重叠或接触时,碰撞返回true? http://jsfiddle.net/HWfMt/156/
    var degree = 0;
var degreeSmall = 0;
var timer=30;
var $spin = $(".gear");
var $spinSmall = $(".gear-small");
var to;
var toSmall;

function collision($div1, $div2) {
  var x1 = $div1.offset().left;
  var y1 = $div1.offset().top;
  var h1 = $div1.outerHeight(true);
  var w1 = $div1.outerWidth(true);
  var b1 = y1 + h1;
  var r1 = x1 + w1;
  var x2 = $div2.offset().left;
  var y2 = $div2.offset().top;
  var h2 = $div2.outerHeight(true);
  var w2 = $div2.outerWidth(true);
  var b2 = y2 + h2;
  var r2 = x2 + w2;

  if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false;
  return true;
}

$( document ).ready(function() {

    rotate();
});


function rotate() {
    degree++;
    $spin.css({ 'WebkitTransform': 'rotate(' + degree + 'deg)'});  
    $spin.css({ '-moz-transform': 'rotate(' + degree + 'deg)'});

    to = setTimeout(function() {
        rotate();
    }, timer);

    $('#result').text(collision($('.gear .inner-gear.yellow'), $('.gear-small .inner-gear.yellow')));

}

谢谢


2
这是我正在运行的一个测试 http://jsfiddle.net/abc123/HWfMt/162/,看起来x轴发生了变化。 - abc123
你有什么建议 @abc123 - Kiwimoisi
我认为一个解决方案是在它们没有旋转或停止时检测是否发生碰撞。无论如何,我只会在它们停止时进行检查,所以我认为在旋转期间检查是不必要的。这样结果可能会更准确。@abc123 - Kiwimoisi
3个回答

3

编辑:因为您添加了注释,希望两个齿轮都旋转,请参见下面的多边形检测。

只有一个齿轮旋转:我已经修改了您的JSFiddle以按照您的想法工作 这里。如您所愿,它将25%的时间显示“true”与碰撞。我发现你尝试做的事情有一些问题;您的框计算错误。您可能希望排除边框,因此我已更改代码以从x1,y1和x2,y2中减去它们。要排除边框,您还需要使用innerWidth / innerHeight而不是outerWidth / outerHeight。

最重要的是,您要确保您的矩形不包含额外的像素,只需添加宽度或高度即可。例如,查看这行具有位置的3个字符:
0 1 2
a b c

第一个a(x1)在位置0处。 宽度为3,但当c(r1)应明显位于位置2时,0 + 3 = 3。包含那个额外像素会导致左上角的碰撞出错,并且似乎比实际早得多。像我在下面的代码中所做的那样减去1以解决此问题:

function collision($div1, $div2) {
  var x1 = $div1.offset().left + parseInt($div1.css('borderLeftWidth'),10);
  var y1 = $div1.offset().top + parseInt($div1.css('borderTopWidth'),10);
  var h1 = $div1.innerHeight();
  var w1 = $div1.innerWidth();
  var b1 = y1 + h1 - 1;
  var r1 = x1 + w1 - 1;
  var x2 = $div2.offset().left + parseInt($div2.css('borderLeftWidth'),10);
  var y2 = $div2.offset().top + parseInt($div2.css('borderTopWidth'),10);
  var h2 = $div2.innerHeight();
  var w2 = $div2.innerWidth();
  var b2 = y2 + h2 - 1;
  var r2 = x2 + w2 - 1;

  return (r1 >= x2 && r2 >= x1 && b1 >= y2 && b2 >= y1);
}

两个齿轮同时旋转: 为了实现这一点,您需要完整的多边形检测功能,可以通过旋转后角落形成的多边形的边来进行检测。 我已将角落div添加到黄色区域,添加了调试用的go / stop / step按钮,并使其他div半透明以使其更加明显。 在此处的JSFiddle中,两个齿轮像您的第二个示例一样旋转,并且现在正确显示碰撞。 多边形碰撞代码来自StackOverflow问题


嗨,给我几秒钟,我会向您展示我认为是反例的内容。我还不确定,如果不是的话,那么您的答案将是完美的 :) - Kiwimoisi
这是我的示例,在它们匹配后停止轮子10像素,当你停止它时它确实会显示“真”。当它不断旋转时,状态是正确的,但是一旦你停止轮子,当它们非常接近碰撞时,碰撞状态就会变成错误的。http://jsfiddle.net/HWfMt/175/ @Ed Bayiates - Kiwimoisi
@Kiwimoisi,你用这个新的例子改变了问题。为了让两个齿轮都旋转,我已经编辑了我的答案,需要使用多边形碰撞检测。 - Ed Bayiates
太棒了,昨天我确实看到了这段代码,但没有尝试使用它。 - Kiwimoisi
我试图通过将页面切成四个角并检测旧顶部位置在哪个角落等方法走得太远了...这种方式更加简单和完美。非常感谢您的帮助。KR - Kiwimoisi
显示剩余2条评论

2

如果你要检查的是轴对齐边界框,则交集测试代码是正确的。那么你在这里遇到的问题是你正在检查的盒子坐标是错误的。我不会为你修复这个问题,但我会向你展示如何轻松调试:

添加一个半透明的覆盖层:

<div id="bb" style="background:rgba(0,0,0,0.5); position:absolute;"></div>

请看您正在比较的内容:

$('#bb').offset({left:x1,top:y1}).width(w1).height(y1);

Updated JSFiddle.


嗨,从技术上讲,我需要获取左上角、底部和右侧的顶部,获取整个区域... - Kiwimoisi
是的,之后要非常小心定位,因为任何像素(例如中心像素)都可能导致触摸。 - user
@user,很好的演示了在旋转矩形上仅使用x、y、w、h的非旋转性质。 - Ed Bayiates

0

试试这个演示:

去掉边框和宽度改为50%,原来是49%

演示

或者另一个解决方案

宽度和高度改为calc(50% - 1px),原来是49%,顶部和左侧改为148px,原来是149px

演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接