Jump to content
Search Community

Window scroll event triggered after scroll tween onComplete

massic80 test
Moderator Tag

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 all!

Today I was trying to execute some instructions on manual scroll event, avoiding the scroll animation performed by TweenMax.
I attempted to initialize a boolean variable, which is false during the TweenMax animation and is restored to true "onComplete". On $(window).on("scroll") I checked the status of the variable.
I found out that a scroll even was triggered even when my status variable was already returned to true: after some tests, it turns out that it's TweenMax itself.
I tried on an empty page, reporting the following code in Firebug console, and looks like after the "hi" reported by TweenMax onComplete, another scroll event is triggered.
 

$(window).on("scroll", function(){console.log ("scroll");});

TweenMax.to(window, 1,
     {
        scrollTo: {
              y: 500
             },
       ease: Linear.easeNone,
       onComplete: function ()
        {
            console.log("hi!");
        }

     });

I wouldn't expect this behavior: why does this happen?

Thanks in advance!
Massi

Link to comment
Share on other sites

I can assure you that TweenMax isn't doing any scrolling after the onComplete fires, but it's entirely possible that the browser fires its onscroll event in a slightly delayed fashion, like maybe when requestAnimationFrame occurs. That would certainly explain the slight offset. In other words, the sequence might look like this:

  1. TweenMax does the scroll
  2. TweenMax fires its onComplete
  3. The browser notices the scroll change and fires its onscroll event.

Again, that's a theory. If it's true, I don't think there's anything we can do inside TweenMax or the ScrollToPlugin to work around that. Let us know if you've got any ideas, though. 

Link to comment
Share on other sites

Thanks a lot for your reply Jack, looks like I'm a scroll pioneer! :)

Of course, when I said "turns out that it's TweenMax itself", I meant "it's only due to TweenMax animation, not other JS code around the page" ;)

Did you try my test code?

Of course, if yours is a correct theory, there is nothing to do on library side... let's study this up (it's annoying)! :)

Link to comment
Share on other sites

Can you try the following variation and see if it works any better?

$(window).on("scroll", function(){ console.log ("scroll"); });

TweenMax.to(window, 1,
{
    scrollTo: {
        y: 500
    },
    ease: Linear.easeNone,
    onComplete: function ()
    {
        TweenMax.delayedCall(0.001, function() {
            console.log("hi!");
        }
    }

});
The very tiny delayedCall will cause the "hi" to occur on GSAP's next tick, which might give the browser a chance for the final scroll event to fire.
Link to comment
Share on other sites

Hi again!
I cant find out why, but it looks like WORKING!
In my example, the timestamp at penultimate tick was around 50 ms before the last one, and the position was exactly the same (this may be due to a fraction of pixel for last tick), hence I didn't expect it to work with a delay of 1 ms.
I was thinking of trying with isTweening() method or ticker property, but since you found an apparently working solution, I'll try applying it to my site and testing it deeply :)

Thanks again, I'll let you know... there is a beer for you, in case you plan to pass around here ;)

Massi

P.S.: maybe it's best to write something about this on documentation: I've spent several hours trying to find out why my layout "didn't work" :)

Link to comment
Share on other sites

This seems to suggest that Jack's assumption was correct.

 

TweenMax.delayedCall() just creates an empty tween with a delay that calls your function 'onComplete'. Like all tweens this is tied to GSAP's ticker (its 'framerate'), and like any tween with a duration or delay greater than 0, it will take at least one tick to complete.

 

The miniscule delay we set is not strictly a delay of exactly 0.001 seconds, but just a way to make sure the function is called on the next tick. At 20 FPS the ticks would occur every 50ms or so, which means the delay could take 1ms, or it could take 50ms (or more even, if the framerate drops). GSAP will keep it accurately synchronised with any other GSAP tweens or delayedCalls you have going on though, which can be a great help when your application logic is being tied to your tweens.

 

You could probably also achieve the same effect of allowing the last scroll event through with a very very short setTimeout().

Link to comment
Share on other sites

Hi again, sorry for the delay, but I got fever.

I think this is a good solution for keeping a "short event" synchronized with TweenMax ticker... but let me understand: is onComplete() event triggered when last "frame" is started? And... how could a setTimeout be synchronized as well?
 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Insert title here</title>
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.9.4/TweenMax.min.js"></script>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.9.4/plugins/ScrollToPlugin.min.js"></script>
    </head>
    <body style="height: 2000px;">
        <script type="text/javascript">
            $(document).ready(
                function(){
                    $(window).on("scroll", function(){ console.log ("scroll"); });

                    TweenMax.to(window, 1,
                    {
                        scrollTo: {
                            y: 500
                        },
                        ease: Linear.easeNone,
                        onComplete: function ()
                        {
                            TweenMax.delayedCall(0.001, function() {
                                console.log("hi!");
                            });
                        }

                    });
                });
        </script>
    </body>
</html>

I found out another trouble: loading my example code above and reproducing the ScrollTo to a negative value (e.g. -25 or higher, not -5 because it doesn't happen), the onComplete doesn't seem to be triggered. The workaround for this is trivial for me, but I think that someone couldn't notice this in a more complex environment.

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