Jump to content
Search Community

Two ScrollTrigger problems with forEach loop: element after pinned elements collapsing and background color jumps shortly to white in between pinned elements

GalaxySurfer
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

GalaxySurfer
Posted

Hi all,

 

I'm building a section for a website with separate ScrollTriggers for desktop and mobile.

The desktop one is a split screen with two columns, the left having a pinned image container with cycling images and the right column with scrolling text.

In the mobile version the items are set up as panels, scrolling on top of each other.

I have two problems and can't figure it out.

 

  1. in the desktop version, when the new trigger is fired, the background color is animating, but it shortly resets to the body color
  2. in the mobile version (<600px) it works well, since I could set the background color on the panel in the forEach loop instead of the larger section color. Here the problem is that after the fourth item, the pinSpacing:false that I set on the ScrollTrigger makes the content after the trigger, so the next section on the page, fall behind the last panel. I can't set pinSpacing to true, since then the panel animation won't work anymore.

 

I tried to look these things on the forum but couldn't find the solution, sorry. Hope you can set my off on the right path, appreciate the help.

 

See the Pen GgRBqBM by GalaxySurfer (@GalaxySurfer) on CodePen.

mvaneijgen
Posted

Hi @GalaxySurfer welcome to the forum!

 

The best thing 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.  
  
Most of the ScrollTrigger effects you see are just moving things on the y-axis instead of scrolling them, then hooking that animation to ScrollTrigger will give the illusion of scrolling, but they are really just animating! Getting to grips with this knowledge will make it so much easier to create all kinds of effects, I've written a whole post about it, check it out:

 

 


Currently you're creating a ScrollTrigger for each card, where with the explanation above you can create one timeline and one ScrollTrigger to get the same effect and then you don't have to worry about pinSpacing issues. Bonus you can even have one of your cards come in from the left or right if you so desire, creating animations will make things so much more flexible. 

 

Hope it helps and happy tweening! 

 

Btw you can solve your flashing to default color, by setting immediateRender: false, on the timeline. But staring with a timeline with all your tweens on it wouldn't even have this problem, so my initial solution is so much easier 

 

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

GalaxySurfer
Posted

Hi @mvaneijgen, thanks for your quick reply!

I saw a Youtube short recently from Cassie advising the same, but apparently I didn't wrap my head around this concept yet and I also have to digest your words haha.

But will try to translate your words to my pen and will show the result in the next few days.

Cheers for your help, and a 👋 from somewhere in the Netherlands too. 😀
 

mvaneijgen
Posted

Ha, yeah it is hard to wrap your head around. It is so much more logical to think "I want something to scroll, so that is what I'll be focusing on"

 

But trust me, animating things and then hooking that to ScrollTrigger will open a world of possibilities! 

 

Ha, had al het vermoeden dat je Nederlands was! Veel geluk met je project! 

  • Like 2
Rodrigo
Posted

Hi,

 

Why not use the endTrigger config property and set the element right after that section:

https://gsap.com/docs/v3/Plugins/ScrollTrigger/?page=1#endTrigger

 

Something like this:

mm.add("(max-width: 599px)", () => {
  // Featured item becomes panel with background color and slides up on scroll
  let panel = gsap.utils.toArray(".featured-item");
  // let panelNotFirst = gsap.utils.toArray(".featured-item:not(:first-child)")
  gsap.set(panel, { backgroundColor: gsap.utils.wrap(bgColorItem) });

  panel.forEach((element, index) => {
    ScrollTrigger.create({
      trigger: element,
      start: "top top",
      end: "top bottom",
      endTrigger: ".spacer.pin-end",
      pin: element,
      scrub: true,
      markers: true,
      pinSpacing: false
    })
  });
  // end of mobile query
});

Here is a fork of your demo:

See the Pen jEOpZvw by GreenSock (@GreenSock) on CodePen.

 

Hopefully this helps

Happy Tweening!

GalaxySurfer
Posted

Hi Rodrigo, yeah that's a really neat solution, thanks!

I'm going to fork my old pen and try to build the animations via the way mvaneijgen suggested, and see how far I'll come and which method works best for me. Keep you posted.

GalaxySurfer
Posted

Hi all,

 

I've been working on the CodePen with medium success.

Here's the new pen: 

See the Pen pvoqzgm by GalaxySurfer (@GalaxySurfer) on CodePen.

 

The good part: I've managed to get the mobile animation working the way I like it, making the featured items into cards and stacking them. The method I've used was @mvaneijgen's suggestion to get the animation right firstly, before doing any ScrollTriggering, hereby helped by Cassie's tiny ScrollTrigger tutorial.

 

With the desktop animation I couldn't get it to work. I could animate the background color of the parent wrapper sequentially in a timeline, using labels, but when I added this to a ScrollTrigger scrolling over each item made the cycle through all the colors, instead of one.

Then I found the answer of @ZachSaucier in this thread, bringing me a step further in the cycling through the background colors, even helping me to return to the original background color outside of the array. The problem here is I suddenly wasn't able to get the image animation working anymore, no matter what I tried. It's probably something small but I give up, since I'm not doing anything different then before as I know. So if someone can have a look, my javascript and GSAP skills are just not developed enough I guess. I could always set up a new ScrollTrigger just for the images, but they should be able to live in one timeline with the background color animation right?

 

Thanks in advance.

mvaneijgen
Posted

I've just picked your mobile animation, because that one seemed to be setup perfeclty. I would just bake the background color changing directly in the animation. Personally I always like to start with a timeline when working with GSAP. Animate your cards up one by one and at the same time add the background animation you want. 

 

I’ve placed some comments in your JS to better explain things, please be sure to read through them!

 

As you can see I've also removed ScrollTrigger for now and installed GSDevTools (a premium plugin you can use for free on places like Codepen!) so that we can really focus on the animation that needs to happen. 

 

This logic you could also apply to your desktop version, but your desktop animation seems to be a bit to complicated for me, I would also just build an animation like you build with the mobile version

 

Hope it helps and happy tweening! 

 

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

GalaxySurfer
Posted

See the Pen jEORoPw?editors=1010 by GalaxySurfer (@GalaxySurfer) on CodePen.

 

Ok I got the result that I'm happy with!

I combined the techniques of all the examples you gave, because f.i. one example had the nice desktop animation with the sliding images and content, but without the background animation.

For the desktop I used a forEach loop to cycle through each item, for the mobile version I used the large ScrollTrigger cycling through one timeline. I can't exactly explain why haha, but I had some troubles using the latter for the desktop version.

Probably it can be done with more compact code (so please feel free to comment!), but very happy for now. Will continue learning (bought a course), also on my javascript skills, to understand better what I'm doing and to get a better grip on all the different ways things can be done.

Thanks for all the help, will now implement it to my portfolio.

 

 

  • Like 2
Rodrigo
Posted

Hi,

 

Great to hear that you got it working and the advice was helpful.

 

The only thing I could add is here:

rightContent.forEach( (title, i) => {
  let tl = gsap.timeline({defaults: {ease:"none"}})
  .from(leftImage[i], {yPercent:101, opacity:0})
  .from(rightContent[i], {opacity:0}, "<=")
  .to("body", {backgroundColor:colors[i]}, "<=")

  ScrollTrigger.create({
    trigger: title,
    start: "center 90%",
    end: "center 50%",
    animation: tl,
    scrub: true,
    pinSpacing: false,
    immediateRender: false
    // markers: true,
  })

})

In the ScrollTrigger config there is no need for the pinSpacing option, since you're not pinning the trigger element, so you can remove that without any issues.

 

Happy Tweening!

  • Like 1
GalaxySurfer
Posted
16 hours ago, Rodrigo said:

The only thing I could add is here:

In the ScrollTrigger config there is no need for the pinSpacing option, since you're not pinning the trigger element, so you can remove that without any issues.

 

Got it, cheers!

GalaxySurfer
Posted

 

Looking back at all the answers I'd like to thank you all for all the options given.

It's hard to select one post as a solution.

 

If I'm correct two main solutions were proposed: one with an animation for each item, and one with one large ScrollTrigger for the full list, setting the end in a way that scrolling feels natural. Hereby my experiences as a newbie coder:

  • forEach() method: I wasn't able to fix a proper ending, after cycling through each item, since the onComplete is after each item. Also some problems with syncing the array of background colors to the loop, with weird results. I guess more in general modifying an element that's not the looping element itself was challenging. It's also hard or not possible to alter the animation for a particular item, whereas in the option below you make a complete timeline for the total animation and can customize the animation of each item as you wish.
  • Full animation first, ScrollTrigger later: in the mobile solution with the cards it worked well, but didn't fully get the concept in the desktop version for some reason at first, the concept was harder to grasp there for me, maybe because of the scrolling of the right column that doesn't need to be included in the timeline, and I thought it did. I also had problems with configuring speed, scrolling felt a bit unnatural, I had to try a few numbers before coming close. I'm not skilled enough to let javascript do the calculation dynamically using the amount of items and it's height of each item. I used the calculations in the examples given here, but struggled anyway and have to dive deeper into this aspect of coding, as I now understand it's importance.

Having said all this I'll pick Rodrygo's answer with the two examples. The forEach method feels a bit more natural to me at this moment, and I borrowed quite a bit from the first example (but it didn't have the animating background, took me ages to add it without weird color shifts.....!). Will dive deeper in the method Michiel offered because I see the beauty of having one animation first, with the timeline and GSDevTools.

 

Cheers, happy coding!

  • Like 1

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