魏秋明
魏秋明

Reputation: 229

How to detect if an element is covered/overlapped by another one?

I have a problem that I want to detect if an element is covered by another one in one page.

eg:

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/

How to detect element A is not been covered but element C is covered by ele D? One more thing: the number of "D" is uncertain. Maybe there are E/F/G... in the page. I appreciate all the thoughts or existing examples/jQuery plugins/CSS/etc.

Thanks all your guys' detailed answers. But I need more shortly explanation maybe one attribute that indicate that A is not covered by any elements and C is covered by rendering. Is there any plugin or attribute existing?

Upvotes: 22

Views: 23933

Answers (4)

lshettyl
lshettyl

Reputation: 8181

Here is a quick example of how you may go about doing it. This would check for both vertical and horizontal overlapping. This is kind of generic and not-so-generic as well since this is based off the HTML in your question. Adjust the top/left values of the .cover to see it work for all possible cases.

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>

Upvotes: 3

JaneCC
JaneCC

Reputation: 323

Why not try the following :

1) Find the element position relative to the viewport:

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

(or may be consider the midpoints coordinates)

2) Find the top element at position x, y:

topElt=document.elementFromPoint(x,y);

3) Check if the top element is the same than the original element :

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

Upvotes: 30

Rohit Kumar
Rohit Kumar

Reputation: 2031

OK. I've gone through all cases of overlapping and have created this fiddle. I've used getBoundintClientRect() and have used it to get top, left, bottom, right values of two divs on which overlapping is to be checked and then I've compared the offsets using various conditional statements and conditions too which you'll find below. In the fiddle all your four elements are having position: absolute, adjust their top and left values to make them overlap one another and to check whether two elements are overlapping or not? pass the two elements in the function -

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

which is in the very last.

You will see the long if else conditions in the fiddle, they are just for testing all possibilities of overlapping. Here is that all possible conditions used to check overlapping -

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>';
}

You will also see if B overlaps A then it will write A is covered because I've compared using x and y coordinates of A and B. In this case, I think an additional condition checking z-index will be used. I've not created for that.

Check the fiddle, and adjust top and left values of different elements and then pass two elements in the function checkElements() and see the result is correct or not.

You can also do all the checking simultaneously as -

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

See this fiddle using the multiple checking.

EDIT: If looping is the problem, then you can combine all the loops of if else into a single if else like this -

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

Upvotes: 0

vijayP
vijayP

Reputation: 11502

Are you looking for something like this?

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>");
    }
}

Upvotes: 3

Related Questions