文本重叠检测具有奇怪的行为

时间:2017-10-18 09:31:07

标签: javascript jquery html css

我试图检测div.text何时位于另一个之上(在父div#element内),父母的背景应根据重叠的存在而改变。

问题在于,如果没有重叠,脚本仍会检测到一个,这可能是因为每个.text再次将自己的位置与自身进行比较。



$(".text").each(function() {
  var self_text = $(this),
    self_textid = self_text.attr('id'),
    self_textLeft = self_text.position().left,
    self_textTop = self_text.position().top,
    self_textWidth = self_text.width(),
    self_textHeight = self_text.height();

  $(".text").each(function() {
    var self_shape = $(this),
      self_shapeLeft = self_shape.position().left,
      self_shapeTop = self_shape.position().top,
      self_shapeWidth = self_shape.width(),
      self_shapeHeight = self_shape.height();

    // check if .text overlaps
    if (
      (self_textLeft + self_textWidth) > self_shapeLeft &&
      self_textLeft < (self_shapeLeft + self_shapeWidth) &&
      (self_textTop + self_textHeight) > self_shapeTop &&
      self_textTop < (self_shapeTop + self_shapeHeight)
    ) {
      // overlap
      $('#elements').css('background', 'red');
    } else {
      // no overlap
      $('#elements').css('background', 'green')
    }
  });
});
&#13;
#elements,
.text {
  position: absolute;
}

.text {
  width: 50px;
  background: blue;
}

#elements {
  height: 250px;
  width: 400px;
  background: yellow;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="elements">
  <div class="text" style="left: 20px; top: 20px;">text1</div>
  <div class="text" style="left: 100px; top: 50px;">text2</div>
  <div class="text" style="left: 10px; top: 200px;">text3</div>
  <div class="text" style="left: 10px; top: 45px;">text4</div>
</div>
&#13;
&#13;
&#13;

如果在不更改.text类的情况下再次循环,我怎么能告诉脚本忽略它自己呢?还有什么方法可以改进代码吗?

2 个答案:

答案 0 :(得分:4)

这是因为你要包含div本身来检查,尝试将其添加到not:

&#13;
&#13;
var $textDivs = $(".text"); // cache this so you are not performing the lookup every time in your loop
$textDivs.each(function() {
  var self_text = $(this),
    self_textid = this.id,
    self_textLeft = self_text.position().left,
    self_textTop = self_text.position().top,
    self_textWidth = self_text.width(),
    self_textHeight = self_text.height(),
    hasNotMatched = true;

  $textDivs.not(self_text).each(function() { // added to a not so not checked against itself
    var self_shape = $(this),
      self_shapeLeft = self_shape.position().left,
      self_shapeTop = self_shape.position().top,
      self_shapeWidth = self_shape.width(),
      self_shapeHeight = self_shape.height();

    // check if .text overlaps
    if (
      (self_textLeft + self_textWidth) > self_shapeLeft &&
      self_textLeft < (self_shapeLeft + self_shapeWidth) &&
      (self_textTop + self_textHeight) > self_shapeTop &&
      self_textTop < (self_shapeTop + self_shapeHeight)
    ) {
      // overlap
      $('#elements').css('background', 'red');
      hasNotMatched = false;

      return false; // break out of each loop so as no need to process anymore and so overlap doesn't turn back green
    } else {
      // no overlap
      $('#elements').css('background', 'green')
    }
  });
  
  return hasNotMatched;    // this will break out of outer loop if matched on inner loop
});
&#13;
#elements,
.text {
  position: absolute;
}

.text {
  width: 50px;
  background: blue;
}

#elements {
  height: 250px;
  width: 400px;
  background: yellow;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="elements">
  <div class="text" style="left:20px; top:20px;">text1</div>
  <div class="text" style="left:100px; top:50px;">text2</div>
  <div class="text" style="left:90px; top:40px;">text3</div>
  <div class="text" style="left:190px; top:30px;">text4</div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

您可以使用

排除当前元素
$(".text").not($(this))

您的解决方案的逻辑也存在问题 - 如果检查的最后一个元素不重叠,则会将背景更改为绿色。处理此问题的一种方法是将背景设置为绿色作为默认值。如果检测到重叠,则将背景更改为红色。

这里可以进行一些优化 - 比如一旦检测到重叠就可以退出。

像这样:

&#13;
&#13;
$(".text").each(function() {
  $('#elements').css('background', 'green');

  var self_text = $(this),
    self_textid = self_text.attr('id'),
    self_textPosition = self_text.position(),
    self_textLeft = self_textPosition.left,
    self_textTop = self_textPosition.top,
    self_textWidth = self_text.width(),
    self_textHeight = self_text.height();

  $(".text").not($(this)).each(function() {
    var self_shape = $(this),
      self_shapePosition = self_shape.position(),
      self_shapeLeft = self_shapePosition.left,
      self_shapeTop = self_shapePosition.top,
      self_shapeWidth = self_shape.width(),
      self_shapeHeight = self_shape.height();

    // check if .text overlaps
    if (
      (self_textLeft + self_textWidth) > self_shapeLeft &&
      self_textLeft < (self_shapeLeft + self_shapeWidth) &&
      (self_textTop + self_textHeight) > self_shapeTop &&
      self_textTop < (self_shapeTop + self_shapeHeight)
    ) {
      // overlap
      $('#elements').css('background', 'red');
    }
  });
});
&#13;
#elements,
.text {
  position: absolute;
}

.text {
  width: 50px;
  background: blue;
}

#elements {
  height: 250px;
  width: 400px;
  background: yellow;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="elements">
  <div class="text" style="left: 20px; top: 20px;">text1</div>
  <div class="text" style="left: 100px; top: 50px;">text2</div>
  <div class="text" style="left: 10px; top: 200px;">text3</div>
  <div class="text" style="left: 10px; top: 45px;">text4</div>
</div>
&#13;
&#13;
&#13;