【问题标题】:How to detect if an element is covered/overlapped by another one?如何检测一个元素是否被另一个元素覆盖/重叠?
【发布时间】:2015-12-19 05:13:03
【问题描述】:

我有一个问题,我想检测一个元素是否在一页中被另一个元素覆盖。

例如:

DOM elements
<div class="ele ele1"><p>A</p></div>
<div class="ele ele2"><p>B</p></div>
<div class="ele ele3"><p>C</p></div>
<div class="cover"><p>D</p></div>


CSS style
.ele{
   display: inline-block;
   width: 100px;
   height: 100px;
   position: relative;
}
p{   
  width: 100%;
  text-align: center;
}
.ele1{
  background-color: red;
}
.ele2{
  background-color: blue;
}
.ele3{
  background-color: green;
}
.cover{
   position: absolute;
   width: 100px;
   height: 100px;
   left: 300px;
   top: 10px;
   background: grey;
}

http://jsfiddle.net/veraWei/6v89b1fy/

如何检测元素A未被覆盖但元素C被ele D覆盖? 还有一件事:“D”的数量是不确定的。页面中可能有 E/F/G...。 我感谢所有想法或现有示例/jQuery 插件/CSS/等。

感谢大家的详细回答。但是我需要更简短的解释,也许一个属性表明 A 没有被任何元素覆盖,而 C 被渲染覆盖。是否存在任何插件或属性?

【问题讨论】:

  • 不明白这个问题。你说的被覆盖是什么意思?你的意思是重叠元素吗?
  • 你的意思是c被d覆盖了?
  • 抱歉,我更新了编辑。 A,B,C,D只是一个符号,我的意思是如何检测在C区域之外我们无法看到完整区域的称为D的元素?但是我们可以看到 A 和 B 的所有像素。
  • 如果您想检查该元素是否被任何其他元素从左侧或右侧或顶部或底部覆盖,这个问题的答案将非常复杂..
  • var coverLeft = $(".cover").offset().left; if (coverLeft &gt;= $(".ele3").offset().left &amp;&amp; coverLeft &lt;= $(".ele3").offset().left + $(".ele3").width()) { console.log("element C is (horizontal)covered") }

标签: javascript jquery


【解决方案1】:

这里有一个简单的例子,说明你可以如何去做。这将检查 both 垂直和水平重叠。这是一种通用且不那么通用的方法,因为它基于您问题中的 HTML。调整 .cover 的顶部/左侧值以查看它适用于所有可能的情况。

var $cover = $(".cover"),
  cWidth = $cover.width(),
  cHeight = $cover.height(),
  cLeft = $cover.offset().left,
  cRight = $(window).width() - (cLeft + cWidth),
  cTop = $cover.offset().top,
  cBtm = $(window).height() - (cTop + cHeight);

$("div:not(.cover)").each(function() {

  var $this = $(this),
    eleWidth = $this.width(),
    eleHeight = $this.height(),
    eleLeft = $this.offset().left,
    eleTop = $this.offset().top,
    eleRight = $(window).width() - (eleLeft + eleWidth),
    eleBtm = $(window).height() - (eleTop + eleHeight);

  if (
    cLeft < (eleLeft + eleWidth) &&
    cRight < (eleRight + eleWidth) &&
    cTop < (eleTop + eleHeight) &&
    cBtm < (eleBtm + eleHeight)
  ) {
    alert($this.text() + " is covered by " + $cover.text());
  }
});
.ele {
  display: inline-block;
  width: 100px;
  height: 100px;
  position: relative;
  margin-top: 40px;
}
p {
  width: 100%;
  text-align: center;
}
.ele1 {
  background-color: red;
}
.ele2 {
  background-color: blue;
}
.ele3 {
  background-color: green;
}
.cover {
  position: absolute;
  width: 100px;
  height: 100px;
  left: 60px;
  top: 110px;
  background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ele ele1">
  <p>A</p>
</div>
<div class="ele ele2">
  <p>B</p>
</div>
<div class="ele ele3">
  <p>C</p>
</div>
<div class="ele ele3">
  <p>D</p>
</div>
<div class="ele ele3">
  <p>E</p>
</div>
<div class="ele ele3">
  <p>F</p>
</div>
<div class="ele ele3">
  <p>G</p>
</div>
<div class="cover">
  <p>COVER</p>
</div>

【讨论】:

  • 感谢您在这里编码。但我认为循环所有元素并不是最合适的方式。在实际情况下,会有很多元素,而且它们都是动态的。所以我最需要的是它们是否是指示元素被覆盖的属性,该属性将返回true还是false?
【解决方案2】:

为什么不尝试以下方法:

1) 查找元素相对于视口的位置:

rect=elt.getBoundingClientRect();
x=rect.left;
y=rect.top;

(或者可以考虑中点坐标)

2) 找到位置 x, y 的顶部元素:

topElt=document.elementFromPoint(x,y);

3) 检查顶部元素是否与原始元素相同:

if(elt.isSameNode(topElt)) console.log('no overlapping');

【讨论】:

【解决方案3】:

好的。我经历了所有重叠情况创建了这个fiddle。我使用了getBoundintClientRect(),并用它来获取topleftbottomright 两个divs 的值,在这些divs 上要检查重叠,然后我比较了偏移量使用各种条件语句和条件,您将在下面找到。在小提琴中,所有四个元素都有position: absolute,调整它们的topleft 值以使它们彼此重叠并检查两个元素是否重叠?传递函数中的两个元素 -

checkElements(elA, elB); // pass two elements to check

这是最后一个。

您会在小提琴中看到很长的 if else 条件,它们只是用于测试所有重叠的可能性。这是用于检查重叠的所有可能条件 -

if((eleB.top >= eleA.top && eleB.top <= eleA.bottom) || (eleB.bottom >= eleA.top && eleB.bottom <= eleA.bottom)) {
    if((eleB.left >= eleA.left && eleB.left <= eleA.right) || (eleB.right >= eleA.left && eleB.right <= eleA.right)) {
        el1.innerHTML = '<p>covered</p>';
    }
    else {
        el1.innerHTML = '<p>not covered</p>';
    }
}
else {
    el1.innerHTML = '<p>not covered</p>';
}

您还会看到 B 是否与 A 重叠,那么它将写为 A 被覆盖,因为我已经使用 A 和 B 的 x 和 y 坐标进行了比较。在这种情况下,我认为需要进行额外的条件检查z-index 将被使用。我没有为此创建。

检查fiddle,调整topleft不同元素的值,然后在函数checkElements()中传递两个元素,看看结果是否正确。

您也可以同时进行所有检查 -

checkElements(elA, elB); // check if A is overlapped by B
checkElements(elB, elC); // check if B is overlapped by C
checkElements(elC, elD); // check if C is overlapped by D

使用多重检查查看此fiddle

编辑:如果循环是问题,那么您可以像这样将if else 的所有循环组合成一个if else -

if(((eleB.top >= eleA.top && eleB.top <= eleA.bottom) || (eleB.bottom >= eleA.top && eleB.bottom <= eleA.bottom)) && ((eleB.left >= eleA.left && eleB.left <= eleA.right) || (eleB.right >= eleA.left && eleB.right <= eleA.right))) {
    el1.innerHTML = '<p>covered</p>'; // or your code of adding true to the attribute that tells about overlapping
}
else {
    el1.innerHTML = '<p>not covered</p>';
}

Updated fiddle

【讨论】:

  • 好的,我明白了。没有这样的内置属性很糟糕。也许我应该考虑另一种方法来解决实际项目中的问题。非常感谢。
【解决方案4】:

你在寻找这样的东西吗?

http://jsfiddle.net/6v89b1fy/4/

var coverElem = $(".cover");
var elemArray = [];
elemArray.push($(".ele1"), $(".ele2"), $(".ele3"));

for(i=0; i< elemArray.length; i++)
{
    var currElemOffset = elemArray[i].offset();
    var currElemWidth = elemArray[i].width();

    var currElemStPoint = currElemOffset.left ;
    var currElemEndPoint = currElemStPoint + currElemWidth;


    if(currElemStPoint <= coverElem.offset().left &&  coverElem.offset().left <=  currElemEndPoint)
    {
        elemArray[i].append("<span>Covered</span>");
    }
    else
    {
        elemArray[i].append("<span>Not covered</span>");
    }
}

【讨论】:

  • 非常感谢,对于一定数量的元素,上面的代码是有效的。但我认为我的要求是不确定数的元素。
  • 在这种情况下,您必须将一个集合中的基本元素分组并覆盖另一个集合中的元素。现在必须根据覆盖元素集合中存在的每个元素检查第一组中的每个元素。你可以很容易地调整上面的代码来启用它。如果您需要更多帮助,请告诉我。
  • 此方法无法捕捉到所有可能的“覆盖”某物的方式,例如jsfiddle.net/2kr1s5r5 右边的那个被错误地标记为未覆盖。
  • @DrunkWolf - 是的......你是绝对正确的。这不是完整的代码。但是是的..这段代码可以作为进一步开发的起点。在这里,我们只是提供帮助,而不是提供完整的解决方案。
  • 这不会处理为元素设置z-index的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
  • 2013-06-06
  • 2012-08-17
相关资源
最近更新 更多