Reputation: 10627
If you test the following example you'll notice that the console does not log the correct coordinates, .onmouseover
of the box. I know I'm getting the cb
Object before the .onmouseover
, but usually when you access a DOM Object property it gives you the correct value at the time.
var box = document.getElementById('box'), cb = box.getBoundingClientRect();
box.style.margin = '30px';
box.onmousemove = function(e){
console.log('x:'+(e.clientX-cb.left)+'; y:'+(e.clientY-cb.top));
}
#box{
width:160px; height:90px; background:#700;
}
<div id='box'></div>
Notice this way works:
var box = document.getElementById('box');
box.style.margin = '30px';
box.onmousemove = function(e){
var cb = box.getBoundingClientRect();
console.log('x:'+(e.clientX-cb.left)+'; y:'+(e.clientY-cb.top));
}
#box{
width:160px; height:90px; background:#700;
}
<div id='box'></div>
Well, it should work, oddly x
never seems to hit 0
, either (of course I know I can do the math). Is there any valid reason for any of the behavior I've described? I'm using FireFox 69.0.3 (64-bit). Is it a bug? I have a work around. I'm just asking.
Upvotes: 0
Views: 532
Reputation: 29002
The issue is that in the first instance you take cb
before adding the margin.
Since getBoundingClientRect
will give you the positions at the point of time it was called, you get a snapshot of the positions without a 30px offset. That's why both x
and y
never go below 30
in the first example but they do in the second when you get a fresh snapshot of the positions every time.
If you you can get a reliable snapshot once, then the calculation would be correct:
var box = document.getElementById('box');
box.style.margin = '30px';
var cb = box.getBoundingClientRect();
box.onmousemove = function(e){
console.log('x:'+(e.clientX-cb.left)+'; y:'+(e.clientY-cb.top));
}
#box{
width:160px; height:90px; background:#700;
}
<div id='box'></div>
Upvotes: 2
Reputation: 136678
That's simply because a DOMRect is not live. That's just like a plain object that get created every time you call one of the methods that return such an object; and even if the originating Element is modified, the DOMRect will still just be whatever it was when it got created.
const target = document.getElementById( 'target' );
const rect_1 = target.getBoundingClientRect();
target.style.width = '120px';
const rect_2 = target.getBoundingClientRect();
console.log( rect_1.width, rect_2.width ); // 10, 120
#target { width: 10px }
<div id="target"></div>
Upvotes: 1