Share Posted August 17, 2021 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 More sharing options...
Author Share Posted August 17, 2021 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 More sharing options...
Share Posted August 17, 2021 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. 5 Link to comment Share on other sites More sharing options...
Author Share Posted August 17, 2021 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 More sharing options...
Share Posted August 17, 2021 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(); }); 4 Link to comment Share on other sites More sharing options...
Author Share Posted August 17, 2021 nice one! never seen that "async" / "await" stuff so far. but it works! cool stuff. thank you OSUblake! 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now