I want to observe the position of a div element that moves inside a larger container:
The page contains one div with the ID #actual which starts at a known position. Over time, the #actual div changes its position, and I need to run a function when that happens.
The #actual position can change in different ways - via CSS left/top changes, a CSS transform on a parent element, or a sibling changes size and pushes the div up/down.
My current attempt is, to add a hidden div to the page, with the ID #known which starts off at the same position as #actual. Now I try to add an IntersectionObserver that fires when the intersection between #actual and #known changes.
Here's my sample code:
const known = document.querySelector('#known');
const actual = document.querySelector('#actual');
const ioOptions = {
tolerance: 0,
root: known
};
const ioObserver = new IntersectionObserver(ioChange, ioOptions);
function ioChange(entries) {
console.log('Intersection changed:', entries[0].intersectionRect);
}
ioObserver.observe(actual);
Problem
The observer never fires. Why? How can I get the Observer to work?
Or is there a better/different way to detect position changes of #actual?
Click below to see the full sample with the two divs:
const known = document.querySelector('#known');
const actual = document.querySelector('#actual');
// -- Intersection Observer --------
const ioOptions = {
tolerance: 0,
root: known
};
const ioObserver = new IntersectionObserver(ioChange, ioOptions);
function ioChange(entries) {
console.log('Intersection changed:', entries[0].intersectionRect);
}
ioObserver.observe(actual);
// -- Sample animation logic -----
// I expect that this animation constantly triggers the
// ioChange callback above.
// -- Sample animation logic -----
function setKnown() {
known.style.left = actual.style.left;
known.style.top = actual.style.top;
}
function moveBox() {
actual.style.left = (Math.random() * 240) + 'px';
actual.style.top = (Math.random() * 240) + 'px';
}
actual.style.left = '120px';
actual.style.top = '120px';
setKnown();
setInterval(moveBox, 1000);
#root {
position: relative;
margin: 20px auto;
background: #fff;
border: 1px solid #000;
width: 320px;
height: 320px;
box-shadow: 0 0 30px #0002;
box-sizing: border-box;
font: 14px sans-serif;
}
.box {
width: 80px;
height: 80px;
position: absolute;
text-align: center;
line-height: 80px;
white-space: nowrap;
box-sizing: border-box;
}
#known {
background: #8881;
border: 1px dashed #999;
}
#actual {
background: #0068;
color: #fff;
transition: all 0.3s;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id="root">
<div id="known" class="box">Known</div>
<div id="actual" class="box">Actual</div>
</div>
</body>
</html>