Jump to content
GreenSock

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

Page jumping/scrolling due to repaint..?

Recommended Posts

Hi guys,

 

Been struggling with this for a while now, and not really sure what can be done about it.

 

If you look at my codepen, when the animation is played, the green box stretches out to become really long.

 

If you then scroll down the page to click the reverse button, the page will jump up to a random point in the page.

 

After a lot of googling, I found a solution, which is commented out in the Javascript section of the codepen.

 

If you comment out the line that's enabled, and uncomment the three lines for the working solution, then it should behave as I want it to.

 

Adding a timeout of 1 millisecond will apparently fix the issue, which I believe is related to the page repainting too quickly, but I'm not 100% sure.

 

This is on Windows 7 - Google Chrome, by the way. Not sure if the issue exists on other browsers yet.

 

 

Has anyone else encountered this problem before? If so, how did you overcome it? setting a timeout seems a bit messy and hack-ish...

 

 

I realise that this isn't strictly a GSAP problem, but figure that the pro's here will likely be well educated to shed some light on this anomaly.

 

 

The real problem I'm having is related to changing a relatively positioned element into an absolutely positioned one, and I'm not sure how I'd get the timeout in to a set, within a TimelineMax, so any advice on that front would be most welcome too.  8-)

 

 

Many thanks!  :-P

See the Pen bgEQKW by anon (@anon) on CodePen

Link to comment
Share on other sites

It only seems to be working sporadically for me now with the timeout. Setting it to 10 seems to help a little.

Link to comment
Share on other sites

Hey kez1304,

 

What is the behaviour you are looking for?

 

I don't see the need to switch the position:relative into position:absolute.

 

To me, the issue is with the fact that you are trying to manipulate the CSS via jQuery, invalidating the timeline, changing its timeScale property and reversing it, all at the same time.

 

If I change your switch statement to the bellow, the timeline plays and reverses without the jumping you are talking about.

 

switch($(this).attr('name')) {
 case 'play':     
  tl.play();
 break;

 case 'reverse':
  tl.reverse();
 break;
}

Would that not be the desired effect?

  • Like 3
Link to comment
Share on other sites

Hello kez1304,

 

The jump is happening since your removing the height to an empty string "" using jQuery css() for .box

 

But Dipscom example is a great way to solve your issue!

 

Normally to prevent the page jump up you need to add return false or event.prebentDefault() on the button event handler. That is normal behavior for clicking a button element. Since your using jQuery you can just use return false which is the same as calling

event.preventDefault();
event.stopPropagation();

But that's not whats happening in your example, since height becomes an empty string it will cause that jump since the container no longer has a defined height.

 

Also keep in mind not to change properties that your are animating with GSAP with jQuery. For example you are using jQuery CSS to set height. But also using GSAP to animate height. The equivalent of jQuery css() is GSAP set() method. Since GSAP will not know your are changing CSS properties outside itself

// this using jQuery css()
$box.css('height', '');

// becomes this with GSAP set() method
TweenLite.set($box,{'height':''});

GSAP set() : https://greensock.com/docs/#/HTML5/GSAP/TweenLite/set/

 

But the way you have your switch statement is what is causing the page jump regardless of the default behavior of the button element. Due to the removal of height with empty string "".

 

So what Dipscom (Pedro) has posted above is a great solution using play() and reverse() :)

  • Like 4
Link to comment
Share on other sites

Hi Dipscom,

 

That codepen is purely a simple example to demonstrate the problem.

 

The reason for switching to absolute is that; I have a div that's left floated, and another div that sits to the right of it, with some dynamic text in it... I need to find the height of the text containing div when it's a true block level element.

 

I thought the best way to get around this was to have a function, that quickly switches the text containing div to an absolutely positioned div, it would become 100% of the page width, I can grab the height of the text containing div, and then remove the position style.

 

Is there a better way to grab that value? Without reflowing the page? Or is there anything I can do to get around this issue?

 

 

UPDATE:

 

Here's a codepen that better demonstrates what I'm trying to achieve, and the problem... 

See the Pen JEXaxG?editors=0010 by anon (@anon) on CodePen

Link to comment
Share on other sites

Eureka!
 
I realise now that it was a fault in my approach to this issue...
 
I was passing a function that calculated the theoretical height of the text containing div, INTO the GSAP animation itself.
 
I can only assume that because GSAP couldn't identify what the value was in advance (and I was invalidating the timeline), that it could only determine the value as it was executing... BECAUSE OF THAT, if that particular tween animation would result in there not being enough space between the current viewport and the bottom of the window, GSAP (or maybe the browser itself..?) would force the screen position to jump up, to accommodate for the newly learnt value.
 
Having moved the function call OUT OF THE value for the paddingBottom, and instead set a variable to its value (that also updates on resize), and using that new variable as the value for paddingBottom... All is well.
 
I guess GSAP doesn't get interrupted whilst it's doing its thing, and knows exactly what it's animating to from the get go.
 
Moral of the story is not to call functions to get tween values, or are there times when that's perfectly acceptable and advisable?

var tl = new TimelineMax();

tl.
  to(element, 1, {
    x: someFunction
  });

function someFunction() {
  return (33 + 66);
}

For example?

Link to comment
Share on other sites

There's no problems with calling functions to get values, what you have to remember is that you will need to recreate the tween/timeline every time you need to update that value. It is not dynamic.

Link to comment
Share on other sites

There's no problems with calling functions to get values, what you have to remember is that you will need to recreate the tween/timeline every time you need to update that value. It is not dynamic.

 

Yup, so I just tl.invalidate().play(), each time, and I'm golden?

Link to comment
Share on other sites

So goes the theory, yes... ;)

 

Do remember that if you don't rewind the timeline, when you .play() it again, the elements will start from where they were when you .invalidate()'d them.

 

Like:

tl.seek(0).invalidate().play()
  • 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.
×