5

In Javascript, when I move an element using the gpu via the translate3d method, the elements style-left position doesnt change at all. As the cpu isnt even aware any motion has occurred.

How do I track what the new position of an element is, after moving it via translate3d?

john-jones
  • 7,490
  • 18
  • 53
  • 86
  • 1
    You don't need to use jQuery, `getBoundingClientRect` can give you the current element position even transformed by CSS3. – Roko C. Buljan Feb 03 '15 at 17:34

3 Answers3

7

Use Element.getBoundingClientRect() to get the element coordinates

Here's just a small example that retrieves the .left Rect property from a CSS3 translated (animated) element:

const box = document.getElementById('box');
const printer = document.getElementById('printer');
const printBoxRectLeft = () => {
  printer.textContent = box.getBoundingClientRect().left;
  requestAnimationFrame(printBoxRectLeft);
};

printBoxRectLeft();
#box{
  width:30px; height:30px; background:red;
  animation: animX 3s infinite alternate;
}
@keyframes animX { to{ transform:translateX(300px); }}
<div id="printer"></div>
<div id="box"></div>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • 1
    smooth solution. never heard of that function. – oshell Feb 04 '15 at 09:19
  • 1
    THANK YOU. I use this for many things but didn't realize this would end the nightmare of getting things done with translations! – thednp Apr 21 '15 at 20:45
  • @RokoC.Buljan unfortunately, this only works great with elements that fill the window width, translated elements wrapped inside more other elements show different `getBoundingClientRect` values. Perhaps we should use element's offsetLeft value to adjust? – thednp Apr 21 '15 at 21:34
  • I confirm temporarily.. `el.getBoundingClientRect().left - el.offsetLeft` always gives the closest value to actual translate value. – thednp Apr 21 '15 at 21:38
  • 2
    When I make a quick test with `el.getBoundingClientRect().left - el.offsetLeft - el.parentNode.offsetLeft ` this gets even more accurate with a more complex structure. – thednp Apr 21 '15 at 21:44
  • @thednp yes, GBCR gives the position relative to the client window, means if you need to get a position *relative* to some other element subtraction needs to be done. – Roko C. Buljan Apr 22 '15 at 08:13
  • This is the exact answer I have been searching for. Thank you! – Giacomo1968 Apr 02 '16 at 05:09
  • @thednp any idea when we might need to include `el.offsetLeft` in `el.getBoundingClientRect().left - el.offsetLeft - el.parentNode.offsetLeft` ? – manikanta Jan 24 '19 at 11:34
  • 1
    @manikanta out the back of my neck... you'd perhaps need to include other variables when you're not strictly interested in the position relative to the viewport, but relative to a scrollable parent element... – Roko C. Buljan Jan 24 '19 at 12:57
3

The style attribute left is set to auto if you do not set it manually. But you should be able to use the jquery function position().

    var position = $('#element').position();
    var left = position.left;

http://jsfiddle.net/nqab2aw7/2/

oshell
  • 8,923
  • 1
  • 29
  • 47
  • In that fiddle i converted rotateY to translate3d(330px,0,0) and yes.. it does seem to work. So at least there is a way, would be even better if there were a jquery-free one. – john-jones Feb 03 '15 at 11:04
2

The other answers that use getBoundingClientRect work in most cases, but it calculates from the viewport, not the DOM's actual 0,0. So if the parent element has negative coords, and is off screen, getBoundingClientRect will return the wrong coordinates.

It also ignores margin, padding, and borderWidth, so if you need to be very precise:

trueLeft = rect.left - margin.left - padding.left - borderWidth - offsetX

to get the other values could use a RegExp:

'translate3d(256px, 512px, 0px)'.replace(/translate3d|px|\(|\)/gi, '').split(',');

// { x: trueLeft, y: translate3d[1], z: translate3d[2] }
Benny Schmidt
  • 3,230
  • 1
  • 19
  • 14