Jump to content
Search Community

Trouble restarting timeline with callback

schmolzp test
Moderator Tag

Go to solution Solved by Carl,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I think this library is awesome and works great! Thanks for taking the time to make it :)
 
So I am building a page that when you click on a button, a bunch of photos will fade and scale down into random positions in a container. I have made three different timelines for each group of photos that will incrementally increase in speed until the last group which will slow back down again. The animation is smooth and works great. My problem is I have created a button that will slide out when that last timeline finishes. When someone clicks on it, I want to be able to just replay the entire animation again. However, it will only play the first timeline over and stop, it won't read my callback within that timeline to move to the next timeline. Not sure why it's doing this since I added the false parameter to suppress events. I'm sure there is a better way with TimelineMax to do what I have done, but this is my first time working with GSAP. Sorry, I won't be able to recreate this in a codepen. Thank you for any help you can provide!
 
Here is my code:

var groupOne = $('.group-one .photo_item'),
    groupTwo = $('.group-two .photo_item'),
    groupThree = $('.group-three .photo_item'),
    currentItem = 0,

    rotateValues = ["-20deg", "20deg", "-10deg", "10deg", "0deg"],

    widthOffset = 100,
    heightOffset = 300,
    containerWidth = $('.photos').width() - widthOffset,
    containerHeight = $('.photos').height() - heightOffset,

    tl = new TimelineMax(),
    tlTwo = new TimelineMax(),
    tlThree = new TimelineMax();

Draggable.create($('.photo_item'), {type:"x,y", edgeResistance:0.2 });

$('.js-btn').one('click', function(){
    beginGroupOne();
});

$('.js-restart-btn').on('click', function() {
    restartTimeline();
});

function beginGroupOne() {
    groupOne.each(function(index, element) {
        tl.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 })
    });
    tl.staggerTo(groupOne, 1.25, { force3D: true, scale:1, autoAlpha:1, ease: Expo.easeOut }, .5, 0)
    .addCallback(beginGroupTwo, "-=.7");
}

function beginGroupTwo() {
    groupTwo.each(function(index, element) {
        tlTwo.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 })
    });
    tlTwo.staggerTo(groupTwo, .75, { scale:1, autoAlpha:1, ease: Expo.easeOut }, .3, 0)
   .addCallback(beginGroupThree, "-=.5");
}

function beginGroupThree() {
    groupThree.each(function(index, element) {
        tlThree.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 })
    });
    tlThree.staggerTo(groupThree, .25, { scale:1, autoAlpha:1, ease: Expo.easeOut }, .1, 0, showRestartBtn);
}

function showRestartBtn() {
    $('.js-restart-btn').addClass('is-active');
}

function restartTimeline() {
    tlTwo.pause(0).invalidate();
    tlThree.pause(0).invalidate();
    tl.restart(false, false);
}

function getRandomRotate() {
    return rotateValues[Math.floor(Math.random() * rotateValues.length)];
}

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

 

Link to comment
Share on other sites

  • Solution

Hi and welcome to the GreenSock forums,

 

One of the greatest features of GSAP is that there is no need to use callbacks to trigger other animations. You can place as many tweens or timelines into 1 timeline at any time that you want. This allows you the flexibility of keeping your code modular (different timelines for certain elements) but you can offset the position of those timelines in a master timeline for ultimate control over the entire sequence.

 

Here is a very basic example that can be tweaked to do the same thing as your code

 

 
//create and return a timeline that animates box1
function box1() {
  var tl = new TimelineLite();
  tl.to("#box1", 1, {rotation:360})
    .to("#box1", 1, {opacity:0})
  return tl;
}


//create and return a timeline that animates box2
function box2() {
  var tl = new TimelineLite();
  tl.to("#box2", 1, {rotation:-360})
    .to("#box2", 1, {y:200, opacity:0, scale:0.2});
  return tl;
}


//create and return a timeline that animates box3
function box3() {
  var tl = new TimelineLite();
  tl.to("#box3", 1, {rotation:-360})
    .to("#box3", 1, {opacity:0, scale:0.2});
  return tl;
}




//create a timeline that holds all the timelines created in the functions above
var masterTimeline = new TimelineLite();


masterTimeline.add(box1()) //starts at time of 0
.add(box2(), "-=1") //starts 1 second before previous timeline ends
.add(box3(), "-=1") //starts 1 second before previous timeline ends


$("#restart").click(function() {
  masterTimeline.restart();
})

http://codepen.io/GreenSock/pen/PNBezq?editors=0010

 

This is the exact same technique used to glue together all the parts of our homepage animation:

 

http://codepen.io/GreenSock/pen/yhEmn?editors=0010

 

If you need further help figuring out why your code wasn't working, please provide a reduced CodePen demo that we can edit and test.

It doesn't need to include a lot of elements, Draggable or lots of randomization. The simpler the better.

  • Like 3
Link to comment
Share on other sites

Thank you! I had already tried to use the master timeline way, but couldn't get it working (obviously I was doing it wrong haha). Your code helped me to understand how it needed to be written. Works great now! Thanks again!

 

Out of curiosity, do you know why my restart button wasn't working on my original code? Shouldn't the false parameter make it execute the callback in my timeline?

Link to comment
Share on other sites

Glad the demo helped.

 


Out of curiosity, do you know why my restart button wasn't working on my original code? Shouldn't the false parameter make it execute the callback in my timeline?

 

 



 

Not really sure if you are asking why the timeline wasn't restarting or why a callback was or was not firing. Again, without a CodePen it is so much more difficult to trouble shoot. If you are still interested, please provide a very simple example. Thanks.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...