Find distance between two DIVs using jQuery? - javascript

I have two DIVs that I need to know the calculated browser distance (in height) of them.
I have read about the offset feature but the examples were not written for the way I am trying to do this.
Example usage:
<div class="foo"></div>
<div class="bar"></div>
I want to know the distance between these two.
Please help me to find the distance dynamically with jQuery.

Something like this should work:
$('.foo').offset().top - $('.bar').offset().top
As long as each class only has one element on the page.
If they are not unique, give the two elements an ID and reference with that.

Use .offset():
$('.foo').offset().top - $('.bar').offset().top

This function finds the distance in pixels between the centre of two elements, no jquery:
function distanceBetweenElems(elem1, elem2) {
var e1Rect = elem1.getBoundingClientRect();
var e2Rect = elem2.getBoundingClientRect();
var dx = (e1Rect.left+(e1Rect.right-e1Rect.left)/2) - (e2Rect.left+(e2Rect.right-e2Rect.left)/2);
var dy = (e1Rect.top+(e1Rect.bottom-e1Rect.top)/2) - (e2Rect.top+(e2Rect.bottom-e2Rect.top)/2);
var dist = Math.sqrt(dx * dx + dy * dy);
return dist;
}
I use it like this:
var target1 = document.querySelector('#foo');
var target2 = document.querySelector('#bar');
if (distanceBetweenElems(target1,target2)<100){
target1.classList.add('active');
}

Related

How to assign values to a jquery object using for loop

I have tried several ways to create a parallax effect on my images where each image has it's own random speed. I think the best way for me to achieve it is by assigning a speed value to each image. However I am not sure how to do this.
var img_list = [];
$.each($('.gallery_image'), function(e) {
img_list.append($(this));
});
for(x in img_list) {
ran = Math.round(Math.random() * (11 - 1) + 1);
speed = ran.toString() + "px";
x.speed = speed;
}
This is what I came up with. I know that x.speed is not an actual thing, but I am using that to illustrate what I am trying to accomplish.
This is a website that has exactly what I am looking for on the main page, but I want the movement to be on scroll. EXAMPLE
for(var x in img_list) {
var ran = Math.round(Math.random() * (11 - 1) + 1);
img_list[x].speed = ran.toString() + "px";
}
Use push
var img_list = [];
$.each($('.gallery_image'), function(e) {
img_list.push($(this));
});
but in this case you don't need a loop because $('.gallery_image') is a collection of objects
In the second loop you can use a each loop and save the speed as a data attribute:
$('.gallery_image').each(function(i,x){
ran = Math.round(Math.random() * (11 - 1) + 1);
speed = ran.toString() + "px";
$(x).data('speed',speed);
});
I dont know if this is relative or not ,but I made a demo .
Hope this helps.
To move image set left css property of dom.
DEMO
https://jsfiddle.net/vikrant47/yem6f0Ls/4/

Redefining a value for each statement?

In the project that I'm working on I want for different elements to fade in and out as you scroll along.
I defined the opacity of the element as f(x)=a ( x - d ) ^ 2 + e where the opacity would be f(x) and x would be $(window).scrollTop (). e would be >=1.
The elements should fade in and out after each other with slight overlap, so for each element the parabola would have to move further along the x axis.
var alpha = -0.000009 * ((Math.pow($(window).scrollTop () + delta), 2)) + 1;
$('#content').css({'opacity':alpha});
That would be part of a function triggered by scrolling.
This works for element #1 but for the following elements I'd have to change delta. Is there a way to define it's value differently for each element? Or would I have to manually change it for each one? I was hoping to keep this as simple as possible.
Is there a way to define it's value differently for each element?
Yes, you could use an attribute data-delta on each element, and read that as part of your function
<div id="content" data-delta="1.23">Content here</div>
read it with .data("delta") given an element reference
var $elem = $('#content');
var delta = $elem.data("delta");
var alpha = -0.000009 * ((Math.pow($(window).scrollTop () + delta), 2)) + 1;
$elem.css({'opacity':alpha});

Read & change rotate value of an Element in SnapSVG

Pls Check out this incomplete fiddle (https://jsfiddle.net/JayKandari/srqLLd97/).
Markup:
<svg id="paper" ></svg>
<div id="workingArea">
<button onclick="calculateTransform()">Get Transform</button>
<div class="results">
Transform: <span class="transformResult"></span>
</div>
<button onclick="rotateText('add')">Rotate + 10 Degrees</button>
<button onclick="rotateText('sub')">Rotate - 10 Degrees</button>
</div>
JS Code:
console.clear();
var paper = Snap("#paper");
var t = paper.text(0, 0, "SnapSVG is Awesome !");
//Translate to 250, 250 & Scale by 2 & 45Deg Rotate
t.transform('T250,250 S2 R45');
// Enable Drag
t.drag();
var calculateTransform = function() {
var currentTransform = t.transform().string;
console.log('test', currentTransform)
$('.results .transformResult').html(currentTransform)
}
var rotateText = function(op) {
// Read Current Rotate Value here.
var rotateVal = 0;
// add/Subtract based on option
if(op == 'add'){
rotateVal += 10;
}else if(op == 'sub') {
rotateVal -= 10;
}
// Calculate newTransform here.
var newTransform = 'T250,250 R' + rotateVal;
// Update object's rotation here.
t.attr({transform: newTransform });
}
Problems:
Read current transformation applied to Element.
Rotate current Element to a specific value.
What you probably are after in your mind is something like this...
var rotateVal = t.transform().localMatrix.split().rotate;
localMatrix gives the matrix specifically applied to that element.
globalMatrix gives the total matrix applying to that element (eg matrices from outer containers).
diffMatrix gives the difference between localMatrix and globalMatrix.
split() ( docs here ) breaks down that matrix into its elements. So we can find 'rotate' from here.
example fiddle
So this is the answer I think you are after.
However, I would actually design the code the slightly different if this is just a minimal example of a more complex design.
Rather than doing something like transform().localMatrix.split().rotate, I would store your own transform components. So something like...
var rotate = 45;
var tx = 250;
var ty = 250;
...then in func
rotate += +10;
var newTransform = 'T'+tx+','+ty+'R'+rotate;
The reason for this, is that you are now controlling precisely the values, and its not really prone to errors (from the lib or misunderstanding about matrices). If you look at your matrix values you display, you will note there are subtle rounding differences, plus with complex matrix calculations, the values aren't quite what we expect and don't always split in a nice easy way that makes sense.
So if this is the main example, the first bit of code will probably suffice. If you are doing more complex transformations, I would think about controlling the values yourself and building up the transform string like the latter example.

How to get distance between two divs

So I have one div inside the other - how can I get distance between them?
I tried something like $('#child').parentsUntil($('#parent')).andSelf() - but it returns an object, not a distance.
P.S. I need it to push other buttons.
http://api.jquery.com/position/
to get the left distance you can use:
var distLeft = $('#child').position().left;
That will return the distance in px relative to the offset parent
if you're interested into the element's page offset than:
var offsLeft = $('#child').offset().left;
http://api.jquery.com/offset/
There's this awesome getBoundingClientRect function. Anything else is just a-b
https://developer.mozilla.org/en-US/docs/DOM/element.getBoundingClientRect
You can use offset
var childOffset = $('#child').offset(), parentOffset = $('#child').parentsUntil($('#parent')).offset();
var leftDistance =childOffset.left - parentOffset.left;
var topDistance = childOffset.top- parentOffset.top;
Did you try something like?
$('innerDiv').position().left;

JavaScript: Collision detection

How does collision detection work in JavaScript?
I can't use jQuery or gameQuery - already using prototype - so, I'm looking for something very simple. I am not asking for complete solution, just point me to the right direction.
Let's say there's:
<div id="ball"></div>
and
<div id="someobject0"></div>
Now the ball is moving (any direction). "Someobject"(0-X) is already pre-defined and there's 20-60 of them randomly positioned like this:
#someobject {position: absolute; top: RNDpx; left: RNDpx;}
I can create an array with "someobject(X)" positions and test collision while the "ball" is moving... Something like:
for(var c=0; c<objposArray.length; c++){
........ and code to check ball's current position vs all objects one by one....
}
But I guess this would be a "noob" solution and it looks pretty slow.
Is there anything better?
Here's a very simple bounding rectangle routine. It expects both a and b to be objects with x, y, width and height properties:
function isCollide(a, b) {
return !(
((a.y + a.height) < (b.y)) ||
(a.y > (b.y + b.height)) ||
((a.x + a.width) < b.x) ||
(a.x > (b.x + b.width))
);
}
To see this function in action, here's a codepen graciously made by #MixerOID.
An answer without jQuery, with HTML elements as parameters:
This is a better approach that checks the real position of the elements as they are being shown on the viewport, even if they're absolute, relative or have been manipulated via transformations:
function isCollide(a, b) {
var aRect = a.getBoundingClientRect();
var bRect = b.getBoundingClientRect();
return !(
((aRect.top + aRect.height) < (bRect.top)) ||
(aRect.top > (bRect.top + bRect.height)) ||
((aRect.left + aRect.width) < bRect.left) ||
(aRect.left > (bRect.left + bRect.width))
);
}
The first thing to have is the actual function that will detect whether you have a collision between the ball and the object.
For the sake of performance it will be great to implement some crude collision detecting technique, e.g., bounding rectangles, and a more accurate one if needed in case you have collision detected, so that your function will run a little bit quicker but using exactly the same loop.
Another option that can help to increase performance is to do some pre-processing with the objects you have. For example you can break the whole area into cells like a generic table and store the appropriate object that are contained within the particular cells. Therefore to detect the collision you are detecting the cells occupied by the ball, get the objects from those cells and use your collision-detecting function.
To speed it up even more you can implement 2d-tree, quadtree or R-tree.
You can try jquery-collision. Full disclosure: I just wrote this and released it. I didn't find a solution, so I wrote it myself.
It allows you to do:
var hit_list = $("#ball").collision("#someobject0");
which will return all the "#someobject0"'s that overlap with "#ball".
Mozilla has a good article on this, with the code shown below.
2D collision detection
Rectangle collision
if (rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.height + rect1.y > rect2.y) {
// Collision detected!
}
Circle collision
if (distance < circle1.radius + circle2.radius) {
// Collision detected!
}
bcm's answer, which has 0 votes at this time, is actually a great, under-appreciated answer. It uses good old Pythagoras to detect when objects are closer than their combined bounding circles. Simple collision detection often uses rectangular collision detection, which is fine if your sprites tend to be, well, rectangular. If they are circular (or otherwise less than rectangular), such as a ball, an asteroid, or any other shape where the extreme corners are usually transparent, you may find this efficient routine to be the most accurate.
But for clarity, here is a more fully realized version of the code:
function doCollide(x1, y1, w1, x2, y2, w2) {
var xd = x1 - x2;
var yd = y1 - y2;
var wt = w2 + w1;
return (xd * xd + yd * yd <= wt * wt);
}
Where the parameters to pass in are the x,y and width values of two different sprite objects.
This is a lightweight solution I've come across -
function E() { // Check collision
S = X - x;
D = Y - y;
F = w + W;
return (S * S + D * D <= F * F)
}
The big and small variables are of two objects, (x coordinate, y coordinate, and w width)
From here.
//Off the cuff, Prototype style.
//Note, this is not optimal; there should be some basic partitioning and caching going on.
(function () {
var elements = [];
Element.register = function (element) {
for (var i=0; i<elements.length; i++) {
if (elements[i]==element) break;
}
elements.push(element);
if (arguments.length>1)
for (var i=0; i<arguments.length; i++)
Element.register(arguments[i]);
};
Element.collide = function () {
for (var outer=0; outer < elements.length; outer++) {
var e1 = Object.extend(
$(elements[outer]).positionedOffset(),
$(elements[outer]).getDimensions()
);
for (var inner=outer; inner<elements.length; innter++) {
var e2 = Object.extend(
$(elements[inner]).positionedOffset(),
$(elements[inner]).getDimensions()
);
if (
(e1.left+e1.width)>=e2.left && e1.left<=(e2.left+e2.width) &&
(e1.top+e1.height)>=e2.top && e1.top<=(e2.top+e2.height)
) {
$(elements[inner]).fire(':collision', {element: $(elements[outer])});
$(elements[outer]).fire(':collision', {element: $(elements[inner])});
}
}
}
};
})();
//Usage:
Element.register(myElementA);
Element.register(myElementB);
$(myElementA).observe(':collision', function (ev) {
console.log('Damn, '+ev.memo.element+', that hurt!');
});
//detect collisions every 100ms
setInterval(Element.collide, 100);
This is a simple way that is inefficient, but it's quite reasonable when you don't need anything too complex or you don't have many objects.
Otherwise there are many different algorithms, but most of them are quite complex to implement.
For example, you can use a divide et impera approach in which you cluster objects hierarchically according to their distance and you give to every cluster a bounding box that contains all the items of the cluster. Then you can check which clusters collide and avoid checking pairs of object that belong to clusters that are not colliding/overlapped.
Otherwise, you can figure out a generic space partitioning algorithm to split up in a similar way the objects to avoid useless checks. These kind of algorithms split the collision detection in two phases: a coarse one in which you see what objects maybe colliding and a fine one in which you effectively check single objects.
For example, you can use a QuadTree (Wikipedia) to work out an easy solution...
Take a look at the Wikipedia page. It can give you some hints.
hittest.js; detect two transparent PNG images (pixel) colliding.
Demo and download link
HTML code
<img id="png-object-1" src="images/object1.png" />
<img id="png-object-2" src="images/object2.png" />
Init function
var pngObject1Element = document.getElementById( "png-object-1" );
var pngObject2Element = document.getElementById( "png-object-2" );
var object1HitTest = new HitTest( pngObject1Element );
Basic usage
if( object1HitTest.toObject( pngObject2Element ) ) {
// Collision detected
}

Categories

Resources