Jump to content
Search Community

Multiple animations sequence with scrolltrigger (understanding and full controll)

maciei test
Moderator Tag

Go to solution Solved by mvaneijgen,

Recommended Posts

Hello everyone!

 

I'm having trouble understanding and fully controlling my animations with Scrolltrigger and scrub.

What I'm trying to achieve is - i want to have two animation elements (.main-title,  var points) fired by scrollTrigger with the same trigger point. However I want to animate .main-title once it's finished i want to fire the next animations which are in forEach() .animate-text with paired .country. I think i achieved that in the codepen (please feel free to correct me or show the better/more efficient way).

Now i have two problems/questions:

  1.  I want to have full control of the duration/amount of scroll of each animation (.main-title, each point etc) for example i want to .main-title to be fast then first point to be slow, the next point fast and the last point very slow. (By point I mean each elem in forEach())
  2. Also i have a bug on .main-title that sometimes it does jump up/down - no idea how to tackle this.

 

Every input/tip/better approach to the whole functionality will be much appreciated, thank you  guys in advance!

See the Pen NWJjMyo by Maciej-Koson (@Maciej-Koson) on CodePen

Link to comment
Share on other sites

  • Solution

Hi @maciei welcome to the forum!

 

What I like to do when working with ScrollTrigger is to remove it! This seems counter intuitive, but ScrollTrigger is just animating something on scroll, so just focus on the animation at first and only when you're happy with the animation add ScrollTrigger back in. This way you can focus on one part at a time and it will save a lot of headache when debugging. So if we just view the animation is this what you want to happen?

 

See the Pen RwdVJQO?editors=0011 by mvaneijgen (@mvaneijgen) on CodePen

 

Indeed it is a bit weird to wrap your head around. Normally in GSAP things work based on durations, but with ScrollTrigger that all gets thrown out the window (not really it still matters if you have multiple animations), but in ScrollTrigger the whole animation gets played over the scroll distance you've set. Right now your scroll distance is a bit weird. The height of .locations is almost 700px and you've set the scroll distance to 600% of that value, so around 4200px, nothing wrong with this but it makes it harder to explain how timing work with ScrollTrigger. 

 

So let's make it simple, if you have 3 tweens on a timeline and tell ScrollTrigger to animate that timeline over 4000px, each tween will take 1333px (eg 4000/3) to animate. A tween in GSAP has a default value of 0.5 seconds, so if we want a tween to take twice as long as the other tweens we have to give it a duration of 1 second, now the two tweens take up 1000px each and the 1 second tween takes 2000px to animate. So with this you can calculate the timing of each tween on ScrollTrigger. Hope it helps and happy tweening! 

 

57 minutes ago, maciei said:

Also i have a bug on .main-title that sometimes it does jump up/down - no idea how to tackle this.

I don't see this happening, if you could reduce the demo and tell us what steps we need to take to trigger this bug, we would be happy to take a look.

  • Like 3
Link to comment
Share on other sites

On 1/19/2024 at 1:14 PM, mvaneijgen said:

ap your head around. Normally in GSAP thin

Oh wow okay, that makes a lot of sense!
Thank you so much for providing this. Also, I watched this https://gsap.com/resources/position-parameter/ which helped a lot! 
One more question regarding controlling timing and controlling tweens:

- Is it a good approach to make multiple animations/tweens within the loop like the one below?

- What would be the best way to control tweens within the loop, what I mean is: for example I want the second element/iteration to last longer (duration 2s) but the last one to be back to normal (1s). I'm trying to catch good practice in composing an efficient set of animations that depend on each other. Also each .country element needs to be fired almost in the same time with the relevant .animate-test but i think i have done it nicely with ""<0.25" position parameter

This is my current code:

var points = gsap.utils.toArray(".point");
  // var height = 200 * points.length;
  console.log(height, 'total height')
  var locations = gsap.timeline({
    scrollTrigger: {
      trigger: ".locations",
      start: "top top",
      end: "+=5000px",
      scrub: true,
      id: "points",
      pin: true,
      markers: true,
    },
  });
  locations.to(".main-title", {
    opacity: 1,
    duration: 1
  });
  locations.to(".main-title", {
    opacity: 0,
    duration: 1
  });
  // https://codepen.io/ervinbosenbacher/pen/oNYOwaz
  points.forEach(function (elem, i) {
    console.log(elem.getElementsByClassName("country"))
    gsap.set(elem, {position: "absolute", top: 0});

    locations.set(elem, {zIndex: 100});
    // locations.from(elem.getElementsByClassName('split right'), {opacity:0}, i)
    locations.from(elem.getElementsByClassName("animate-text"), {opacity: 0, translateY: 100, duration: 1});
    locations.to(elem.getElementsByClassName("country"), {opacity: 1, duration: 1}, "<0.25");

    if (i != points.length - 1) {
      locations.to(elem.getElementsByClassName("animate-text"), {opacity: 0, translateY: -100, });
      // locations.to(elem.getElementsByClassName('split right'), { opacity: 1}, i + .25)
    }
  });
Link to comment
Share on other sites

Looks good to me! My philosophy is if it works it works! There is always time to clean things up later. There is also always the trade of being readable or being highly optimised. Personally I like readable code more than optimised code, because I rather that I can still figure it out in a year from now. 

 

9 minutes ago, maciei said:

for example I want the second element/iteration to last longer (duration 2s) but the last one to be back to normal (1s)

This could be done in so many ways and doesn't really have to do with GSAP. You could check in your loop on which iteration you're on and then do some logic based on that. You could multiply the duration based on the index and then check if the current index is equal to points.length, then you know you are at the last one. Or you can keep an array of durations = [1, 2, 17, 1] and then set the duration to duration[index] 

 

If you have a specific question regarding something in your code post a new minimal demo with a question with a  clear description of the expected result - "I am expecting the purple div to spin 360degrees" and a clear description of the issue -  "the purple div only spins 90deg" and we would be happy to take a look for you, but otherwise happy tweening and good luck with the project!

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