Jump to content
Search Community

ScrollTrigger and Lottie animation flickering problem

lucky111 test
Moderator Tag

Recommended Posts

Hi
We have previously discussed witch of the two implementations of ScrollTriger controlling a Lottie animation is the best and most effective.
There are two
1. The one shown in the examples at greeensock https://greensock.com/docs/v3/HelperFunctions#lottie
2. Ant the one implemented by the user Chris Gannon https://github.com/chrisgannon/ScrollLottie

 

In a previous thread we agreed that the first approach seems the best and most effective, but in a resent project I'm working with I'm starting to notice some flickering in the Lottie animation witch was disapered when I switched to approach 2. The flickering starting appear in very long Lottei animations.
Then object that are moving fast in the animation starts to flicker.

I have made two pens to point out this problem
You can here see how the flickering only appear in the approach 1 pen.

I'm curious to now what causes this
Do you guys have any clue?


 

 

 

See the Pen MWpYoWp by lucky111 (@lucky111) on CodePen



 

 

 

 

See the Pen jOBEmRq by lucky111 (@lucky111) on CodePen

Link to comment
Share on other sites

This is a guess - but the first approach has a 'scrub: 2' so it's taking two seconds to catch up to the scroller.

These 2 seconds are effectively 'easing out' of the animation - If we were animating that rocket with GSAP and motionpath plugin, we'd be animating the actual elements' position, so we'd just see a gentle decrease in speed.

However with Lottie it's effectively a big sprite player, so the easing out is actually slowly playing a few final frames. You can see this 'flicker' if you save out a Lottie animation with a low frame-rate and then play it slowly. It's like a flick-book, you get frames instead of lerping values.

  • Like 4
Link to comment
Share on other sites

Yes but why is not this flickering showing up in the second  approach?
It's the exact same lottie file with the same scroll length

(the scond approche is the upper pen of the two. A little confusing but I'm not able to change the order)

Link to comment
Share on other sites

Yee I think we are something on the tracks here

But why is the flickering only aper in long lotties.
Watch the scrollbar, the Lottie film in the examples is a quite long lottie, much longer than the animation part.

If you clone and fix with the pen and change the lottie url to this (a lottie that is just as long as the actual animation)

https://assets2.lottiefiles.com/packages/lf20_ljas34zn.json

 

You will see that the animation is incredible smooth and nice

I myself has hard to see how the length of the lottie interacts with the ScrollTrigger / gsap / scrub code and make this flickering aper.

What is your best guess Cassie?
 

Link to comment
Share on other sites

It could also potentially be the number of frames one animation is saved out as?

You do have a big base 64 png in there too which I imagine could be causing issues, that's a lot to re-render to the DOM 60 times a second.

Have you tried asking in the Lottie forums?

There seem to be threads about flickering in there - https://forum.webflow.com/t/lottie-animation-flickering-strobing-on-scroll/100320/2

  • Like 3
Link to comment
Share on other sites

Ah, I chased this down to a decimal precision thing. Basically, GSAP rounds to the closest 4 decimal places in order to solve various problems like:

  1. Binary math rounding. Example: 4 % 0.8 should be 0.8 but computers return 0.7999999999999998, so rounding fixes that
  2. Too many decimal places can cause the browser to introduce scientific notation and then if that gets put into a string (like for CSS when you've got units), 0.0000001 could become 1e-7 which can cause failures when the browser tries to read that value back in. Like 1e-7px - the browser is like "huh?" 
  3. Memory savings for strings. For example, SVG path data strings have a lot of numbers crammed into them, so reducing the number of decimal places can save quite a bit of characters that get shoved into that string.

However, when you've got a super long timeline and ScrollTrigger scrubs the progress (a value between 0 and 1), those decimal places represent more timeline real estate. In other words, going from 0.0002 to 0.0003 can feel like a bit of a jump. In the next GSAP release, I'll add two extra decimal places on generic value tweens (this doesn't affect CSS, for example). Here's a fork of your CodePen with that beta file in place: 

See the Pen KKWdLRE?editors=0010 by GreenSock (@GreenSock) on CodePen

 

(Nothing changed except the core GSAP file)

 

Better? 

 

The reason Gannon's didn't exhibit that behavior was because it was using a totally different technique that was creating a new tween on every update, and that tween was animating the frame number which doesn't have the tiny decimals that a progress value would. It's far less efficient, but it appeared smoother due to the rounding stuff which is only apparent in long animations where those extremely small decimals represented larger chunks of time.

 

Make sense?  

  • Like 6
  • Thanks 1
Link to comment
Share on other sites

  • 2 years later...

Posting here for visibility. If you're using the <lottie-player> component and loading the Lottie animation in through it's src and having a flickering issue on iOS while tying this to a scrub for GSAP, the problem is that the lottie player only loads in the first png in the sequence until scrubbing begins and then dynamically introduces the frames for every scroll jack.

So in my instance the setup kind of looked like:

<lottie-player
  mode="normal"
  src="/your-lottie.json"
  style="width: 100%"
 >
</lottie-player>

 

let player = document.querySelector('lottie-player')

let animation = player.getLottie()

let playhead = { frame: 0 }
let tl = gsap.timeline({
  defaults: { duration: 1 }
})

tl.to(playhead, {
                frame: (Whatever frame you want the animation to scrub to) || animation.totalFrames,
                duration: (however long you want it to take) || animation.totalFrames,
                ease: 'none',
                onUpdate: () => animation.goToAndStop(playhead.frame, true)
              })
// add in whatever other timeline actions you need to do after this, and continue chaining
ScrollTrigger.create({
      trigger: selector,
      pin: true,
      start: 'top top',
      animation: tl,
      scrub: 1
    })

I was having trouble figuring out how to use the LottieScrollTrigger in a timeline the way I needed to so I had to use the regular scroll trigger. Essentially I wanted to pin the element when I got there, scrub through a bit of the lottie animation at a predetermined point, show something else, scrub to another predetermined point, show another thing, then finish the animation. So here we're using the playhead variable with a frame property and on update from the scrub we're making the animation go to that point from the playhead.

 

This worked well in all browsers other than iOS, it was flickering and that was because all frames were not loaded initially and being loaded at the instant scrolling occurred. Instead you'll want to load the lottie animation in with JS

 

    player = lottie.loadAnimation({
        container: lottieElement, // element you're injecting the lottie into
        renderer: 'svg',
        loop: false,
        autoplay: false,
        path: lottiePath // the path to the animation json
    });

player.addEventListener('data_ready', () => {
  // do all your GSAP stuff after the data is loaded
})

This will load the entire animation and stop the flickering

  • Thanks 2
Link to comment
Share on other sites

Hi @Ninthony,

 

Thanks for sharing your findings with the community, I'm sure many users will benefit from your knowledge and kindness! 🥳

 

Just an FYI we do have a couple of examples that use the Lottie-ScrollTrigger helper function in our Stackblitz examples:

https://greensock.com/docs/v3/HelperFunctions#lottie

 

https://stackblitz.com/edit/vitejs-vite-emmptw

 

https://stackblitz.com/edit/react-pfgj43

 

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

Appreciate it @Rodrigo, I'll have to pick it apart. Thing was I needed the lottie animation to STOP when I got to a certain point to reveal some text. So I kind of needed it to be a part of the same timeline, so the way you feed the animation property the timeline variable in the scroll trigger. I wasn't certain of how to achieve that. I haven't taken a deep look into what you posted, but it looks like the one example just scrolls through the entire animation. I don't think that would have been a problem for me if that was the case. I will bookmark this though cause I'm sure I'll encounter a similar situation. 

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