Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
James WIlk

onComplete functions not firing in first timeline

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 have a separate stepped animation that I am using on the onComplete of the TweenMax animations and it works great everywhere except the first 5 animations.

 

Here is the code excerpt. The last onComplete will fire causing all previous onComplete's to fire.

function treeanimation(treeFrame){
		bgPos = treeFrame*211;
		$("#plant").css('background-position', '0px -'+bgPos+'px');
	}
	var controller = $.superscrollorama({})
	controller.pin($('#slides'), aniDur,{
		anim: (new TimelineLite())
		.append([
			TweenMax.to($('#slide1-bg'), .5, 
				{css: 
					{
						top:"100%"
					},
					onComplete: function(){
						treeanimation(1);
					},
					onReverseComplete: function() {
						treeanimation(0);
					}
				}
			),
			TweenMax.to($('#slide1-content'), .5, 
				{css: 
					{
						top:"-50%",
						display: "none"
					},
					onComplete: function(){
						treeanimation(2);
					},
					onReverseComplete: function() {
						treeanimation(1);
					}
				}
			),
			TweenMax.to($('#slide1-body'), .5, 
				{css: 
					{
						display:"none"
					},
					onComplete: function(){
						treeanimation(3);
					},
					onReverseComplete: function() {
						treeanimation(2);
					}
				}
			),
			TweenMax.to($('#slide2-content'), .5, 
				{css: 
					{
						marginTop:"20%"
					},
					onComplete: function(){
						treeanimation(4);
					},
					onReverseComplete: function() {
						treeanimation(3);
					}
				}
			),
			TweenMax.to($('#slide2'), .5, 
				{css: 
					{
						top:"0"
					},
				onComplete: function(){
					$("#slide2-nav").html('<img src="img/active-btn.png" alt="Slide 2">')
					$("#slide2-nav").parent().addClass('active')
					treeanimation(5);
					},
				onReverseComplete: function(){
					$("#slide2-nav").html('<img src="img/inactiv-btn.png" alt="Slide 2">')
					$("#slide2-nav").parent().removeClass('active')
					treeanimation(4);
					}
				}
			)
		])
		.append([
			TweenMax.to($('#slide2'), .5, 
				{css: 
					{
						right:"-100%"
					},
					onComplete: function(){
						treeanimation(6);
					},
					onReverseComplete: function() {
						treeanimation(5);
					}
				}
			),
			TweenMax.to($('#slide2-content'), .5, 
				{css: 
					{
						marginLeft:"-90%",
						display: "none"
					},
					onComplete: function(){
						treeanimation(7);
					},
					onReverseComplete: function() {
						treeanimation(6);
					}
				}
			),
			TweenMax.to($('#slide3'), .5, 
				{css: 
					{
						left: "0%"
					},
				onComplete: function(){
					$("#slide2-nav").html('<img src="img/inactiv-btn.png" alt="Slide 2">')
					$("#slide3-nav").html('<img src="img/active-btn.png" alt="Slide 3">')
					$("#slide3-nav").parent().addClass('active')
					$("#slide2-nav").parent().removeClass('active')
					treeanimation(8);
					},
				onReverseComplete: function(){
					$("#slide3-nav").html('<img src="img/inactiv-btn.png" alt="Slide 3">')
					$("#slide2-nav").html('<img src="img/active-btn.png" alt="Slide 2">')
					$("#slide3-nav").parent().removeClass('active')
					$("#slide2-nav").parent().addClass('active')
					treeanimation(7);
					}
				}
			),
			TweenMax.to($('#slide3-content'), 0.5, 
				{css: 
					{
						marginLeft: "10%"
					},
				startAt: {css:
						{
							marginLeft: "110%"
						}
					},
					onComplete: function(){
						treeanimation(9);
					},
					onReverseComplete: function() {
						treeanimation(8);
					}
				}
			),
		])

Any Help would be greatly appreciated. This is integrated with SuperScrollerama

Link to comment
Share on other sites

Hi James and welcome to the Greensock forums.
 
I'm going to start with the obvious, have you added a console.log to the treeanimation callback?, just to check that behaviour.

 

Also you could try reading each tween progress, to see if they reach 1 (the progress of any tween/timeline goes between 0 at the beginning and 1 at the end), it could be that the tween's might not reaching the end.

 

Also you said that it works after the fifth animation. In that animation's onComplete you make some css changes, mainly you add a class to the element's parent and replace the content of another element with an image.

 

Finally you could also try the set method instead of JQuery's css, like this:

function treeanimation(treeFrame)
{
  bgPos = treeFrame*211;
  TweenLite.set($("#plant"), {backgroundPosition:'0px ' + bgPos + 'px'});
}

Unfortunately we're not superscrollorama experts here so it'd also help if you could set up a reduced live sample (jsfiddle or coedpen) showing the issue.

 

Best,

Rodrigo.

Link to comment
Share on other sites

I checked and the animations onComplete are ALL being called after the first append statement.

 

All 5 get called but right after each other, not when the tween has finished.

Link to comment
Share on other sites

It looks like your syntax is wrong.

Let's step away from the superscrollorama implementation and just focus on how callbacks in tweens work

 

BAD

TweenLite.to(elem, 1, {left:200, onComplete:someFunction(1)})

 

you need to pass the onComplete property the name of the function you want to call. If you add the () like someFunction() that means that someFunction() will execute immediately.

 

GOOD:

TweenLite.to(elem, 1, {left:200, onComplete:someFunction, onCompleteParams:[1]})

 

In the code above notice how the onCompleteParams property accepts an Array of values (so that you can pass multiple params into the callback). Also note the onComplete property is only using the name of the function without the ()

 

Take a look here: http://www.greensock.com/jump-start-js/#event-callbacks

 

Let us know if this solves the issue

  • Like 1
Link to comment
Share on other sites

I am passing it an anonymous function that calls a function neither of your examples properly explain how to implement passing of my variable to the function.

Link to comment
Share on other sites

This also doesn't explain why all 40 other animations work just fine and the first 5 do not...

Link to comment
Share on other sites

Sorry about that, you are quite right. I read your code a bit too quick and got lost in some of the many line breaks.

 

Perhaps you can create a simple jsfiddle or codepen example so that it is perfectly clear what the issue is. Right now its kind of tough just analyzing the js code on its own.

  • Like 1
Link to comment
Share on other sites

I can't create it in another form it would defeat the purpose of finding the bug. I show you two .appends that have animations in them

 

The second appends oncomplete animations fire just fine and the next 40, however the first 5 do not until the 5th animation has completed

Link to comment
Share on other sites

Hi,

 

The reason Carl is asking for a simplified sample is because sometimes things might look good on the code, but you can find the issues with the code running. Another possibility is a link to a live page. Is not the easiest thing to troubleshoot with just a code extract .

 

Question, the first five animations happen normally, I mean in a good sequence, no strange issues?. Since you're using scrollorama another question would be if you need to scroll to play the first animations or they happen when the page loads?.

 

I don't know if it'll fix anything but could you try the following code and let us know how it goes?:

var controller = $.superscrollorama({})
	controller.pin($('#slides'), aniDur,{
		anim: (new TimelineLite({paused:true}))

Perhaps if the timeline is paused the issue could be solved. Again, sorry but we're not scrollorama experts so we're not very familiar with the way it handles the timeline instance being used.

 

Rodrigo.

  • Like 1
Link to comment
Share on other sites

That didn't work. SuperScrollerama acts as a stepper for the animations, attaching one pixel scrolled to one frame of animation basically. So it's always paused until you start scrolling.

 

All other animations happen no problem, and the first 5 animations happen no problem it's just that the onComplete function's do not fire until the 5th one has finished then all at once console logs complete on all 5.

Link to comment
Share on other sites

You'll need to provide some sort of files that we can test. 

 

Make them as simple as possible with as few tweens as possible. The onComplete callbacks only need to do a console.log(). We would just need to see that the callbacks aren't firing at the proper time. The quality of animation or visual assets is of no importance.

 

 

http://css-tricks.com/reduced-test-cases/

 

Thanks

Link to comment
Share on other sites

Getting a 404 error on that link. 

 

From looking at the code alone it seems that the first 5 tweens should start and end at the same time thus firing their onComplete callbacks in unison.

 

Very hard to imagine a situation where 1 tween's onComplete callback doesn't fire until another tween completes like you are suggesting.

 

 

 

  • Like 1
Link to comment
Share on other sites

im getting a 404 error page on that link as well ...

Link to comment
Share on other sites

Getting a 404 error on that link. 

 

From looking at the code alone it seems that the first 5 tweens should start and end at the same time thus firing their onComplete callbacks in unison.

 

Very hard to imagine a situation where 1 tween's onComplete callback doesn't fire until another tween completes like you are suggesting.

 

 

 

 

There is no all at once in this application its not possible as its all stepper based animating with superscrollerama.

 

And what you say doesn't explain why the other animations fire fine.

Link to comment
Share on other sites

Carl that short video explaining the issue.. was really super cool !!!

 

It even helped me understand what was going on since, im new to superscrollorama.. thx :)

  • Like 1
Link to comment
Share on other sites

Thanks for taking the time to make that video Carl.

 

I understand now what is going on with the Superscrollerama and Greensocks pair.

 

What I was trying to do is attach the tree sprite to change at the end of every animation, but as each of those all end at the same time because they are in the same append it wont work.

 

I can't put every animation in a new append as that would mean the red covers the screen, then the text comes down etc etc, making the animation much longer (meaning more scrolling) than intended.

 

What I think I can do for the staggered approach to the sprite while keeping the animations the same is to use the onStart instead of the onComplete, as I believe each animation would indeed start at a different time because of the 0.5 on the previous animation.

 

Am I correct in thinking thats how it would work?

 

Thanks

James

Link to comment
Share on other sites

Ok I just tried the onStart and they all start at the same time as well.

 

Any ideas on how to run my functions during each animation? I can't attach the plant sprite to SuperScrollerama and a Tween because I don't need to animate its position but make it change positions immediately.

Link to comment
Share on other sites

A large part of the problem is that all the SuperScrollorama examples and docs use old and out-dated methods from the GSAP API, which

 

  • aren't nearly as concise and powerful as the new methods
  • are no longer documented

So instead of advising you on how to use old and undocumented code in a way that works, I'll show you the best technique to use moving forward.

 

If you want to offset the start time of each tween in that first sequence slightly (so that they each end at slightly different times) I would suggest you replace the first append() method with add() like so: (the only modifications are shown in red)

 

.add([
TweenMax.to($('#slide1-bg'), .5, 
{css: 
{
top:"100%"
},
onComplete: function(){
treeanimation(1);
},
onReverseComplete: function() {
treeanimation(0);
}
}
),
TweenMax.to($('#slide1-content'), .5, 
{css: 
{
top:"-50%",
display: "none"
},
onComplete: function(){
treeanimation(2);
},
onReverseComplete: function() {
treeanimation(1);
}
}
),
TweenMax.to($('#slide1-body'), .5, 
{css: 
{
display:"none"
},
onComplete: function(){
treeanimation(3);
},
onReverseComplete: function() {
treeanimation(2);
}
}
),
TweenMax.to($('#slide2-content'), .5, 
{css: 
{
marginTop:"20%"
},
onComplete: function(){
treeanimation(4);
},
onReverseComplete: function() {
treeanimation(3);
}
}
),
TweenMax.to($('#slide2'), .5, 
{css: 
{
top:"0"
},
onComplete: function(){
$("#slide2-nav").html('<img src="img/active-btn.png" alt="Slide 2">')
$("#slide2-nav").parent().addClass('active')
treeanimation(5);
},
onReverseComplete: function(){
$("#slide2-nav").html('<img src="img/inactiv-btn.png" alt="Slide 2">')
$("#slide2-nav").parent().removeClass('active')
treeanimation(4);
}
}
)
], 0, "normal", 0.1)
 
add() is very flexible and can add tweens, timelines, labels, functions or even arrays of all those elements to a timeline AND provide a convenient means to stagger the position of each element.
 
In the code above you are using 4 parameters of the add method
 
param1: an array of tweens
param2: position (absolute time of 0), this is where the first tween is inserted
param3: align mode "normal"
param4: stagger. each tween will start 0.1 seconds after the previous tween starts
 
There are a ton of options to read about in the add() docs.
 
Yes, the animation will be a little different each time but you will get each leaf to appear in a staggered fashion.
 
*be sure you are using a version of GSAP higher than 1.8.0
 
Also, if you would like to do more with TimelineLite I would strongly suggest you watch this very short video: http://www.greensock.com/sequence-video/ which illustrates some of the core concepts for building timelines.
  • Like 1
Link to comment
Share on other sites

Ok so I realized all of the appends are doing the same, it just looked different.

 

So If I were to .add() instead of append what position would I put the other 9 appends I have at, would 1-9 work?

 

I think this is more of an experiment now because of superscrollerrama

Link to comment
Share on other sites

Yeah, 1-9 would mean you are adding each array of tweens at time of 1 second, 2 seconds, 3 seconds...

 

If you use position of "+=0" that would be a relative time which would translate to 0 seconds after the last group of tweens end... in other words in direct succession. The benefit here is if you edit the first group of tweens to have durations of 5 seconds you won't have to edit the position of all the other groups of tweens.

Link to comment
Share on other sites

Ok that does fix the on completes, but with that I would have to go in and redo all of my animations as the timing is off with all of the staggering.

 

I think I am going to have to find a better way to animate my plant image, as the rest of the application is already in a good state and changing this fixed the plant and destroyed everything else lol.

 

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.
×