Jump to content
Search Community

stop after end repeat

friendlygiraffe 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

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

Link to comment
Share on other sites

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++;
}
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

 

 

 

 

Link to comment
Share on other sites

  • Solution
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
Link to comment
Share on other sites

  • 2 weeks later...

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);
		}
	}

}
Link to comment
Share on other sites

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!
 

Link to comment
Share on other sites

  • 1 year later...

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

 

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