Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
Frank

Repeating the same tween with random numbers

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

Hello,

 

I'm new to GSAP and in fact pretty new with JS, so please bear with me. I'd like to use GSAP together with Edge Animate.

 

I'd like to produce a flickering type of animation and started out using this:

TweenMax.to(object, Math.random() * 0.5 + 0.5, {opacity: Math.random(), repeat:-1});

The length of the tween should be random (between 0.5 and 1 second) as well as the opacity target. The code repeats the exact tween again instead of using a new random property for each new iteration.

 

How can I get this to work with new random numbers with every iteration? Also, if I use for example rotation instead opacity, how can I make every iteration start at the previous end position rather than the initial one? Couldn't figure out how to use invalidate() in case this is the key.

 

Can these two things be achieved without adding standard JS loops?   

 

Thanks in advance for your help.

 

Frank

 

Link to comment
Share on other sites

Hi and welcome to forums,

 

I would suggest you to create function ( for example flick ), and then run it at the end of the tween, using TweenMax onComplete handler.

 

Here is some pseudocode:

 

var $box = $(".box");

function flick(){
    TweenMax.to($box, Math.random() * 0.5 + 0.5, {opacity: Math.random(), onComplete:flick});
}

flick();
By using this method, every time the function is executed it will generate new values ( for time and opacity )

Update: Here is working pen: 

See the Pen IkjAK by bassta (@bassta) on CodePen

 
Cheers, Ico
  • Like 5
Link to comment
Share on other sites

When you create a tween (or do any kind of operation in JS), all of the values are calculated according to an order of operation. Even though a random number is being used, it is evaluated to a 'non-random' number before TweenMax.to() is ever called.

 

e.g. in general terms, your code would run something like:

 

call Math.random()     -> 0.2

evaluate (0.2*0.5+0.5) -> 0.6

call Math.random()     -> 0.7

call TweenMax.to(object, 0.6, {opacity: 0.7, repeat: -1});

 

In the end it's a non-random tween and every repeat will be the same.

 

You could try generating a new tween after each one completes instead of repeating the same tween each time. Something like this would do the job:

var something = document.getElementById('something');

flickerAnimate(something);

function flickerAnimate(object) {
    TweenMax.to(object, Math.random() * 0.5 + 0.5, {
        opacity: Math.random(), // or rotation etc
        onComplete: flickerAnimate,
        onCompleteParams: [object]
    });
}

Each tween will use the current value (end of the just completed tween) as its starting value, so this would work fine for rotation as well.

Edited by jamiejefferson
Whoops bassta snuck in while I was typing ever so slowly. Good idea bassta :)
  • Like 4
Link to comment
Share on other sites

Hah Jamie, I think your code is even better... It is nice to see different approaches to do a task. I personally prefer to cache my objects and reference them rather to pass them as a parameter. Nice work! 

Link to comment
Share on other sites

Guys, thanks so much for the quick replies. I'll test this out later tonight and get back.

 

Thanks again.

Link to comment
Share on other sites

Yep Chrysto's way works just as well - I only went with the parameter to avoid searching through the scope chain, and so the function could be used for as many flickering objects as are needed.

Link to comment
Share on other sites

Hum, one question about 'onComplete':

 

It seems my Timeline isn't waiting for the timeline to complete before it calls the function.

 

Any clue how to delay the start of the 'glow(YearGlow)' function until 'Year' is fully visible?

	var Curtain = sym.$("Curtain");
	var Mask = sym.$("Mask");
	var YearGlow = sym.$("Story1Year_GLOW");
	var Year = sym.$("Story1Year");

	var tl = new TimelineLite({delay:1, onComplete:glow(YearGlow)});
	tl.to(Curtain, 4, {autoAlpha:0})
	  .to(Year,    2, {autoAlpha:1});

	flicker(Mask);

	function flicker(object) {
		 TweenMax.to(object, 2, {
			  opacity: Math.random() * 0.5,
			  onComplete: flicker,
			  onCompleteParams: [object]
		 });
	}

	function glow(object) {
		 TweenMax.to(object, Math.random() * 0.1, {
			  opacity: Math.random(),
			  onComplete: glow,
			  onCompleteParams: [object]
		 });
	} 

Thanks!

Link to comment
Share on other sites

Hi, just add the onComplete callback to

 .to(Year, 2, {autoAlpha:1, onComplete:glow(YearGlow)}); 

It would be great if you create a pen ( codepen.io ) , so I can edit your code and see the changes. 

 

Cheers, Ico

Link to comment
Share on other sites

Ico, I did this initially, but it didn't work, so I created a timeline and added a 'onComplete' there (code above) but it's still not working. Maybe it's an issue with Edge Animate not treating 'onComplete' properly?

Link to comment
Share on other sites

I'm not really sure about being a problem with logic or with Edge Animate. I have almost non experience with EdgeAnimate. 

Btw the way I work is to create and test all components separately ( something like unit testing ), so when I know that some piece of code is working, I add it to the other code ( in your case Edge Animate ). I would suggest you to create pen, demonstrating the current behaviour, to post back what's the problem and the desired behaviour, and once everything is working you can implement it in EdgeAnimate. If it is not working there, probably the problem will be in the EdgeAnimate. 

 

You provided a JS code, but without the actual markup and styling it will be very difficult for me to help you.

 

Cheers, Ico :) 

  • Like 2
Link to comment
Share on other sites

I see one problem in your js code and that is how you are attmepting to call the onComplete function and pass in parameters.

 

BAD

var tl = new TimelineLite({delay:1, onComplete:glow(YearGlow)});

GOOD

var tl = new TimelineLite({delay:1, onComplete:glow, onCompleteParame:[YearGlow])};

It appears you are using the proper syntax in your tweens... just not in your timeline.

 

If you still need help, please create a simple codepen as Ico suggested. I'm sure we can get to the bottom of it.

 

here is a basic example that you can fork: http://codepen.io/GreenSock/pen/srtqe

  • Like 3
Link to comment
Share on other sites

Ah, now I understand the 'onCompleteParams' property, they contain the parameters of the 'onComplete' function. I should have read the docs more carefully, since it's all there.

 

Yes, it's working now as intended. Thanks Ico and Carl for your help.

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