Jump to content
Search Community

stop after end repeat

friendlygiraffe

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

friendlygiraffe
Posted

Hi there,

 

I have a banner that loops 3 times:

var tl = new TimelineMax({repeat:3});

tl.append( TweenLite.from($(".text1"), 0.5, {alpha:0}));
tl.append( TweenLite.to($(".text1"), 0.5, {alpha:0}),"+=2.5");
tl.append( TweenLite.from($(".text2"), 0.5, {alpha:0}) );
tl.append( TweenLite.to($(".text2"), 0.5, {alpha:0}),"+=2.5" );
tl.append( TweenLite.from($(".tele"), 0.5, {alpha:0}) );
tl.append( TweenLite.to($(".tele"), 0.5, {alpha:0}),"+=2" );
tl.append( TweenLite.from($(".endframe_logos"), 0.5, {alpha:0}) );
tl.append( TweenLite.to($(".endframe_logos"), 0.5, {alpha:0}),"+=4" );

After it's finished the 3 loops,  I don't want the last Tween to fire. instead stopping at the 2nd from last line

 

Is this possible using a label or some such?

 

Thanks

Posted

How about having a loop variable and a if statement?

var loop = 0;

var tl = new TimelineMax({repeat:3, onComplete:count});

tl.from($(".text1"), 0.5, {alpha:0}));
tl.to($(".text1"), 0.5, {alpha:0}),"+=2.5");
tl.from($(".text2"), 0.5, {alpha:0}) );
tl.to($(".text2"), 0.5, {alpha:0}),"+=2.5" );
tl.from($(".tele"), 0.5, {alpha:0}) );
tl.to($(".tele"), 0.5, {alpha:0}),"+=2" );
tl.from($(".endframe_logos"), 0.5, {alpha:0}) );
if(loop < 2) {
 tl.to($(".endframe_logos"), 0.5, {alpha:0}),"+=4" );
}

function count() {
 loop++;
}
Posted

Dipscom, that conditional logic wouldn't work because you're running it once when the timeline is created (rather than each iteration). 

 

friendlygiraffe, you could consolidate your code quite a bit by using the convenience methods, chaining, and skipping the jQuery selectors. Here's something that would probably work (though I haven't tested since you didn't provide a codepen demo): 

var tl = new TimelineMax({repeat:3, repeatDelay:0.5}),
    loop = 0;


tl.from(".text1", 0.5, {alpha:0})
  .to(".text1", 0.5, {alpha:0}, "+=2.5")
  .from(".text2", 0.5, {alpha:0} )
  .to(".text2", 0.5, {alpha:0}, "+=2.5")
  .from(".tele", 0.5, {alpha:0})
  .to(".tele", 0.5, {alpha:0}, "+=2")
  .from(".endframe_logos", 0.5, {alpha:0})
  .call(function() {
     loop++;
     if (loop < 3) {
             TweenLite.to(".endframe_logos", 0.5, {alpha:0});
     }
   }, "+=4");

Better?

  • Like 1
Posted

Dear mr. Almighty Code-God Who Answers by GreenSock,

 

My eyes burn with the vision of you addressing me personally and my soul is elevated into nirvana for receiving advice from your goddiness.

 

Yes, I do forget that detail more often than not. The timeline creation code only runs once. I will return to the dark depths of shame now and brood about it.

  • Like 2
Posted

LOL. Nice, Dipscom. No need to cower in the dark depths of shame - I'm super appreciative of your contributions here in the forums. It's such a great way for all of us to learn (myself included). Please keep chiming in as much as you can. We're happy you're here!

  • Like 1
friendlygiraffe
Posted

Dipscom, that conditional logic wouldn't work because you're running it once when the timeline is created (rather than each iteration). 

 

friendlygiraffe, you could consolidate your code quite a bit by using the convenience methods, chaining, and skipping the jQuery selectors. Here's something that would probably work (though I haven't tested since you didn't provide a codepen demo): 

var tl = new TimelineMax({repeat:3, repeatDelay:0.5}),
    loop = 0;


tl.from(".text1", 0.5, {alpha:0})
  .to(".text1", 0.5, {alpha:0}, "+=2.5")
  .from(".text2", 0.5, {alpha:0} )
  .to(".text2", 0.5, {alpha:0}, "+=2.5")
  .from(".tele", 0.5, {alpha:0})
  .to(".tele", 0.5, {alpha:0}, "+=2")
  .from(".endframe_logos", 0.5, {alpha:0})
  .call(function() {
     loop++;
     if (loop < 3) {
             TweenLite.to(".endframe_logos", 0.5, {alpha:0});
     }
   }, "+=4");

Better?

 

Hi jack - I created a CodePen of your method here 

See the Pen zvjRBd by friendlygiraffe (@friendlygiraffe) on CodePen.

 

If you run a debug view, it throws an error:

“Uncaught TypeError: Function.prototype.apply: Arguments list has wrong type”

Any ideas? 

 

Thanks

 

 

 

 

  • Solution
Posted
yeah, simple mistake (which is why we like demos :-P) call() takes 2 additional parameters before position: params and scope
 

the following code would avoid the error

.call(function() {
     loop++;
     if (loop < 2) {
        TweenLite.to(".frame3", 1, {alpha:0});
     }
   }, [], this, "+=4");

However, you will notice that while the tween in that condition is running, the timeline is already repeating. 

 

I'd sugget putting a call() right before the last tween and have it figure out whether the timeline should play through the last tween or pause (on final iteration)

 

var tl = new TimelineMax({repeat:-1}),
    loop = 0;
    loopMax = 3;


tl.from("#frame1", 1, {alpha:0})
  .to("#frame1", 1, {alpha:0}, "+=0.5")
  .from("#frame2", 1, {alpha:0} )
  .to("#frame2", 1, {alpha:0}, "+=0.5")
  .from("#frame3", 1, {alpha:0})
  .call(loopCheck)
  .to("#frame3", 2, {alpha:0, scale:0, rotation:360}, "+=2");


tl.timeScale(3)


function loopCheck() {
  console.log("loopCheck")
     loop++;
     if (loop < loopMax) {
        console.log("play again")
        tl.play();
     } else{
       console.log("done")
       tl.pause();
     }
   }
 

 

http://codepen.io/GreenSock/pen/eprVXV?editors=001

 

notice that the timeline is set to repeat infinitely and the condition above decides whether or not it should keep going

  • Like 4
friendlygiraffe
Posted

That is great. Thanks Carl

  • Like 1
  • 2 weeks later...
Posted

can this be done with just tweenlite and timelinelite?

This is my code below. It loops, but stop at the end. I've been trying to make it stop a few seconds before the end of the timeline but have failed to so.

function start() {
	var bg = document.getElementById('bg'),
		txt_01 = document.getElementById('txt_01'),
		txt_02 = document.getElementById('txt_02'),
		txt_03 = document.getElementById('txt_03'),
		lockup = document.getElementById('lockup'),
		banner = document.getElementById('banner'),
		tl = new TimelineLite();
		tl.eventCallback("onComplete", loopAnimation);

	tl
	.add('f1', 0)
	.add('f2', 4)
	.add('f3', 8)
	.add('f4', 12)

	tl
	.from([txt_01], 1, {x:'-=728px', ease: Power1.easeOut, onStart:function(){banner.style.visibility = 'visible';}})
	.from(txt_02, 1, {x:'-=728px', ease: Power1.easeOut}, 'f2-=0.5')
	.to(txt_01, 0.6, {opacity: 0, ease: Power1.easeOut}, 'f2-=0.6')
	.to(txt_02, 0.6, {opacity: 0, ease: Power1.easeOut}, 'f3-=0.6')
	.staggerFrom([txt_03], 0.6, {opacity: 0, ease: Power1.easeOut}, 0, 'f3+=0.5')
	.to(txt_03, 0.6, {opacity: 0, ease: Power1.easeOut}, 'f4')
	// stops looping animation
	.add('stop', '-=2')



	// start looping animation
	var loopNumber = 0;

	function loopAnimation() {
		loopNumber = loopNumber + 1;

		if (loopNumber >= 2) {
			tl.addPause('stop');
			console.log('Paused');
		} else {
			tl.restart();
			console.log('Times looped = ' + loopNumber);
		}
	}

}
Posted

try changing

tl.addPause('stop');

to

tl.pause('stop');
  • Like 1
Posted

thanks carl,

 

that works but it still plays my last animation line then pauses.

.add('stop') // want it to stop here before it plays the line below
.to(txt_03, 0.6, {opacity: 0, ease: Power1.easeOut}, 'f4')

So basically i want it to stop before txt_03 fades out. Its because the timeline hasn't complete its 'loop' yet. So this below hasn't fired yet

if (loopNumber >= 2) {
   tl.pause('stop');
   console.log('Paused');

Does that make sense?

 

What would be the best solution?

Thanks!
 

  • 1 year later...
Posted

Thanks for this one Carl. That code is really useful for setting up endframes in looped animations :D

 

 

 

yeah, simple mistake (which is why we like demos :-P) call() takes 2 additional parameters before position: params and scope
 

the following code would avoid the error

.call(function() {
     loop++;
     if (loop < 2) {
        TweenLite.to(".frame3", 1, {alpha:0});
     }
   }, [], this, "+=4");

However, you will notice that while the tween in that condition is running, the timeline is already repeating. 

 

I'd sugget putting a call() right before the last tween and have it figure out whether the timeline should play through the last tween or pause (on final iteration)

 

var tl = new TimelineMax({repeat:-1}),
    loop = 0;
    loopMax = 3;


tl.from("#frame1", 1, {alpha:0})
  .to("#frame1", 1, {alpha:0}, "+=0.5")
  .from("#frame2", 1, {alpha:0} )
  .to("#frame2", 1, {alpha:0}, "+=0.5")
  .from("#frame3", 1, {alpha:0})
  .call(loopCheck)
  .to("#frame3", 2, {alpha:0, scale:0, rotation:360}, "+=2");


tl.timeScale(3)


function loopCheck() {
  console.log("loopCheck")
     loop++;
     if (loop < loopMax) {
        console.log("play again")
        tl.play();
     } else{
       console.log("done")
       tl.pause();
     }
   }
 

 

See the Pen eprVXV?editors=001 by GreenSock (@GreenSock) on CodePen.

 

notice that the timeline is set to repeat infinitely and the condition above decides whether or not it should keep going

 

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