Search code examples
jquerycssgoogle-chrometranslate3djquery-1.10

Delay detecting collision with translate3d and jQuery


I'm trying to detect a collision between two elements and I'm facing problems when using the css3 translate3d instead of making use of the top property.

Problems take place in:

  • Chrome (35.0.1916.153 m)
  • Opera (22.0.1471.70)

When using translate3d there's a delay detecting the collision. I'm using setInterval with a lapse of 1 millisecond to make sure the position of both elements is being monitored almost in real time.

In my examples, the small square will become black when the collision is detected. As you can see, the delay sometimes is quite big, sometimes the collision seems to be detected when the animation is finished.

Working properly when modifying the top property:
http://jsfiddle.net/rHZbt/10/

Delay when using translate3d instead to move the elements:
http://jsfiddle.net/rHZbt/9/

This is the way I detect the collision with jQuery:

var interval = setInterval(function () {
    checkCollision();
}, 1);

function checkCollision() {
    var top = $('#element').offset().top;
    var bigBoxTop = $('#demo').offset().top + $('#demo').height();


    if (bigBoxTop >= top) {
        $('#element').css('background', 'black');
        clearInterval(interval);
    }
}

Any ideas of what's the cause of this bug?


Solution

  • What I found was that jQuery wasn't getting the apropriate information at all until the animation had stopped, it was getting "old" coordinates.

    This can be seen here by running your web-inspector in chrome and looking at your console. http://jsfiddle.net/rHZbt/11/ (BTW I have cached your selectors for better performance). Whereas http://jsfiddle.net/rHZbt/12/ which worked with top was reporting the correct positions at all points.

    This lead me to Receiving elements position in the middle of CSS transition and "Force Reflow" in CSS transitions in Bootstrap with the last comment in the first one suggesting any css change basically will enable a synchronisation of the other CSS properties

    i.e. demo.css('visibility' , 'hidden').css('visibility' , 'visible'); and hey voila by even just adding demo.css('visibility' , 'visible'); to the checkCollision function you get it working as seen here http://jsfiddle.net/rHZbt/13/

    function checkCollision() {
        demo.css('visibility', 'visible');
        var top = element.offset().top;
        var bigBoxTop = demo.offset().top + demo.height();
        console.log(bigBoxTop, top);
        if (bigBoxTop >= top) {
            element.css('background', 'black');
            clearInterval(interval);
        }
    }