Jump to content
Search Community

Guidance on changing / adding class names on pinned section + revealing elements on pinned scroll

amit95 test
Moderator Tag

Recommended Posts

I'm seeking guidance on how to achieve what I'm after, as I'm stumped on the next steps at the moments.

 

  1. This pinned section which contains 4 text elements. By default 2/4 text elements are shown. Then, on scroll one more will show, then the last (and then unpin). I have added an image on its default view for reference. Is the best way around this to do something like :nth-child(n+2){ opacity: 0; } and then to made the proceeding items opacity 1 and translate in? 
  2. On the "active" text element, I want to add a class to it to make its opacity 1 (as it is set to 50% via css).  I'm aware that toggleClass exists, but unsure on how I can target $(this) or the current element? Unless the solution is to use something like the below?

 

onEnter: () => $(this).addClass('pinnedBgText__text--active'),
onLeave: () => $(this).removeClass('pinnedBgText__text--active'),

 

Image for default state reference:

 

703205959_Screenshot2022-09-17at00_43_52.thumb.png.910ec97813a3511185e4d85707ae9770.png

 

Please view pen in full screen.

 

See the Pen ExLWvRX by amit_rai95 (@amit_rai95) on CodePen

Link to comment
Share on other sites

Hi,

 

Does the following code helps you creating the animation you're after?:

let container = document.querySelector(".pinnedBgText");
const texts = gsap.utils.toArray(".pinnedBgText__text");

// Hide and move down the last two elements
gsap.set(texts.slice(2), { opacity: 0, y: 50 });

const tl = gsap
  .timeline({
    scrollTrigger: {
      trigger: container,
      pin: ".pinnedBgText",
      anticipatePin: 1,
      start: "top top",
      end: "+=1000",
      scrub: 1
    }
  })
  .to(container, {
    x: () => -(container.getBoundingClientRect().width - window.innerWidth),
    duration: 4
  })
  .to(texts, {
    opacity: 1,
    y: 0,
    duration: 1,
    ease: "none",
    stagger: 0.5
  }, 0.25);

First hide the last two elements. Then it might be easier to just create a timeline to control both the container movement as well as the texts animations. Create a staggered animation for the texts that starts a bit after the container starts moving.

 

Happy Tweening!!!

Link to comment
Share on other sites

Hi @Rodrigo

 

It's sort of what I'm after. This is on me for not clarifying in my original question, but at most, only two text items will be shown at one time.

 

Here's a walkthrough of the flow I'm after:

  • User scrolls to .pinnedBgText, at which point the section pins. At this point, the first text item will be opacity: 1, whilst the other text item will be opacity: 0.5, like in the image in my first post.
  • Then, the user scrolls down, making the second item (which was opacity 0.5) to opacity: 1 (showcasing that this text is now the "active" text). The first text item then becomes opacity: 0.5.
  • The user scrolls down further which makes the first text item translate off screen, and then the third text item will translate up, below the second item (as only two text items should be present on screen). This item will then be opacity: 1
  • and so on...

Hopefully the above made sense?

 

I believe what may be required to achieve something like this would be a nested pinned container, for the text elements?

Link to comment
Share on other sites

The best thing to do 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.

 

I was looking for the logic in the animation, but I couldn't find it. I myself usually then spend several hours trying to figure it out, while it is usually better to just write it out how it should work and worry about it later how to make it dynamic, so that is what I did.

 

See the Pen ZEoejBV?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

 

This should be the timeline (this is not dynamic) and now you need to move this code in some sort of loop (I think a ,forEach()) and have checks for if it the frist animation or the last, because those are the only once that are different. Or if it doesn't need to be dynamic use it as is.

  • Like 2
Link to comment
Share on other sites

Hi @mvaneijgen,

 

Many thanks for the demo. I've had a play around with the animation and have tested it with ScrollTrigger - All works well so far.

 

As you've mentioned, it needs to be dynamic (for example, more than the demoed 4 .pinnedBgText__text elements may exist). 

 

I can see that in your demo, you're accessing the array index numerically, changing 2 text elements to make the animation work (i.e. texts[0] and texts[1] to make the first two text items work accordingly.

 

As such, I can't do something like:

 

var i = 0;

texts.forEach((text) => {
  
  tl.to(texts[i], {
    
  });
  
});

Because they'll hold the same value for each loop.

 

Could you provide me with a hint on how I can make this dynamic?

 

Here's the latest demo:

 

Link to comment
Share on other sites

9 hours ago, amit95 said:

it needs to be dynamic

 

Ha, I thought so!

 

9 hours ago, amit95 said:

As such, I can't do something like:

 

 

You can! The second value you pass in a forEach is the index of the item. With this you could easily do text[index+1] 

 

texts.forEach((text, index) => {...})

Still the first and the last animations  need to be different, so you'll need to check if you're at the first index or at the last item in the index, with something like this. 

 

if(index === 0){ CUSTOM_TWEEN }
if(index === texts.length){ CUSTOM_TWEEN }

 

Hope it helps! Sorry I don't have time to code anything up myself, but be sure to post back if you've got something up and running, but are stuck on something.

Link to comment
Share on other sites

@mvaneijgen

 

Everything needs to be dynamic nowadays 🥲

 

With your above advice, I believe I'm on the right track. Is this newest codepen what you were referring to?

 

 

Additionally, consider the following snippet:

 

tl.to(texts[i+1], {
  opacity: 1,
  duration: duration,
}, "<");

In the above, what's the purpose of "<" ?

Link to comment
Share on other sites

Yep looks good. 

 

17 hours ago, amit95 said:

In the above, what's the purpose of "<" ?

 

That is the position parameter, that one in particular means "play at the sametime as the previous tween", There are a lot more variants (see the  docs)

 

I highly recommend watching some of the videos from Greensock, just to get a feel for what is all possible, that will get you up and running so much faster and while your at it also checkout @Carl videos 

 

https://www.youtube.com/c/GreenSockLearning/videos

https://www.youtube.com/user/snorklTV/videos

 

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