Jump to content
GreenSock

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

Responsive code is buggy on resizing, works on refresh

Recommended Posts

I'm working on a menu that needs to react differently for mobile vs desktop. I got it working but when I change the viewport width, the animation and reverse animation are bugged one time, after that they adept to the 'new' situation. On browser refresh it also works correctly. 

 

Can anyone point out why the animations don't work correctly when changing the viewport width the first time? 

If I look in the inspector I see the values being being used are still from the other timeline, even though the new screensize is active.. 

 

Item 2 slides out a sub-menu, other items should do the same but I left that out for now.

See the Pen XWagryM by werkinprogres (@werkinprogres) on CodePen

Link to comment
Share on other sites

I got it cleaned up and working now, but the animation fires instantly now every time the page loads or is resized.

When I use the paused(true); before the timeline, the old issue comes up again. The value of the other timeline is still used for the new situation. 

New codepen here: 

See the Pen jOLwxbG by werkinprogres (@werkinprogres) on CodePen

Link to comment
Share on other sites

Welcome to the forums @JaPPa

 

In your first demo, your media queries are conflicting. You should make 1px different, like...

"(max-width: 799px)"
"(min-width: 800px)"

 

The second, you need to reset everything, kind of like this.

See the Pen VwzWgmb by GreenSock (@GreenSock) on CodePen

 

Link to comment
Share on other sites

57 minutes ago, OSUblake said:

Welcome to the forums @JaPPa

- Thank you very much!

 

In your first demo, your media queries are conflicting. You should make 1px different, like...

"(max-width: 799px)"
"(min-width: 800px)"

- Yes... good catch, think it happened during changing different methods. 

 

The second, you need to reset everything, kind of like this.

 

- Awesome, I was not aware of the .clear() and the .progress(0) method. I've read the docs around them and think I get the concept much better now.

 

Just one more question, how would I approach the situation of Item 2, 3 and 4 all have a sub-menu and one is open, how can I setup that one sub-menu closes and the other one opens if a sub-menu is already opened. In other words, is there a way to see of a sub-menu (timeline) is activated and can that one close (reverse) before opening the new one. This case would only be on de desktop version. 

Link to comment
Share on other sites

There are many, many ways to approach this. My personal preference is to just track the state with a variable and use a function to open/close things, sorta like this:

let currentSection; // when a section is open, store it here.

function openMenuSection(section) {
  let tl = gsap.timeline();
  if (currentSection) {
    tl.to(...close menu animation...)
  }
  tl.to(section, {...open menu animation...});
  currentSection = section; // record the current section
  return tl;
}

If you still need help, please make sure you provide a minimal demo with just the part you're struggling with. 

 

Happy tweening!

Link to comment
Share on other sites

17 hours ago, GreenSock said:

There are many, many ways to approach this. My personal preference is to just track the state with a variable and use a function to open/close things, sorta like this:

let currentSection; // when a section is open, store it here.

function openMenuSection(section) {
  let tl = gsap.timeline();
  if (currentSection) {
    tl.to(...close menu animation...)
  }
  tl.to(section, {...open menu animation...});
  currentSection = section; // record the current section
  return tl;
}

If you still need help, please make sure you provide a minimal demo with just the part you're struggling with. 

 

Happy tweening!

 

I'm trying to figure this out but I am stuck. I made a new Codepen and cleaned it up so only the three sub menu's are in the Codepen. I made it work that all three timelines run and close but I can't figure it how to implement your function. 

 

See the Pen MWvvoNE by werkinprogres (@werkinprogres) on CodePen

Link to comment
Share on other sites

This is how I'd do it: 

See the Pen ExvvGPp?editors=0010 by GreenSock (@GreenSock) on CodePen

  • Just use common classnames for each thing that has similar functionality (just use "subMenu" for them all instead of "subMenuOne", "subMenuTwo", "subMenuThree"). 
  • Loop through the nav items and set up common functionality for them all...
  • I added an .open(), .close(), and .toggle() method for each nav item to make it simple.
  • Store a reference to the currently open nav item (if there is one)
  • Then just call the associated methods and do the animations. The open() and close() methods return the animation they create because that can be very handy if you need to leverage those. We do that in the .open() method to close() the currently open one before running the new one's open animation. 
  • I animated xPercent instead of marginLeft because it'll perform better (since it doesn't affect layout).

Is that what you're looking for? 

Link to comment
Share on other sites

On 10/30/2021 at 8:18 AM, GreenSock said:

This is how I'd do it: 

 

 

  • Just use common classnames for each thing that has similar functionality (just use "subMenu" for them all instead of "subMenuOne", "subMenuTwo", "subMenuThree"). 
  • Loop through the nav items and set up common functionality for them all...
  • I added an .open(), .close(), and .toggle() method for each nav item to make it simple.
  • Store a reference to the currently open nav item (if there is one)
  • Then just call the associated methods and do the animations. The open() and close() methods return the animation they create because that can be very handy if you need to leverage those. We do that in the .open() method to close() the currently open one before running the new one's open animation. 
  • I animated xPercent instead of marginLeft because it'll perform better (since it doesn't affect layout).

Is that what you're looking for? 

Thank you! That looks very nice and thanks for the tip for using Translate X instead of margin-left, although iOS showed it a bit buggy where it left a small bar on the right after the animation was done. Have to dig deeper in that. 

 

I've used your method with the responsive problem at the beginning of this topic, it works, but only after refreshing. When I resize the screen the animations fails and nothing works anymore.  @OSUblake used a method to 'reset' the animation as I understand it when going from one screen size to an other with:

tl.reversed(false).progress(0).clear().pause(); 

I'm not sure if that method can be used with the stored timeline open/closed. I've setup a new code pen with a little media query css and the responsive JS code:

 

See the Pen PoKOwKw by werkinprogres (@werkinprogres) on CodePen

 

Theoretically I could only use a CSS media-query in this case, although the values for the animation should stay the same, limiting the options a lot. But even with just the CSS media-query the animations fails as the values don't get updated in the when checking the inspector. 

@media only screen and (max-width: 799px) {
  .menu {
    width: 100%;
    .subMenu {
      z-index: 10;
      transform: translateX(-100%);
    }
  }
}

 

Link to comment
Share on other sites

Yeah, that's just a bunch of logic issues in your code - you're running that same function multiple times which is adding event listeners but you're never removing the event listeners so they build up. Like on the second one, it'd call .toggle() twice for example. 

 

Here's a corrected version: 

See the Pen JjyOEzO?editors=0010 by GreenSock (@GreenSock) on CodePen

 

Better? 

Link to comment
Share on other sites

5 hours ago, GreenSock said:

Yeah, that's just a bunch of logic issues in your code - you're running that same function multiple times which is adding event listeners but you're never removing the event listeners so they build up. Like on the second one, it'd call .toggle() twice for example. 

 

Here's a corrected version: 

 

 

 

Better? 

That is really great! The code is a bit overwhelming to be honest but I think I get the concept. If I'm getting it right the responsive part is done with:

  let startAt = matches ? -100 : 0,
      endAt = matches ? 0 : 100;

Which is using the media-query function and uses the startAt and endAt values based on true/false result. And these values are then returned to the closing and opening parts in the xPercent animation. 

 

I'm wondering how I could change things now thought, if I wanted to add a stagger for the list items in the UL, or add an other element to the timeline on only the mobile or desktop version. And how can speedup the closing animation or jump to a timestamp in the timeline (to skip the stagger part when closing) or change the easing of the animation. 

 

Could startAt and endAt be an array and adding more values in there which can called in the opening an closing parts of the code? Because adding things directly in the open/close part of the code will kill the responsive part if I understand it correctly. Or add a timeline on the return, would that do the trick?

Link to comment
Share on other sites

On 11/2/2021 at 3:04 AM, JaPPa said:

I'm wondering how I could change things now thought, if I wanted to add a stagger for the list items in the UL, or add an other element to the timeline on only the mobile or desktop version. And how can speedup the closing animation or jump to a timestamp in the timeline (to skip the stagger part when closing) or change the easing of the animation. 

Sure, staggering should be easy. See https://greensock.com/docs/v3/Staggers

 

You can use a different duration for the closing animation, no problem.  Same for easing. 

 

Don't think in terms of a timeline - this doesn't need to be a timeline that you reuse. I'm dynamically creating a new tween each time in that demo so that you have even more flexibility (like using a different ease in reverse). Just about anything is possible, but unfortunately we don't have the resources to offer free general consulting services to walk you through logic issues in your code, but we're happy to answer any GSAP-specific questions. Or you can hire someone to help you by posting in our Jobs & Freelance forum. 

 

Good luck!

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