Jump to content
GreenSock

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

Window scroll event triggered after scroll tween onComplete

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

Share this post


Link to post
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. 

Share this post


Link to post
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)! :)

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

At the moment I can't try, I'll let you know tonight (Italy time)... thanks in advance!

Share this post


Link to post
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" :)

Share this post


Link to post
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().

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×