Jump to content
GreenSock

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

Property Hook? .call() when yPercent = 90

Recommended Posts

The jetpack-dude again.

 

I tween the background layers from yPercent 0 to yPercent 100.

At exactly yPercent 65 I need to change the dudes helmet to a space helmet.

Reason I don't hardcode the offset: the duration and easing of the background-tween will depend on the user input. (How many clicks in 10 seconds) – Finding a formula to calculate when the background will hit 65 yPercent; naaah :D

 

 

So far I'm doing it like this:

 

background.eventCallback("onUpdate", function() {
	if ($(".background")[0]._gsTransform.yPercent >= 65) helmet.frame(2);
})

 

This solution works. But I don't know how this effects performance. Feels like an overkill.

Plus: You guys spoiled me with the power of timelines; When the master timeline now begins from 0, I have to change back his helmet manually. It would be super cool, if this "when yPercent hits 65, do this"-thing could be part of the timeline. 

 

tl
	.fromTo(".background", 20, { yPercent: 0 }, { yPercent: 100, hook: {
		yPercent: 65, 
		call: function() { ... } 
    }
	})

// or
tl
	.fromTo(".background", 20, { yPercent: 0 }, { yPercent: 100, hook: {
		yPercent: 65, 
		over: function() { ... },
		under: function() { ... }
    }
	})


// or
tl
	.fromTo(".background", 20, { yPercent: 0 }, { yPercent: 100 })
	.hook(".background", yPercent, 65, function() {
  		// change his helmet
	})

// or as offset parameter?
tl
	.fromTo(".background", 20, { yPercent: 0 }, { yPercent: 100 })
	.to(".something", 1, { background: "red" }, "yPercent==65") // bool, so it is not a label :X

 

What do you think about a Hook-Plugin?

And I wonder how you guys would tackle this with the current toolset. :) 

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

Link to comment
Share on other sites

Here's an idea: 

See the Pen e77276f6563509b09b1510b17211071a by GreenSock (@GreenSock) on CodePen

 

Basically I'm doing the work up-front instead of on every onUpdate. You simply feed in an animation (could be a tween or timeline) and a function that checks whatever condition you want and returns true or false. It'll iterate the progress to find the spot at which that condition changes to true and spit back the playhead time. You can then use that however you want - in this case, it's to place your other animation(s) into the timeline. 


 

// this function is the key - it iterates over the timeline at large (20%) increments until the condition is true, then reverses by half the amount (10%) until it flips back, then half that amount forward, etc. for 20 direction-changes (you can change that number by feeding in a precision parameter). This is typically better than just iterating by a certain small amount because it affords greater precision in less loops.  
function calculateTimeAtCondition(animation, condition, suppressCallbacks, precision) {
    precision = precision || 20;
    suppressCallbacks = (suppressCallbacks !== false);
    var startingProgress = animation.progress(),
         inc = 0.2,
         progress = inc,
         curState = false;
    animation.progress(1).progress(progress, suppressCallbacks); //jump to the end and back to the start to ensure that all nested tweens are rendered/instantiated
    while (--precision > -1) {
        while (curState === condition() && progress > 0 && progress < 1) {
            progress += inc;
            animation.progress(progress, suppressCallbacks);
        }
        curState = !curState;
        inc *= -0.5;
    }
    animation.progress(startingProgress, suppressCallbacks);
    return animation.duration() * progress;
}

 I also cached a few variables to make the condition-checking faster but that's relatively minor. 

 

The other problem with the way you were doing it previously is that it'd keep firing those new animations once the condition is true (on every onUpdate) which probably isn't what you wanted. This new way prevents that and would be much faster at runtime for the actual animation(s). 

 

Does that answer your question? 

  • Like 4
Link to comment
Share on other sites

Damn, gotta chew on this a while longer;

pretty advanced JS for me.

 

Do I understand correctly, that this jumping 20 forward, 10 back, only works with conditions smaller as / larger as (< / >)?

 

So a condition "when x is exactly 90" will not work with this function, but "when x is larger than 90" effectively gives the time when x is exactly 90? 

 

This solution is way better than mine.

Only drawback is that I now have to control the Tweens / Timelines / whatever I do with the xOver90time– My solution was tied to the playback of main timeline and automatically reacts to .pause(), .timeScale etc. by nature. 

 

Do you see any way to tie your method to the main timeline?

Link to comment
Share on other sites

Right, the condition shouldn't be looking for an exact match because it's extremely unlikely that it'd land EXACTLY on top of that number when it's iterating and zeroing in on it back and forth. It keeps getting closer and closer is the point. 

 

In fact, while animating it's very unlikely it'd ever hit the value EXACTLY anyway. Remember, the way an animation works is that roughly 60 times per second, it updates the playhead and renders it at a new position, so animating 0 to 100 might result in frames like 1.02154, then 2.3541, then 4.000214, etc. It all depends on the update cycles, main thread performance, the ease, etc. 

 

I didn't quite understand your question about the main timeline. The solution I provided allows you to embed it into a timeline, thus it'd remain perfectly synchronized regardless of pause(), timeScale, etc. I must be misunderstanding something - can you provide a reduced test case in codepen that demonstrates the problem? 

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