Jump to content
GreenSock

jasper

GS Timeline is messin' with my responsive design

Recommended Posts

So I'm building a responsive design that basically works.  I've put a GS timeline in it; that basically works too.  I'm running .from() tweens to animate the position of elements, so that I don't hard-code final positions of elements, which would interfere with the responsive layout(s).  That basically works too.

 

The problem happens when the user resizes the browser window while the animation is running.

 

The site is horribly complicated, with a bootstrap layout, but I've managed to re-create the problem in a nice simple codepen (or two).

 

The first codepen is completely JavaScript-free, just to show you the hoped-for result.  Kindly resize your browser window and notice that 600px is the threshold width at which the layout changes:

 

 

Now here's what happens when I add a GS timeline:

 

See the Pen raemZm by phranc (@phranc) on CodePen

 

Things are fine when the page is first loaded, regardless of the width of the window. However, if I resize the window above (or below) the threshold width of 600px while the animation is running, the final positions of the animated elements are not as expected.

 

It seems to me that the final positions of the .from() tweens are fixed when the timeline is initialized.  I'd be OK with just trashing and reinitializing the tlimeline when the window is resized, like this:

$(window).resize(function() {
     //trash all timelines
     //initialize all timelines
     //restart all timelines
});

However, I'm not sure how to go about that ("kill"?  "clear"?) as I'm a bit of a GS noob.

 

Or, maybe there's a better solution that doesn't require me to reinitialize the timeline (or copy/paste 100 lines of JS that I'll never understand).

 

Insights greatly appreciated!

 

See the Pen pvyPGE by phranc (@phranc) on CodePen

Link to comment
Share on other sites

To kill all tweens you could run 

TweenMax.killAll();

or more specific 

TweenMax.killTweensOf(myObject);

(myobject is any selector or jquery object)

 

Now apart from that I could not see the problem you are describing, for me the boxes kept on coming down even while I was re-sizing the browser, even when I opened the chrome mobile emulator.

 

The problem you are experiencing it might be due to intense framing, meaning that for some reason the CPU is running very intensively so you might experience those effects.

Link to comment
Share on other sites

Hi Michael71,

 

Thanks for replying! Maybe I haven't explained myself very well.

 

In the first (script-free) Codepen, the red square should be, and is, underneath the white square for window widths < 600, and to the right of the white square for widths > 600.

 

In the second Codepen, the hoped-for behaviour is for the final position of the squares to be as described above.  It works, except for when I resize the window.  If I load the page when the window width > 600 and then decrease the width below 600, the final position of the red square is the same distance from the top of the page as the white square.  Conversely, if I load the "mobile" version of the page (load the page with window width < 600) and then increase the width of the page > 600, the red square is lower than the white square.

 

In both of these cases, the final position of the red square is what would be expected with the window at its initial width, not its resized width.

 

I'm sure it's not a framing issue as I'm running an mbp with 16GB RAM and 1GB of video RAM, and anyways I've increased the duration of the tweens in the second pen to 2s each, with the same result.

 

Yes, the boxes keep coming down, but please note that the final position of the red box is not the same if you:

1/ load the page with window width > 600px

2/ load the page with window width < 600px and then resize it to > 600px

 

(the opposite case also applies)

 

thanks

Link to comment
Share on other sites

Yes I see it now, it actually makes sense, since what the media query is saying is that it should end up at 55px from top, and the tween only states where it should start from (which is -200 pixels). 

 

If you see the #thing box ends up at 55pixels from -200 so the "from" works correctly

 

I think if you add something like this:

var intro_timeline = new TimelineMax({repeat:-1, onRepeat:function(){
  TweenLite.set("#thing", {clearProps:"all"});
  intro_timeline.invalidate();
  //intro_timeline.restart();
}});
intro_timeline
  .from($('#desc'), 2, {top:"-200px"})
  .from($('#thing'), 2, {top:"-200px"});

Fixes the issue, basically the tween needs to update its starting positions

 

You can view the forked codepen here: 

See the Pen NPNzqo by netgfx (@netgfx) on CodePen

 

for a more snappy but expensive solution you could invalidate onUpdate but I wouldn't recommend it.

 

As a rule of thumb I find .to or .fromTo functions to be less confusing and offer more control.

 

I hope it helps.

Link to comment
Share on other sites

Hi Michael71, thanks for your perseverance, it's appreciated!

 

basically the tween needs to update its starting positions

 

 

Sorry, now I'm confused.  Did you mean "ending positions"?  I hard-coded the starting positions in the timeline code, and am using CSS to determine the ending positions, no?

 

for a more snappy but expensive solution you could invalidate onUpdate but I wouldn't recommend it.

 

Care to elaborate? :D

 

Your solution is instructive, but the actual timeline is a lot longer than the one in the codepen (about 30 seconds), so I'm still looking for a way to reinitialize and restart the timeline on a window.resize() event.  Thanks for pointing the way to clearprops though...

Link to comment
Share on other sites

As far as I understand when a tween is defined it "stores" the position of the item that is about to tween and then animates it (starting or ending positions I guess depends on the .from or .to declarations). In your case that "starting/ending" position has changed while the animation was running (that is logical since the animation repeats so it never ends) and whilst the css position changed from 55 to 0 the tween doesn't know that.

 

That is why we try to run invalidate which clears starting positions. more info here: http://greensock.com/docs/#/HTML5/GSAP/TimelineMax/invalidate/

 

One way would be to add the following on the resize event:

var tm = new TimelineLite({});

window.onresize = function(){
tm.kill();
tm.invalidate();
tm.restart();
};

I hope I'm making more sense now. The point is that if the css that the tween is affecting changes, the tween needs to be updated.

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