Jump to content
Search Community

GSAP animate height and expand

DD77 test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I'm trying to expand the content using GSAP, so I can have the height animated of the hidden content. 

If you click the "Sterilisers" button/product, you expanding the content. 

I applied GSAP but with not the expected result. Please advice what's the best  way.

 

$('.js-tile').richTile().on({
  'expanded.RichTile': function(event, tile) {
    // disable siblings on expand
    var siblings = tile.element.siblings('.js-tile');
    siblings.richTile('enable');
    siblings.richTile('collapse');
    
      var currentTile = $(this);
      var $tiles = $('.js-tile');
      $tiles.not(currentTile).addClass('not-expanded');
    console.log('click 1');
    TweenMax.from(".Tile.is-expanded .Tile-flyout", 0.8, { height:0 , opacity: 0, autoAlpha:0, ease: Power1.easeOut });
      
    // re-enable when this tile is collapsed
    tile.element.one('collapsed.RichTile', function() {
      siblings.richTile('enable');
      $tiles.not(currentTile).removeClass('not-expanded');
      
      console.log('click 2');
      TweenMax.from(".Tile-flyout", 0.8, { height: 0, opacity: 0, autoAlpha:1, ease: Power1.easeOut });
   
    });
  }
});

 

See the Pen ZaxOzQ by davide77 (@davide77) on CodePen

Link to comment
Share on other sites

Hi @DD77,

 

I'm not totally sure what is the behaviour that you are expecting and you seem to have a lot of code for what appears to be a expand/collapse logic.

 

I think your issue lies in the fact that you are using .from() tweens. They can be quite tricky to work with if you are not sure how they behave.

 

From you title, you want this to be responsive and I don't think animating the height of the element will work. Try using scaleY for that.

 

What you want to do in this case is to have a .fromTo() call instead of just a .from(). You can also scale the children in the opposite direction in order to keep them from deforming. Bellow is a quick example how you could go about it:

 

TweenMax.fromTo(".Tile.is-expanded .Tile-flyout", 0.8, { scaleY:0 , autoAlpha:0, ease: Linear.easeNone }, {scaleY:1, autoAlpha:1});
TweenMax.fromTo(".Tile.is-expanded .Tile-flyout > *", 0.8, { scaleY:2, ease: Linear.easeNone }, {scaleY:1});

 

I didn't spend the time to work out the scaling correctly but I think it will give you a good idea. This way, your animation will be more performant as well, by the way.

 

:)

  • Like 3
Link to comment
Share on other sites

13 hours ago, Dipscom said:

You can also scale the children in the opposite direction in order to keep them from deforming...

 

I didn't spend the time to work out the scaling correctly but I think it will give you a good idea. 

 

It doesn't take a lot of time to figure out the reciprocal of a number. Just divide 1 by the starting scale to get the inverse scale.

 

I'll give you a second to figure that out...

 

1 / 0 = ???

 

z1wKgAp.jpg

 

 

You just created a universe ending paradox, that will destroy anything and everything.

 

Ok. So let's use a small value instead, like 0.01. This should work, right?

 

var scale = 0.01;
var invScale = 1 / scale;
    
TweenMax.fromTo(".Tile.is-expanded .Tile-flyout", duration, { 
  scaleY: scale, 
  autoAlpha: 0, 
}, {
  scaleY: 1, 
  autoAlpha: 1,
  ease: Linear.easeNone 
});
    
TweenMax.fromTo(".Tile.is-expanded .Tile-flyout > *", duration, { 
  scaleY: invScale, 
}, {
  scaleY: 1,
  ease: Linear.easeNone 
});

 

 

Let's see what happens when you click on the Sterilisers product. You will probably need to open these demos up inside CodePen as the small height of the embedded pen hides what's going on. Also note that you will need to click the run button to reset it. 

 

See the Pen GOxdar by osublake (@osublake) on CodePen

 

 

Oh noes! What's going on? Both animations are using a linear ease, so the scale values are changing at the same rate, but they look like they are moving at completely different speeds.

 

If this is starting to sound familiar, it's because it's the same scaling problem I struggled with here.

 

 

So let's put that exponential scale ease that @GreenSock came up with through some more testing.

 

function ExpoScaleEase(start, end) {
  var factor = Math.log(end / start);
  var change = end - start;
  return function(v) {
    return (start * Math.exp(factor * v) - start) / change;
  };
}

//to use it, you pass in the start/end scales...
TweenLite.to("#img", 5, {scale:0.5, ease:ExpoScaleEase(30, 0.5)});

 

 

And here's the result. Pretty darn close!

 

See the Pen aVYKEv by osublake (@osublake) on CodePen

 

 

That whole demo is broken, so there's probably some CSS throwing it off a tad, but overall I think it demonstrates how adding an exponential scale ease to GSAP would be a good idea. All aboard the performance driven counter-transform train!!!

 

  • Like 5
Link to comment
Share on other sites

Something in that demo was definitely causing drifting to happen. I made an isolated demo, and everything works as expected.

 

One thing I noticed when using exponential scale is that it is kind of like a linear ease, which may not be what you want, so I modified it to accept an optional ease.

 

Also added some checks to prevent errors. Not sure what would be the best way to handle zero and negative numbers.

 

function ExpoScaleEase(start, end, ease) {
    
  var change = (end - start);
  var factor = Math.log(end / start);
  
  if (!change || !factor) {    
    console.log("Invalid ExpoScaleEase values: %s, %s", start, end);
    return ease || Linear.easeNone;
  }
    
  if (ease) {
    return function(v) {
      return (start * Math.exp(factor * ease.getRatio(v)) - start) / change;
    };
  }
  
  return function(v) {
    return (start * Math.exp(factor * v) - start) / change;
  };
}

// to use, pass in the start/end scales and an optional ease
TweenLite.to("#img", 5, {scale: 0.5, ease: ExpoScaleEase(30, 0.5, Back.easeOut) });

 

 

Looks best in Edge. Probably because it doesn't support the will-change property, which makes me happy :-D

In Firefox, the child element can get real blurry during the animation, and without will-change, screen tearing may happen.

 

See the Pen VrXVWd by osublake (@osublake) on CodePen

 

 

 

  • Like 3
Link to comment
Share on other sites

7 hours ago, OSUblake said:

You just created a universe ending paradox, that will destroy anything and everything.

 

Maybe I am trying to do exactly that.

 

Maybe I'm just tired of it all. I get next to no time to GSAP anymore. Life's got complicated and I don't like it.

 

But you have foiled my plans. I now need to find another way to create a singularity. Who knows? I might be reborn in this new universe with actual mathematical knowledge.

 

Link to comment
Share on other sites

Much better, isn't it, @DD77?

 

And you have removed all the excess code, which made it much easier for me to go over the code.

 

The only things I would mention is that you don't need to .set() the display to "none" and I would remove the 0.6 second delay from the animation - You want the animation to start immediately once the click is registered.

 

To level up, I would challenge you to change the code to implement the scaling technique, rather than the height to improve the smoothness and performance of your animation.

 

:D

 

Well done.

  • Like 3
Link to comment
Share on other sites

  • 3 years later...

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