How to check if an element is overlapping other elements? [duplicate] - javascript

This question already has answers here:
jQuery/JavaScript collision detection
(7 answers)
Closed 6 years ago.
I have two div elements. Each of them have 450px width and height. How do I check if the first div is overlapping the second div?
I've tried to use javascript hittest, but it's a little bit complicated. Since I'm trying to find out how it actually work, I would like to get started with a simpler code.
I found out that I can use .getClientRects to get the boundary of an element, but I'm not exactly sure how to compare boundaries.
Please advise me!

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.

Here's something I made some days ago: https://gist.github.com/yckart/7177551
var AABB = {
collide: function (el1, el2) {
var rect1 = el1.getBoundingClientRect();
var rect2 = el2.getBoundingClientRect();
return !(
rect1.top > rect2.bottom ||
rect1.right < rect2.left ||
rect1.bottom < rect2.top ||
rect1.left > rect2.right
);
},
inside: function (el1, el2) {
var rect1 = el1.getBoundingClientRect();
var rect2 = el2.getBoundingClientRect();
return (
((rect2.top <= rect1.top) && (rect1.top <= rect2.bottom)) &&
((rect2.top <= rect1.bottom) && (rect1.bottom <= rect2.bottom)) &&
((rect2.left <= rect1.left) && (rect1.left <= rect2.right)) &&
((rect2.left <= rect1.right) && (rect1.right <= rect2.right))
);
}
};

element.getBoundingClientRect() is quiet good in modern browsers, delivers a bounding relative to the screen. look here Than test if the bounding boxes overlap, that is simple geometry...
oh excuse me... found your edit too late...

In Internet Explorer earlier than version 8, the returned TextRectangle object contains the coordinates in physical pixel size, while from version 8, it contains the coordinates in logical pixel size.
If you need the bounding rectangle of the entire element, use the getBoundingClientRect method.

Related

Dynamic element hit detection system not working

Within my project I have a character that automatically walks down the screen. I want to detect whenever the character hits a certain dungeon (each "dungeon" is a div with some text inside).
Here is my code in a simplified format:
//call the function
console.log(isCollide(characterData[0][0], document.getElementsByClassName("Dungeon_Wrapper_Room")[a])));
var isCollide = function(a, b) {
//Used to parse get the x/y pixel coordinates by removing the "px" at the end of the string.
var aTOPstr = a.style.top;
var aTOP = (parseInt(aTOPstr.slice(0, aTOPstr.length-2)));
var aLEFTstr = a.style.left;
var aLEFT = (parseInt(aLEFTstr.slice(0, aLEFTstr.length-2)));
var bTOPstr = b.style.top;
var bTOP = (parseInt(bTOPstr.slice(0, bTOPstr.length-2)));
var bLEFTstr = b.style.left;
var bLEFT = (parseInt(bLEFTstr.slice(0, bLEFTstr.length-2)));
console.log(((aTOP + 32) > (bTOP))+" "+(aTOP < (bTOP - 32))+" "+((aLEFT + 32) > bLEFT)+" "+(aLEFT < (bLEFT + 50)));
return (
!((aTOP + 32) < (bTOP)) ||
(aTOP > (bTOP + 50)) ||
((aLEFT + 32) < aLEFT) ||
(aLEFT > (aLEFT + 50))
);
};
The character image was created dynamically (in the end I'll use a for loop to run through an array of characters, each with this detection).
var characterData = [
[document.createElement("img"), {/*Misc. Character Data Goes Here*/}]
];
characterData[0][0].src = "images/characters/default.png";
characterData[0][0].style.position = "relative";
characterData[0][0].style.left += ((50-32)/2)+"px";
characterData[0][0].style.top += (-(50-32+25))+"px";
characterData[0][0].id = "character0";
tavernBox.appendChild(characterData[0][0]);
My HTML:
<div id="Town_Wrapper">
<div id="townBoxWrapper">
<div id="tavernBox">
<!-- Characters are appended here -->
</div>
</div>
</div>
<div id="Dungeon_Wrapper">
<div class='Dungeon_Wrapper_Room'>Boss
<!--Box character is being detected with-->
</div>
</div>
I've based my hit detection off the answer I found here: https://stackoverflow.com/a/7301852/7214959 but still am having no success.
I have absolutely no clue what is wrong with it. I've tried switching the < around and other functions but still can't find anything. I've also tried going from relative to absolute positioning and still got nothing. The isCollide function needs to return true or !false to indicate it has collided but each section of the if statement always returns "false" and there is never a single "true".
JSFiddle (contains debugging for console and alert): https://jsfiddle.net/drfyvLng/
Solved: The selected answer solves the issue presented in the jsfiddle. Within my own code I had to turn the certain dungeon into absolute positioning and find its location use .offsetTOP and .offsetLEFT. Additionally I made the return formula detect when the character is inside the box rather than when it isn't.
There were a few issues with the JSfiddle.
This was evaluating to null because there's no top set in the css style.
var bTOPstr = b.style.top;
Update your CSS to this and that part is covered.
<div class='Dungeon_Wrapper_Room' style="background-color: yellow; min-height:50px; top:0px; bottom:50px; left:0px; right:100px">
Then your if statement that checks collision is different to the one you based it off, be careful when copying code!
!((aTOP + 32) < (bTOP)) ||
(aTOP > (bTOP + 50)) ||
((aLEFT + 32) < aLEFT) ||
(aLEFT > (aLEFT + 50))
aLeft + 32 < aLeft should be aLeft + 32 < bLeft
aLeft > aLeft + 50 should be aLeft > bLeft + 50
Finally, you need another bracket on the if statement. The answer your based it off is checking '!' on the entire expression, yours just uses the first line.
So now it looks like this.
!(((aTOP + 32) < (bTOP)) ||
(aTOP > (bTOP + 50)) ||
((aLEFT + 32) < bLEFT) ||
(aLEFT > (bLEFT + 50)))
Which should work.

Javascript check if div overlaps other div

I can't get my head around this problem, so i hope that you guys can help me fixing it.
The thing is that I want to check if an div is overlapping an another div when they are dynamically added to the body.
Let's say that I've got an first div with the following information:
X1 = 316, X2 = 440
This is being calculated with the information that an box has an length of 60px and 1px margin around him. Also, the exL stands for the amount of 'boxes' inside the div ( in this test case it's 2, but it will be many more... ) So the code to calculate that is:
var X2 = ( oldX1 + ( kist_length * exL ) + ( 2 * exL))
I've got this code so far:
// X:
oldX1 = ( 316 );
oldX2 = ( oldX1 + ( kist_length * exL ) + ( 2 * exL));
newX1 = ( 99 );
newX2 = ( newX1 + ( kist_length * newLength ) + ( 2 * newLength));
if( (newX1 >= oldX1 || newX1 <= oldX2) || ( newX2 >= oldX2 || newX2 <= oldX2) ){
console.log("X is overlapping...");
}
If i use the code above the program says it's overlapping, but as you can see below, that's not true. the values that the checker is using are ( + kisten stands for + the length ( so the boxes + length of box * times of boxes ):
newX = 99
newX + kisten = 223
oldX = 316
oldX + kisten = 440
I know that it's because the OR statement. But if I use AND statements between the () inside the if, it's not working 100% to. Let's take a look at the following picture:
First I've placed Box1. After that I've placed Box2, that succeeded without the warning about an overlapping. But X is overlapping...( not the Y, but the X is... ). When i place Box3, i do get the warning that X is overlapping...
So my question is rather simple ( but i guess the answer isn't... ), What do I wrong with the check? Which part of the if statement did i do wrong?
I guess there is a typo in your script, since newX2 >= oldX2 || newX2 <= oldX2 is always true :-)
But the condition in order to not have any overlapping is that (I reason on segments since you are dealing axis by axis here) new segment is before the old one :
newX1----------------newX2 oldX1---------------oldX2
or the second one is after first one :
oldX1---------------oldX2 newX1----------------newX2
So the corresponding condition is the following one :
function overlaps() {
var minOldX = Math.min(oldX1, newX1),
maxOldX = Math.max(oldX1, newX1),
minNewX = Math.min(oldX2, newX2),
maxNewX = Math.max(oldX2, newX2);
return (
maxNewX <= minOldX || // <- first case
minNewX >= maxOldX // <- second case
);
}

Display images according to number set from interval

i try to display from svg ,layers according to numbers set from an interval.I have 2 random numbers (left and right) set to display from interval (10,99) both.That works good,but, i need to display layer 1(banane1) from svg if left || right belongs to interval (10,20) , then if left || right belongs to interval (20,30) to display layer 2(banane2) from svg and so on untill left || right belongs to interval (90,99) to display layer 9(banane9). There are 9 intervals and 9 layers from svg to display. Code i wrote looks like :
FIDDLE: http://jsfiddle.net/r68Bg/
for(var i = 0; i < 2; i++){
panouri = document.getElementById('panou' + i);
svgDoc = panouri.contentDocument;
}
where panou0 and panou1 are 2 svg that has layers 2 numbers where i display later random numbers set from intervals and 9 layers each with different content which must be displayed according to random numbers.
function randomIntFromInterval(min,max)
{
return Math.floor(Math.random()*(max-min+1)+min);
};
function conditions(){
left = randomIntFromInterval(10,99);
right = randomIntFromInterval(10,99);
for(var i = 0; i < 2; i++){
ecuations.push(left, right);
randoms = document.getElementById("panou" + i).contentDocument;
numere = randoms.getElementById("number");
numere.textContent = ecuations[i];
}
};
where i add into my svg (panou0 and panou1) randoms numbers from set intervals.
function setBananeState(state)
{
for(var i = 1; i < 10; i++){
svgItem = svgDoc.getElementById("banane" + i);
svgItem.setAttribute("display", "none");
svgItem = svgDoc.getElementById(state);
svgItem.setAttribute("display", "inline");
}
};
function getBanane(){
if(left || right >= 30 && left || right <= 40){
bananeState = "banane3";
setBananeState(bananeState);
}
};
Here i have all layers from svgs which contains bananas to display according to random number given and a function getBanane() which has condition to display layer1 (banane1 by id from svg) if random number is from interval (10,20).Unfortunately this doesnt work...and i must have 8 more condition to display layers from svg if random numbers are from different interval
This isn't going to work:
if(left || right == randomIntFromInterval(10,20)){
What you are doing here is a ORing left with right which will give you a boolean which you are then comparing to randomIntFromInterval. I think what you are trying to do is this:
var interval = randomIntFromInterval(10,20);
if (left == interval || right == interval) {
EDIT: Okay you changed your question. So now this:
if(left || right >= 30 && left || right <= 40){
Is not right, you can't write an if statement like that in javascript, or in most (probably all) programming languages. You can't say "if a or b is greater than x", like you would in normal English speech because it's ambiguous. You have to explicitly say "if (a is greater than x) or (b is greater than x)". So your if statement above needs to become:
if ((left >= 30 || right >=30) && (left <= 40 || right <= 40)) {
Although I'm not sure this is exactly what you want either. Because here if left==0 and right==41, then this statement would be true. I think you want either left or right to be in the interval, so your best check would be:
if ((left >= 30 && left <= 40) || (right >= 30 && right <= 40)) {

Check if element is in user sight vertically

I'm looking for a function that would get an element from the DOM and determine whether it is in the sight of the user vertically?
I searched for a function that would get an element and check if it is in the current scroll height the user is viewing. I ended up trying a bunch of functions that didn't quite do what I needed and I built my own. Since I didn't find such function I'm now sharing it with you guys in case someone needs it in future! :P This is without using any frameworks or plugins.
function visible(a, t){
// a => element
// t => tolerance, how much pixels can be hidden and still return true
var w_top = window.pageYOffset || document.documentElement.scrollTop,
w_hgh = window.outerHeight,
a_top = 0,
a_hgh = a.offsetHeight;
while(a.tagName.toLowerCase() !== 'body') {
a_top += a.offsetTop;
a = a.offsetParent;
}
var b = (w_top + w_hgh) - (a_top + a_hgh);
if(b > (0 - t) && b < (w_hgh - a_hgh + t)){
return true;
}
return false;
}
An example in use:
var element = document.getElementById('id');
if(!visible(element, 50)){
element.focus();
}

Display Div relative to Href element

Need to position a div based on the href element position in the page.
The code which I currentl have works on my machine which runs IE8.
The same code does not work on another machine with same configuration . Please help
BTW , the div is absolutely position and in the javascript we have:
divobj.style.left = event.x - 185;
divobj.style.top = event.y - 5;
try to use this function.
function getElementPosition(element) {
var x = 0; var y = 0;
while(element !=null ) {
x += element.offsetLeft || 0;
y += element.offsetTop || 0;
element = element.offsetParent;
if (!element || element.style['position'] == 'relative' || element.tagName == 'BODY') break;
}
return {'x':x, 'y':y};
}
it will retrun the position of your link element, but you have to pass that element as argument to this function.
The solution might be as simple as adding a unit of measurement, e.g.:
divobj.style.left = event.x - 185 + 'px'; divobj.style.top = event.y - 5 + 'px';
Some browsers assume 'px' as the unit of measurement; others don't make an assumption and therefore do nothing with what they consider an invalid value.

Categories