Jump to content
GreenSock

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

Transform Navigation Hover Event to Click Event with gsap.utils

Recommended Posts

I have this collapsing sub-navigation which works pretty good with mouseover/leave. But now the client  wants the toggle effect triggered by click event. Having a click event is easy and opening is also no problem. But how can i call all other gsap timelines to close/reverse before opening the current item?

See the Pen rNmgprW by nicmare (@nicmare) on CodePen

Link to comment
Share on other sites

that is my approach:

let targets = gsap.utils.toArray(".menu-item-has-children");
targets.forEach(subitem => {
    
    const nav_tl = gsap.to(subitem, {
        height:"auto",
        duration:0.2
    }).pause();

    const submenu_tl = gsap.from($(subitem).find(".sub-menu"), {
        paused: true,
        autoAlpha: 0,
        x: "-=30",
        ease:"back",
        duration: 0.3,
        
    });
    
    $(subitem).on("click touchstart", (e) => {
        e.preventDefault();
        targets.reverse();
        targets.reverse();
        nav_tl.play();
        submenu_tl.play();
    });
});

but it does not work. there is no reverse before.

Link to comment
Share on other sites

14 minutes ago, nicmare said:

but it does not work. there is no reverse before.

 

targets is an array of elements, so there won't be any animation controls available.

 

You can add the animations to the elements and then loop through them.

 

let targets = gsap.utils.toArray(".menu-item-has-children");
targets.forEach(subitem => {
    
    const nav_tl = gsap.to(subitem, {
        height:"auto",
        duration:0.2
    }).pause();

    const submenu_tl = gsap.from(subitem.querySelector(".sub-menu"), {
        paused: true,
        autoAlpha: 0,
        x: "-=30",
        ease:"back",
        duration: 0.3,
        
    });
  
  // add animations to element
  subitem.nav_tl = nav_tl;
  subitem.submenu_tl = submenu_tl;
    
    $(subitem).on("click touchstart", (e) => {
        e.preventDefault();
        // targets.reverse();
        // targets.reverse();
      targets.forEach(target => {
        target.nav_tl.reverse();
        target.submenu_tl.reverse();
      })
        nav_tl.play();
        submenu_tl.play();
    });
});

 

If you need the reverse to complete first, you can use a promise as shown here.

 

 

 

  • Like 5
Link to comment
Share on other sites

yea i know my approach made no sense but i had no clue how to access the timelines. But thankfully your code does the job. Thank you very much!

I then tried to use the await code from the other post but it seems not to work. reverse animation is not firing:

let targets = gsap.utils.toArray(".menu-item-has-children");
targets.forEach(subitem => {
    
    const nav_tl = gsap.to(subitem, {
        height:"auto",
        duration:0.2
    }).pause();

    const submenu_tl = gsap.from(subitem.querySelector(".sub-menu"), {
        paused: true,
        autoAlpha: 0,
        x: "-=30",
        ease:"back",
        duration: 0.3,
        
    });
  
  // add animations to element
  subitem.nav_tl = nav_tl;
  subitem.submenu_tl = submenu_tl;
    
    $(subitem).on("click touchstart", (e) => {
        e.preventDefault();

        targets.forEach(target => {
            async function animate1() {
                await Promise.all([
                    target.nav_tl.reverse(),
                    target.submenu_tl.reverse()
                ]);
            };
          
      
            nav_tl.play();
            submenu_tl.play();
        });
    });
});

do i miss something? i get not js console error

Link to comment
Share on other sites

You'd probably have to create an array and add the animations to it like this.

$(subitem).on("click touchstart", async (e) => {      
      e.preventDefault();
      const promises = [];
      targets.forEach(target => {
        promises.push(
          target.nav_tl.reverse(),
          target.submenu_tl.reverse()
        );
      });
      await Promise.all(promises);
      nav_tl.play();
      submenu_tl.play();
    });

 

  • Like 4
Link to comment
Share on other sites

nice one! never seen that "async" / "await" stuff so far. but it works! cool stuff. thank you OSUblake!

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