How to Check If an Element Is Overlapping Other Elements

How to check if an element is overlapping other elements?

Something like this for rect1 and rect2 retrieved via getBoundingClientRect():

var overlap = !(rect1.right < rect2.left || 
rect1.left > rect2.right ||
rect1.bottom < rect2.top ||
rect1.top > rect2.bottom)

Explain: if one or more expressions in the parenthese are true, there's no overlapping. If all are false, there must be an overlapping.

Most performant way to check if elements are overlapping

I figured out a way thru trial and error. I'll post this here for anyone else who could use it.

// dismiss -- just creating less CSSconst randomColor = "#" + ((1 << 24) * Math.random() | 0).toString(16);document.querySelectorAll('.label').forEach((x, i) => {  document.querySelectorAll('.label')[i].style.background = "#" + ((1 << 24) * Math.random() | 0).toString(16);});
//function to check for overlappingfunction overlayCheck() { let points = document.querySelectorAll('.label'); let rightPos = (elem) => elem.getBoundingClientRect().right; let leftPos = (elem) => elem.getBoundingClientRect().left; let topPos = (elem) => elem.getBoundingClientRect().top; let btmPos = (elem) => elem.getBoundingClientRect().bottom;
for (let i = 0; i < points.length; i++) { for (let j = 0; j < points.length; j++) { let isOverlapping = !( rightPos(points[i]) < leftPos(points[j]) || leftPos(points[i]) > rightPos(points[j]) || btmPos(points[i]) < topPos(points[j]) || topPos(points[i]) > btmPos(points[j]) );
if (isOverlapping && j !== i) { points[i].innerHTML = `${points[i].innerHTML} C`; } } }}overlayCheck();
.parent {  position: relative;  display: flex;}
.label { height: 75px; left: 0; width: 100px; margin-left: 10px; background-color: orange}
.cover { width: 220px; position: absolute; left: 0; height: 50px; bottom: 0;}
<div class="parent">  <div class="label cover">Label 1</div>  <div class="label">Label 2</div>  <div class="label">Label 3</div>  <div class="label">Label 4</div>  <div class="label">Label 5</div>  <div class="label">Label 6</div></div>

Detecting if Html element is overlapping another Html element

You can do that by finding the offset of the elements, then finding the width & height of each. It's then just a matter of simple math to determine if they're overlapping.

I'm not going to do all the work for you, but this should get you on the right track:

<div id="one"></div>
<div id="two"></div>

<script>
var offsetOne = $('#one').offset();
var offsetTwo = $('#two').offset();
var widthOne = $('#one').width();
var widthTwo = $('#two').width();
var heightOne = $('#one').height();
var heightTwo = $('#two').height();
</script>

All that's left is to use the two offset's .top & .left along with the widths and heights to determine if there's an overlap. Check out the links to documentation in each of the functions in the first paragraph of my answer.

Check if two or more DOM elements overlap

After looking at the code, it seems overly complex to check the rendered elements for collision when you can work this out from the start and end times.

The way I've done it, is to group events which collide in arrays like so:

let collisions = [
// only 1 event in this array so no collisions
[{
start: 30,
end: 120
}],
// 3 events in this array which have overlapping times
[{
start: 300,
end: 330
}, {
start: 290,
end: 330
}, {
start: 300,
end: 330
}]
];

Then we iterate through each group of collisions, and create the elements with the appropriate width and positioning.

for (var i = 0; i < collisions.length; i++) {
var collision = collisions[i];

for (var j = 0; j < collision.length; j++) {
var event = collision[j];

let height = event.end - event.start;
let top = event.start + 50;

// 360 = max width of event
let width = 360 / collision.length;

// a lot of this could be moved into a css class
// I removed the "display: inline-block" code because these are absolutely positioned. Replaced it with "left: (j * width)px"
let div = $(`<div id=${'e-'+ (i + j)}>`).css('position', 'absolute').css('top', top)
.css('height', height).css('width', width).css('left', (j * width) + 'px')
.css('backgroundColor', arrayOfColors.shift()).addClass('event')
.text('New Event').css('fontWeight', 'bold');

// append event div to parent container
$('#events').append(div);
}
}

//**********************************************************************////  TITLE     - Thought Machine Coding Challenge, Single Day Calendar//  AUTHOR    - DOUGLAS WISSETT WALKER//  DATE      - 21/04/2016//  VERSION   - 0.0.3//  PREVIOUS  - 0.0.2////**********************************************************************
let arr = [{ start: 30, end: 120}, { start: 70, end: 180}, { start: 80, end: 190}, { start: 300, end: 330}, { start: 290, end: 330}, { start: 220, end: 260}, { start: 220, end: 260}, { start: 220, end: 260}, { start: 220, end: 260}, { start: 400, end: 440}, { start: 20, end: 200}];
let renderDay;$(document).ready(() => {
renderDay = function(array) { $('.event').each(function(i, el) { $(el).remove(); });
// background colors for events let arrayOfColors = [ 'rgba(255, 153, 153, 0.75)', 'rgba(255, 204, 153, 0.75)', 'rgba(204, 255, 153, 0.75)', 'rgba(153, 255, 255, 0.75)', 'rgba(153, 153, 255, 0.75)', 'rgba(255, 153, 255, 0.75)' ]
let collisions = mapCollisions(array);
let eventCount = 0; // used for unique id for (let i = 0; i < collisions.length; i++) { let collision = collisions[i];
for (let j = 0; j < collision.length; j++) { let event = collision[j];
let height = event.end - event.start; let top = event.start + 50;
// 360 = max width of event let width = 360 / collision.length;
// a lot of this could be moved into a css class // I removed the "display: inline-block" code because these are absolutely positioned // Replaced it with "left: (j * width)px" let div = $("<div id='e-" + eventCount + "'>").css('position', 'absolute').css('top', top) .css('height', height).css('width', width).css('left', (j * width) + 'px') .css('backgroundColor', arrayOfColors.shift()).addClass('event') .text('New Event').css('fontWeight', 'bold');
eventCount++; // append event div to parent container $('#events').append(div); } } }
renderDay(arr);});
// Sorry this is pretty messy and I'm not familiar with ES6/Typescript or whatever you are usingfunction mapCollisions(array) { let collisions = [];
for (let i = 0; i < array.length; i++) { let event = array[i]; let collides = false;
// for each group of colliding events, check if this event collides for (let j = 0; j < collisions.length; j++) { let collision = collisions[j];
// for each event in a group of colliding events for (let k = 0; k < collision.length; k++) { let collidingEvent = collision[k]; // event which possibly collides
// Not 100% sure if this will catch all collisions if ( event.start >= collidingEvent.start && event.start < collidingEvent.end || event.end <= collidingEvent.end && event.end > collidingEvent.start || collidingEvent.start >= event.start && collidingEvent.start < event.end || collidingEvent.end <= event.end && collidingEvent.end > event.start) { collision.push(event); collides = true; break; }
}
}
if (!collides) { collisions.push([event]); } }
console.log(collisions); return collisions;}
html,body {  margin: 0;  padding: 0;  font-family: sans-serif;}#container {  height: 100%;  width: 100%;}#header-title {  text-align: center;}#calendar {  width: 400px;  height: 620px;  margin-top: 70px;}#events {  position: absolute;  top: 80px;  left: 100px;  width: 800px;  height: 620px;}.event {  box-shadow: 0 0 20px black;  border-radius: 5px;}.hr-block {  border-top: 2px solid black;  height: 58px;  margin: 0;  padding: 0;  margin-left: 100px;  min-width: 360px;  opacity: .5;}.hr-header {  position: relative;  top: -33px;  left: -68px;}
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/responsive.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script charset="UTF-8" src="js/moment.js"></script> <script charset="UTF-8" src="js/script2.js"></script> <title>Thought Machine Code Challenge</title></head>
<body>
<div id="container"> <div class="header"> <h1 id="header-title"></h1> </div> <div id="calendar"> <div class="hr-block"> <h2 class="hr-header">09:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">10:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">11:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">12:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">13:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">14:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">15:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">16:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">17:00</h2> </div> <div class="hr-block"> <h2 class="hr-header">18:00</h2> </div> </div> </div>
<div id="events">
</div>
<script> document.getElementById("header-title").innerHTML = moment().calendar(); </script></body>
</html>

Detect overlapping between fixed item element and multiple static elements

Simply because your apply the logic for each one and thus only the last one is considered. Each one will change the font color for the same element and only the last change will remain.

For example, when you are in the first black box you will test all the three. The first will give true, the second false, the third false and you will endup with false because it's the last. That's why it only works with the last because when the last gives true, you will get the white color after the other two have applied the black color.

Instead you need to apply an OR logic and when one gives true you stop and don't check the others:

function collision($fixed, $moving) {  var x1 = $fixed.offset().left;  var y1 = $fixed.offset().top;  var h1 = $fixed.outerHeight(true);  var w1 = $fixed.outerWidth(true);  var b1 = y1 + h1;  var r1 = x1 + w1;  var x2 = $moving.offset().left;  var y2 = $moving.offset().top;  var h2 = $moving.outerHeight(true);  var w2 = $moving.outerWidth(true);  var b2 = y2 + h2;  var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false; return true;}
$(window).scroll(function() { var all = $(".moving"); for (var i = 0; i < all.length; i++) { if (collision($(".fixed"), all.eq(i))) { $('.fixed').css('color', 'white'); break; //no need to test the others ! } else { $('.fixed').css('color', 'black'); } } });
.fixed {  color: black;  position: fixed;  top: 50px;}
.moving { width: 400px; height: 100px; background-color: black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="fixed"> Fixed Element</div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="moving"></div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="moving"></div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="moving"></div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

How to detect elements overlapping (overlaying) using JavaScript?

function isObjOnObj(a,b){
var al = a.left;
var ar = a.left+a.width;
var bl = b.left;
var br = b.left+b.width;

var at = a.top;
var ab = a.top+a.height;
var bt = b.top;
var bb = b.top+b.height;

if(bl>ar || br<al){return false;}//overlap not possible
if(bt>ab || bb<at){return false;}//overlap not possible

if(bl>al && bl<ar){return true;}
if(br>al && br<ar){return true;}

if(bt>at && bt<ab){return true;}
if(bb>at && bb<ab){return true;}

return false;
}


Related Topics



Leave a reply



Submit