0

I'm trying to do a transition between two backgrounds:

$(document).ready(function() {

    // Set first background
    $('#bg .bg').backstretch( bg[0]['normal'], {speed: 0} );

    $('li').click(function() {
        var i = $(this).index();

        // Select first bg element
        var bg1 = $('#bg .bg:first-child');

        // Add second element
        $('#bg').append('<div class="bg" />');
        var bg2 = $('#bg .bg:nth-of-type(2)');
        $(bg2).css('left', '200%');;

        // Set second element background
        $(bg2).backstretch( bg[1]['normal'], {speed: 0} );

        // Move first background out
        $(bg1).animate({
            'left': '-100%'
        }, { duration: 500, queue: false });

        // Move second background in
        $(bg2).animate({
            'left': '0'
        }, { duration: 500, queue: false });
    });

});

My html for the absolute positioned 100%x100% backgrounds is:

<div id="bg">
   <div class="bg"></div>
</div>

bg[x]['normal'] are just strings with paths to images.

Briefly, my code appends a new .bg div to #bg and uses backstretch to set the background image. It then proceeds to animate the first background by moving it towards the left while the second background comes in from the right.

The code works just fine appart from the fact that there is a white gap between the two backgrounds during the transition. This is likely because bg1 get animate slightly before bg2.

How can I ensure these two backgrounds start their animation at the exact same moment?

(The queue: false was taken from an answer to this same question, but it is definitely not working in my case)

Juicy
  • 11,840
  • 35
  • 123
  • 212
  • Could you wrap both backgrounds absolutely positioned against each other in a wrapper div, and then just animate the one wrapper Div to slide to the left, and then remove the old background from the wrapper div? That would mean only one animation was playing, since they are both sliding to the left exactly the same distance. – Mark Jul 18 '14 at 15:14
  • @Mark yep! that's the way I ended up going. Turn out to be easier and less messy as well – Juicy Jul 18 '14 at 15:24
  • Darn! I knew I should have written that up as an answer. Seemed a little crazy to do two animations for what was one basic action. Tell me, is there any kind of a jump at the end or when you destroy the old background? I was a little concerned about something like that happening with this sort of approach, but if it's working smoothly enough I might try this on a project I have going on. – Mark Jul 18 '14 at 16:44
  • @Mark In my case I simply didn't destroy the other background. The background of my page is a sort of "map" and when the user clicks a link the background moves to a point on the "map". So it was just easier for me to paste several background images together in a wrapper and scroll along it, without ever destroying individual background images. So I never ran in to problems with destroying them. However I will point out that I'm still having trouble with window resizing (occasionally resize of individual images is off by a few pixels, annoying...) – Juicy Jul 18 '14 at 17:32
  • I would be interested in knowing what the problem ends up being with the resize issue when you solve it (if you solve it). I've never really had a problem with resize stuff before. – Mark Jul 18 '14 at 17:49

4 Answers4

1

Try setting the queue parameter in the animate method to false.

The jQuery animate documentation explains the queue parameter here: http://api.jquery.com/animate/

Here's another StackOverflow post that answers the same question: How to run two jQuery animations simultaneously?

Community
  • 1
  • 1
VinceFior
  • 1,279
  • 13
  • 25
  • This is actually probably as close as you can get, even though truly executing them simultaneously is not possible. – doublesharp Jul 17 '14 at 01:28
  • I appreciate the answer but if you looked at my code you would see I already have `queue: false` and I also pointed out that I took that from the same post your pointing me too! You could have read the full question but thank you anyway! :) – Juicy Jul 17 '14 at 01:33
0

JavaScript is single threaded, so you can only execute one function at the time. Meaning, the two animations can not be executed in parallel.

TGH
  • 38,769
  • 12
  • 102
  • 135
  • That's not correct, the animation doesn't have to complete you just can't guarantee they are added to the event loop at the same time. – doublesharp Jul 17 '14 at 01:21
  • What I means is that the callbacks can only be executed one at the time, so one callback has to finish before the next one can start. – TGH Jul 17 '14 at 01:24
  • I think we are agreeing - the callback to start the animation has to complete before the callback for the next animation is called, however the animation itself doesn't have to complete for the loop the continue (there isn't a 500ms delay between each animation). – doublesharp Jul 17 '14 at 01:26
0

The way that you are doing it is as close as you can get. JavaScript runs in a single event thread, so you can only add callbacks to that single event loop. The slight delay you are seeing is due to the animations being added to the event loop at slightly different times - there is no way to change this behavior.

You will need to use CSS, background layers, etc to achieve the look that you want.

doublesharp
  • 26,888
  • 6
  • 52
  • 73
0

Perhaps declaring the animations in a wrapper function before $(document).ready may help, because you don't have to redeclare the animation functions each time the li is clicked:

function FireBGAnims(bg1,bg2){
    // Move first background out
$(bg1).animate({
    'left': '-100%'
}, { duration: 500, queue: false });

// Move second background in
$(bg2).animate({
    'left': '0'
}, { duration: 500, queue: false });
}

$(document).ready(function() {

    // Set first background
    $('#bg .bg').backstretch( bg[0]['normal'], {speed: 0} );

    $('li').click(function() {
        var i = $(this).index();

        // Select first bg element
        var bg1 = $('#bg .bg:first-child');

        // Add second element
        $('#bg').append('<div class="bg" />');
        var bg2 = $('#bg .bg:nth-of-type(2)');
        $(bg2).css('left', '200%');;

        // Set second element background
        $(bg2).backstretch( bg[1]['normal'], {speed: 0} );

        FireBGAnims(bg1,bg2);

    });

});
WICS2 SRC
  • 216
  • 1
  • 2
  • 7