Jump to content

Alex M

360 scroll to a specific frame using Scroltrigger

Recommended Posts

Hi @maculotti.a@gmail.com, welcome to the GreenSock forums and thanks for supporting GreenSock by being a Club member!


I think the issue here is the fact that you have to take into account the size and separation of each frame in the spritesheet and then accommodate the size in the container in order to scale the position and separation accordingly. The spritesheet is a 3600px square with 6 rows and 6 columns, so why are you using these dimensions?

var spriteSheet = {
  width: 778,
  height: 778,

When you change those to 600 it works, but the issue is that the spritesheet doesn't seems to be put together properly, since it looks quite weird as you can see:

See the Pen BaPKvYo by GreenSock (@GreenSock) on CodePen


One alternative is to break the spritesheet into single images and use the approach from this airpods ScrollTrigger animation by @OSUblake


Another alternative is to use the spritesheet with PIXIJS in order to get an even better performance than in regular canvas:

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


Also you should really focus on getting the spritesheet positioned correctly first and then worry about moving it around. Sometimes the best approach is to forget about ScrollTrigger and focus on the correct HTML/CSS setup first, then get your GSAP Animations working as you expect and once you got all that, add ScrollTrigger to the mix.


Hopefully this helps. Let us know if you have more questions.


Happy Tweening!

  • Like 2
Link to comment
Share on other sites

Thanks, @Rodrigo, that really helped point me out in the right direction. 


I think the canvas solution you proposed is neater. I'm actually after an effect to have more control over the position: for instance #section-2 should be on this specific frame, #section-3 on another specific frame, and so on.

Link to comment
Share on other sites

I'm back again looking for some advices. 


I'm trying to replicate this animation: https://drive.google.com/file/d/1-DAuIAuSgHehIwyQbWeWb9wjMhyAcY4Z/view?usp=share_link

on this example I've worked with scrolltrigger for every sections and animating the entering elements but 

the main issue here is that the frame of the socks are always different depending on the viewport size. 


So I decided to come back with simple js and css animation:


I'm having all the section on position fixed so everything will be on the same position on every screen.

I'm checking the frame that I need and if we are on that specific frame I put a class to show the correct section setting opacity at 1. 


I'd like to use gsap for animate the elements inside every section with the class of 'js-show' but if I use a functions it runs multiple times. 

Any idea how to do this? 


See the Pen oNMxROz by maqquo91 (@maqquo91) on CodePen

Link to comment
Share on other sites

Hi, @maculotti.a@gmail.com. Thanks for being a Club GreenSock member! 💚🥳


I glanced at your latest code and unfortunately it's extremely inefficient. You're literally calling getBoundingClientRect() on every single "scroll" event which is quite expensive, and then you're additionally calling showSection() each time too. Very wasteful. This is why we put so much effort into making ScrollTrigger efficient - it just has to check two simple numeric values for each ScrollTrigger during the scroll to see if it's active and what the progress would be. I'm confused about why you switched to using CSS animations as well as vanilla JS rather than GSAP and ScrollTrigger. 


We don't have the resources to rebuild it all for you according to your specs, but we'd be happy to answer any GSAP-specific questions you may have. Or if you'd like to explore paid consulting options, feel free to contact us and we can do our best to help you out for a fee. 


11 hours ago, maculotti.a@gmail.com said:

I've worked with scrolltrigger for every sections and animating the entering elements but 

the main issue here is that the frame of the socks are always different depending on the viewport size. 

Would you please post a minimal demo showing your attempt at that? I wonder if you just misunderstood something. You can set up ScrollTriggers to be EXACT pixel values if you want. I have a feeling that if you provided a minimal demo and clearly explained what you're looking for (one simple step at a time, not a list of requirements), it may be a lot easier than you think. There is a "step" ease and there are snapping features baked into GSAP too. I think it may just be a matter of you grasping how to use the tools and then you'll feel empowered to do just about anything animation-wise :) I just don't fully understand exactly what you're trying to do here, so breaking it down to some simple tasks and providing a minimal demo for each will get you a long way toward a solid answer. 

Link to comment
Share on other sites

Hi @GreenSock, thanks for the answer, I really appreciate it. 

I'm aware of the inefficiency but I really was hopeless and discourage.


As a workaround to have the socks position always as I wanted, I used the snap:


OPTION 1: snap

Here is a minimal demo with snapping working and animation all set: 

See the Pen rNrMmwK by maqquo91 (@maqquo91) on CodePen

What I don't like about this solution is that the sock isn't smooth, I think because goes directly from 0 to -3600 instead of doing all the steps.


Another thinks that I'm unable to understand is why is the difference between set and to:

If I use the method .set the animation is working but if I use to. with ease function the animation isn't working. 


//Animation working
.set("#socks-container .frames", { x: -(spriteW * 10) });

//Not working
.to("#socks-container .frames", { x: -(spriteW * 14), ease: SteppedEase.config(36) })




I like the smoothness of the socks rotating here but I can't figure out how to sync this on a timeline and calculate how far does the socks need to move from one point to another. 


What I'm trying to achieve is to sync the animation of the socks scrolling with the interaction of the other sections, so basically
- from header to "section-1" the socks should move from 0 to -3.600
- from "section-1" to "section-2" move -6.000
- from "section-2" to "section-3" move -8.400


The exact frame allows me to insert some information and arrows for displaying the features of the product. 


Thanks in advance


Link to comment
Share on other sites



I think you should completely remove ScrollTrigger from this and focus on just getting the animation to work as you want using buttons on each section. Just start for setting the container for the sprite on the center of the screen with a position fixed and a big z-index, create the animations and play/restart them using buttons. Once you have the animations working add ScrollTrigger without snapping, just toggleActions or scrub in it and when you have that working as expected add the snapping functionality you want.


I know it sounds weird or counter intuitive but you'd be surprised by how many of us around here use that same approach on our workflows. ScrollTrigger is the last part of the whole thing. For example right now you have this in your code:

triggers = panels.map((panel, i) => {
  return ScrollTrigger.create({
    trigger: panel,
    start: "top bottom",
    end: "+=200%",
    onToggle: self => self.isActive && !scrollTween && goToSection(self, i),
    // markers: true

But that triggers array is not being used anywhere so you have unused code that could be affecting the way your animations and ScrollTrigger are working, so the best option IMHO is to start with just the animations and take it from there.


Happy Tweening!

  • Like 2
Link to comment
Share on other sites

Hi @Rodrigo thanks, I started to like this approach.

I've recreate a pen here: 

See the Pen NWBRYXL by maqquo91 (@maqquo91) on CodePen

 and I figure out that I was totally misunderstanding the ease functions.


I just posted here in case anyone else bumped into this problem:


ease: SteppedEase.config(4)
// This need to match the current frame that steps from the previous one, instead of the whole number of frames.


I'll start with this approach and keep going. 


  • Like 1
Link to comment
Share on other sites

Glad to hear you're making progress, @Alex M


I glanced at your code and noticed a few little things: 

  1. I'd recommend using the simplified string-based syntax for that ease: 
    // old
    ease: SteppedEase.config(4)
    // new
    ease: "steps(4)"


  2. In a .fromTo() tween, you put all the special properties in the "to" object, but you accidentally put the duration in the "from" part: 
    // bad
    gsap.fromTo("#id", { duration: .5, ... }, { ... });
    // good
    gsap.fromTo("#id", { ... }, { duration: .5, ... });


  3. You appear to either have accidentally forgotten "gsap" in front of a .to(), or you're trying to string together individual tweens as if they're in a timeline: 
    // bad
    gsap.from("#id", { ... })
        .to("#id", { ... }) // <- oops
    // good
    gsap.from("#id", { ... })
    gsap.to("#id", { ... })
    // also good (for sequencing)
    let tl = gsap.timeline();
    tl.from("#id", { ... })
      .to("#id", { ... })


I totally agree with @Rodrigo's advice about just focusing on the animation first (don't worry about connecting it to scroll at all yet). Then, once you get that looking good, THEN bring ScrollTrigger into the mix. 


If you get stuck with something GSAP-related, just post a minimal demo here that's only focused on that one part (remove all unnecessary code) and we'd be happy to help. 

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