Jump to content
Search Community

Timeline .add() anonymous function to return tween?

katerlouis 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 need to make some calculations for a Tween I want to add.

But when I .add() it with a anonymous function returning the Tween, the following tween doesn't wait for it's turn. 

Like it doesn't know how long it's gonna take. "But Why!?" am I thinking.


Dear Elders, help me out here please :)


See the Pen Mmydqd by katerlouis (@katerlouis) on CodePen

Link to comment
Share on other sites

Okay, I am highly confused:


1) Why does parantheses AFTER an anonymous function make the problem disappear?


2) now I added those parantheses, but the calculations I want to make, get ignored (better said: probably calculated at some other time, which is not convenient for me)



it appears the anonymous function gets calculated before anything else, now? 

Link to comment
Share on other sites

I'm not sure what you mean. With that change, your demo is exhibiting the behavior I would expect. The box moves, background animates to yellow, background animates to blue, box moves back to 0.


Just my two cents worth, but the add() method is best used for nesting timelines into a master. Rather than adding anonymous functions, I'd recommend something like this:

var master = new TimelineMax({paused:true});

// child 1
function child1() {
    var tl = new TimelineMax();
    tl.to("#someElement", 1, { x: 100 });
    return tl;    

// child 2
function child2() {
    var tl = new TimelineMax();
    tl.to("#anotherElement", 1, { x: 100 });
    return tl;

.add( child1() ) 
.add( child2() ) 

Happy tweening.


Link to comment
Share on other sites

This doesn't work for me; I need to calculate the widths and heights that are applied at that exact moment.

tl = new TimelineMax({ repeat: -1 });
	.from("#box-1", 2, { width: 0 })
	.to("#box-1", 2, { width: 400 })

	// effect shrink from the left
	.add(function() {
		var width = $("#box-1").width();
		return TweenMax.to("#box-1", 2, { x: "+="+width, width: 0 });

	// with the additional parentheses the timing of the .add() is no longer ignored
	// but the width calculation fails totally, seems to be 0? Why?

	.to("body", 2, { backgroundColor: "blue" }) 

The width inside the .add() is zero; which I just can't have :'(

I understand that the ".from()" is set at the time the .add(function()) is run through; and nested timelines don't help here as it seems.


Is .call() the solution?



PS: I'm still curious why .add(function() {}()); works? (+ 2 parantheses)

Link to comment
Share on other sites

I see... you need the width of the box after its been tweened. Would something like this work for you?

.to("#box-1", 2, { width: 400, onComplete:getWidth })

function getWidth() {
var width = $("#box-1").width();
return TweenMax.to("#box-1", 2, { x: "+="+width, width: 0 });

Blake did a lengthy answer about add, callbacks, etc. which should help:




Happy tweening.


Link to comment
Share on other sites

  • Solution

It sounds like using a function-based value will do the trick for you here as the values are not determined until the animation runs


var customHeight = 0;
var tl = new TimelineLite()
tl.to(".box", 1, {width:500})
  .to(".box", 1, {height:customHeight}) // 0 
  .to(".box", 1, {height:function(){
 return customHeight; //500

//change the value of customHeight 0.5 seconds after timeline starts
TweenLite.delayedCall(0.5, changeCustomHeight);
function changeCustomHeight() {
customHeight = 500;

notice that 2 tweens use the same customHeight value.

The first height tween gets a value of 0 and the second gets a value of 500.



  • Like 3
Link to comment
Share on other sites

Thank you, Carl!

This works for me, although it would feel more intuitive, if my first CodePen would just work, where I .add() an anonymous function. I see that GSAP needs to run the function "so early" in order to get the duration and offset (and maybe even more I don't know about); 


Now I know better– Woop Woop!


Having another function + delayedCall swirling around is not necessary in my case. I just did this:

.to("#box-1", 2, { x: function() {
	return "+="+ $("#box-1").width();	
}, width: 0 })



Now lets say I want to make the same thing for more than 1 property.

Why doesn't the following work?

// Return the whole property object with a anonymous function
// Doesn't work :'(
.to("#box-1", 2, function() {
	// some calculations...
	var width = $("#box-1").width();
	var someOtherCalculation = 0; // imagine fancy math here
	var bg = (some_fancy_if) ? "green" : "red";

	return { x: width, width: someOtherCalculation, backgroundColor: bg }


Link to comment
Share on other sites

Cool. The delayedCall() was just to illustrate that the customHeight variable could change by an "external" factor before the tween runs.


If you want to set multiple values, you just need unique functions for each property:

TweenLite.to(something, 1, {
x:function() {
  // custom things
  return someValue

width:function() {
  // custom things
  return someValue
  • Like 2
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...