Jump to content
Search Community

Prevent One Tween from Firing Whilst Another One is Executing

emilychews 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,
 
I have a side menu that is present on a page after page load.  
 
You can then slide the menu off the screen by either scrolling 1px or clicking the 'X' on the menu.
 
When the menu has disappeared from a view a 'Menu' button shows and if you click on it, it brings the slide menu back in.
 
Once again to complete the cycle you can get rid of this menu by either clicking the 'X' on the menu or scrolling 1px up or down.
 
There's a bug in the code though which I found accidentally, which is purely of my making and i can't seem to get rid of it.
 
Problem:
When the menu has been closed and all you have is the 'Menu' button, if you click this button and accidentally scroll as the menu slides back in, the Tween that is fired by the 1px scroll hijacks the click Tween and it slides off again.
 
Is there any built-in functionality in GSAP to prevent one timeline firing whilst another one is animating? (effectively making it null for the duration of the other animation).  I've been going around in circles trying to solve it with setTimeOut(), but I don't think this is the correct way to approach it.
 
The GSAP code is below and there is a pen to illustrate the problem here

Any help / ideas would be awesome.

Emily
 
jQuery(document).ready(function($){


  // global var for menu container
  var $menuContainer = $('.menu-container');
  
  TweenMax.set($menuContainer, {x: '-100%'});  //set the menu off the screen before sliding in on page load
  TweenMax.set('.showMenu--button', {autoAlpha: 0});  // Button that appears after the Menu slides away


  // slides menu in on page load
  function bringInMenu(){
      
        var menuIn = new TimelineMax();

        menuIn
        .to($menuContainer, .9, {x: '0%', ease: Power1.easeOut})
        .from($menuContainer, .5, {skewX: '2deg', transformOrigin: 'bottom right', ease: Power1.easeOut}, '-=.5')
        .to('.downarrow', 1, {y: -20, repeat: -1, yoyo: true, ease: Power1.easeOut});  // animated down arrow

    };

  bringInMenu();


  // Close menu with the 'X' on the menu itself
  $('.menu-x').on('click', function(){

      var closeOnClick = new TimelineMax();

          closeOnClick
            .to($menuContainer, 1, {x: '-98%', ease: Power1.easeIn})
            .to($menuContainer, .3, {scaleY: 0, transformOrigin: 'top right', ease: Power1.easeIn})
            .to('.showMenu--button', 1, {autoAlpha: 1});

  });


  // Close the menu on scroll  
  var scrolled = false;

  $(window).scroll(function() {
      if ( !scrolled && $(document).scrollTop() > 1) {
    
      var closeOnScroll = new TimelineMax();

      closeOnScroll
         .to($menuContainer, 1, {x: '-98%', ease: Power1.easeIn})
         .to($menuContainer, .3, {scaleY: 0, transformOrigin: 'top right', ease: Power1.easeIn})
         .to('.showMenu--button', 1, {autoAlpha: 1});  // reveals menu button

         scrolled = true; // update the scroll state

      }

  });


  // ClICK FUNCTION TO BRING BACK MENU
  $('.showMenu--button').on('click', function() {
  
      var desktopMenuClick = new TimelineMax ();
  
      desktopMenuClick
         .to($menuContainer, .3, {scaleY: 1, transformOrigin: 'top right', ease: Power1.easeIn})
         .to($menuContainer, 1, {x: '0%', ease: Power1.easeIn})
         .to('.showMenu--button', 1.3, {autoAlpha: 0}, '-=1.3');
    
     scrolled = false; // resets scroll state to false
  
  });


});  // end of jQuery

 

See the Pen PpXaNV by emilychews (@emilychews) on CodePen

Link to comment
Share on other sites

Hi Emily :)

 

I'm not sure I completely followed everything in your question, but it sounds like you are looking for the isActive() method. That will allow you to check whether your timeline is active or not. If it's active, you can prevent other things from happening. Here's some more info:

 

https://greensock.com/docs/#/HTML5/GSAP/TweenMax/isActive/

 

If you want to check on one element, you can also use the isTweening() method.

 

https://greensock.com/docs/#/HTML5/GSAP/TweenMax/isTweening/

 

Does that help?

 

Happy tweening.

:)

  • Like 5
Link to comment
Share on other sites

OMFG ! That's amazing.  Thanks so much Point C.  I had one person slate me on one of the javascript forums about why I should use CSS and the add class / remove class methods which i didn't want to do because of all the extra code and difficulty in getting everything to integrate when i was trying to use setTimeOut(). Sometimes it hard to grasp stuff when you're new to coding (although its steadily getting easier).

 

You're such a legend.  It also solves a different issue I had on a tween, which will now be making its way back like the Resurrection.

Emily :) :) 

Link to comment
Share on other sites

Actually, although that does work, there is side effect.  If I use the isActive() method it does prevent the menu sliding off screen again mid-animation if the user scrolls (good), but when the animation is complete, it stops the scroll triggered tween from working if the scroll wheel has been used during the animation.

 

The function is between lines 57 and 74.  On line 61 the isActive() if statement does what I need.  

 

I need to work out how to effectively kill off that if statement once the menu has animated back into view.

 

Emily

Link to comment
Share on other sites

When I use the isActive() method, I usually prefer to find out if something is not active. You can wrap a function or event listener inside that logic and only execute it if the timeline isn't active. So something like this:

  if( !yourTimeline.isActive() ) {
    //do stuff if yourTimeline isn't active
  }

I think making that change will get you to your goal. 

 

Does that help?

 

Happy tweening.

:)

 

 

  • Like 4
Link to comment
Share on other sites

Thanks Point C.

That's really good to know and I'll have a play around with it tomorrow. Because it was two separate functions and two event listeners (scroll and click), I ended by finding a solution using jQuery's offset() method in relation to the menu's position coordinates (bit of a hack).  But I have to say the original answer was really informative and I've been scanning the docs on some of the other related methods that I didn't know existed, and as per my first reply, the isActive() method did solve a separate issue i was having on a different part of the site so i'm defo hugely grateful!!

Thanks again,

 

Emily.

P.S - sorry for saying OMFG! in my first answer, it wasn't very professional.

 

  • Like 1
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...