Jump to content
Search Community

Setting Timescale on Timeline has no Effect

Ben Carey test
Moderator Tag

Recommended Posts

I have set up a timeline that is controlled by the user's scroll position. See the following (it's in Vue.js but that shouldn't really affect anything here):

 

this.scrollImageHeight = this.$refs.image.clientHeight;

let trigger     = 100;
let duration    = this.scrollImageHeight * 0.8;

this.scrollTimeline = new TimelineMax({ paused: true })
    .to(this.$refs.left, duration, { x: '-2.5%', y: '10.6%', force3D: true }, trigger)
    .to(this.$refs.center, duration, { x: '132%', y: '58.7%', force3D: true }, trigger)
    .to(this.$refs.right, duration, { x: '68.5%', y: '-6.7%', force3D: true }, trigger)
    .to(this.$refs.center, 100, { scale: 1 });

 

Then, in order to make the timeline responsive, I intend to update the timeScale whenever the user resizes their screen (yes, I am debouncing the resize callback :-)).

 

const timeScale = this.scrollImageHeight / this.$refs.image.clientHeight;

this.scrollTimeline.timeScale(timeScale);

For some reason, setting the timeScale has absolutely no effect on the timeline. The timeline keeps the original duration set when the timeline initialized. I have also tried changing the duration of the timeline but this also had no effect.

 

I have confirmed that the number passed into timeScale is correct. I have tried hardcoding other numbers to see if that has any effect but nothing seems to work.

 

I am using gsap version 2.1.3.

 

Can anyone suggest what I am doing wrong here?

 

Note: I haven't supplied a codepen as this is just a snippet taken from my large Vue component, and I am hoping that I am just missing something really obvious and you will be able to point it out. If that is not the case then I will do my best to create a codepen.

 

In addition, in case this is relevant, this is my scroll callback:

 

this.scrollTimeline.time(window.pageYOffset);

 

Link to comment
Share on other sites

Hey Ben and welcome to the GreenSock forums! 

 

Using timeScale to make a timeline responsive is an... interesting approach :) we generally recommend killing off the previous tweens/timelines and creating new ones on resize if the need be. Alternatively using responsive units or something like intersection observers make it so you don't have to do that a lot of the time. 

 

It seems like this.scrollTimeline.time(window.pageYOffset); would be passing in numbers that are much larger than the duration of the timeline if the page is very tall. I might check to make sure that value is within the time of the scrollTimeline.

 

Besides that, it's really hard to say what's going wrong. Sorry, but it'd be very helpful for us to see a minimal demo.

 

P.S. Why not use GSAP 3? It's smaller, has a lot of new features, and has an improved API. If you do switch over to GSAP 3, use the beta file for now because version 3.0.5 has a regression related to timeScale.

  • Like 1
Link to comment
Share on other sites

Hi Zach,

 

Thank you very much for your prompt response :).

 

The way I am using timeScale is by calculating the percentage change in my responsive image height, and then inverting that percentage change and applying it to the timeScale. In other words, think of it like this:

  1. User starts on large screen
  2. Responsive image height is 1500px
  3. Timeline duration is 1500 (the height of the image that will be animated)
  4. User resizes the screen (smaller)
  5. New image height is 1000px
  6. Calculate the new timeScale by doing originalHeight / newHeight i.e. 1500 / 1000 = 1.5

This should increase the speed of the animation on smaller screens and decrease it on larger screens. For some reason, it does nothing...

 

I have checked all of the numbers being inserted into timeScale and they are correct. Just to double check, I hardcoded the following and still couldn't get it to make any difference to the speed of the animation:

 

this.scrollTimeline.timeScale(1000)

It seems that timeScale has no effect on my Timeline and I don't understand why. Could there be scenarios where timeScale is ignored?

 

I saw there was a new version the other day and I was tempted to upgrade but this is a large project and there are various places I am using Tween and Timeline etc so the upgrade will take me time that I am quite limited on at the moment. That said, if you think upgrading may fix my issue then I will go ahead and do it...

 

You are right, technically large numbers will be passed into this.scrollTimeline.time(window.pageYOffset);, however, I assumed that Timeline would just ignore the number outside of the animation bounds, thus, it wouldn't cause any issues. Am I wrong here?

 

Creating a demo is really difficult due to the size of this component, and the fact that it is Vue. I was hoping that the issue would be really obvious and therefore I could avoid it but if there is nothing that stands out to you then I will have to find a way to create a simple demo.

 

Just to add to the above, I can confirm that this.scrollTimeline.timeScale() reflects the set value when I get it. In other words, it is succesfully setting the timeScale, it just isn't doing anything with it. It is basically as if the Timeline is ignoring the timeScale, no matter what the set value is.

Edited by Ben Carey
Link to comment
Share on other sites

In case anyone comes across this post in future; I wasn't able to identify the issue with timeScale, however the method that Zach originally suggested is the way in which to go about handling this. Namely, recreating the timeline on each resize (use a debounce function):

 

_handleResize() {

    // Debounce the scroll animation initialization
    if (this.resizeTimeout) {
        clearTimeout(this.resizeTimeout);
    }

    this.resizeTimeout = setTimeout(this.initializeScrollAnimation, 100);

}

And then re initialize the timeline:

 

initializeScrollAnimation() {

  // Empty the timeline if it already exists
  if (this.scrollTimeline) {
    this.scrollTimeline.clear();
  }

  const trigger   = 100;
  const duration  = Math.max(this.$refs.image.clientHeight * 0.6, 800);

  this.scrollTimeline = new TimelineMax({ paused: true })
    .fromTo(this.$refs.left, duration, { x: '-12.5%', y: '.6%', rotation: -45.01, autoAlpha: 0 }, { x: '-2.5%', y: '10.6%', rotation: -45, autoAlpha: 1, ease: Power1.easeInOut, force3D: true }, trigger)
    .fromTo(this.$refs.center, duration, { x: '240.1%', y: '73.8%', rotation: -45.01, autoAlpha: 0 }, { x: '220.1%', y: '63.8%', rotation: -45, autoAlpha: 1, ease: Power1.easeInOut, force3D: true }, trigger)
    .fromTo(this.$refs.right, duration, { x: '88.5%', y: '4.7%', rotation: -45.01, autoAlpha: 0 }, { x: '68.5%', y: '-6.7%', rotation: -45, autoAlpha: 1, ease: Power1.easeInOut, force3D: true }, trigger)
    .fromTo(this.$refs.center, duration / 2, { scale: .85, filter: 'drop-shadow(rgba(0, 0, 0, .3) -60px 75px 33px)' }, { x: '218%', y: '62%', scale: 1, filter: 'drop-shadow(rgba(0, 0, 0, .6) -60px 75px 33px)', ease: Power1.easeInOut, force3D: true });

  this._updateScrollTimeline();

}

 

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