lucky111 Posted April 13, 2021 Share Posted April 13, 2021 Hi I testing to connect a Lottie animation to scrolltrigger. In the documentation there is a nice example with a pin thats work wery well. https://greensock.com/docs/v3/HelperFunctions#lottie It refere to a guy named Chris Gannon who has develop a tool for this and work as an inspiration for the example i guess. When I study the two examples I can notice quite a different in approach in solving this. Both examples working well for me but I'm curios to know whats the differance and witch approach is the best and most effective.https://github.com/chrisgannon/ScrollLottie The two pens See the Pen QWdjEbx by GreenSock (@GreenSock) on CodePen What approach is the best!! See the Pen 7e302171605cbc4274ce44733189ffe9 by chrisgannon (@chrisgannon) on CodePen Link to comment Share on other sites More sharing options...
Cassie Posted April 13, 2021 Share Posted April 13, 2021 Hi Lucky111, It's basically the same approach really - Both use GSAP ScrollTrigger to scroll through a Lottie animation. The only difference is that Chris Gannon's JS is in an external JavaScript file and the GSAP one isn't. Your choice as to whether you want his script to do the heavy lifting for you or write it yourself. https://github.com/chrisgannon/ScrollLottie https://s3-us-west-2.amazonaws.com/s.cdpn.io/35984/ScrollLottie.js Link to comment Share on other sites More sharing options...
lucky111 Posted April 13, 2021 Author Share Posted April 13, 2021 Thanks Cassi for your fast response When I look in the code the approch is complete different i looks to me in The gsap example gsap.to(playhead, { frame: animation.totalFrames - 1, ease: 'none', onUpdate: () => animation.goToAndStop(playhead.frame, true), scrollTrigger: st }); }); You use scrolltrigger inside a gsap.to animation of the whole Lottie animation But in Chris code ScrollTrigger.create({ trigger: obj.target, scrub: true, pin: true, start: "top top", end: endString, onUpdate: self => { if(obj.duration) { gsap.to(timeObj, { duration: obj.duration, currentFrame:(Math.floor(self.progress * (anim.totalFrames - 1))), onUpdate: () => { anim.goToAndStop(timeObj.currentFrame, true) }, ease: 'expo' }) } else { anim.goToAndStop(self.progress * (anim.totalFrames - 1), true) } } }); He create a scrolltiger and do a lot of small gsap.to animations I'm very keen to understand the diffrent approches for those two way to code this task? Link to comment Share on other sites More sharing options...
Cassie Posted April 13, 2021 Share Posted April 13, 2021 Ok! So they're really just different ways of using ScrollTrigger. You can add a ScrollTrigger to a tween or timeline, or use it standalone and fire callbacks. Simplified version - See the Pen 6502e216925c5366583cb5186673c2d0 by cassie-codes (@cassie-codes) on CodePen It's hard to say which is best. I would probably go with the GSAP helper function as it's evolved from Chris's original library and doesn't require an external resource - but they're both good. Link to comment Share on other sites More sharing options...
lucky111 Posted April 13, 2021 Author Share Posted April 13, 2021 Ok In Chris code you can skip a gsap.to animation if you set the duration to zero. In the GSAP helper you always have on gsap.to and controll the duration with a scrub value may be it all boling down to the same 1 Link to comment Share on other sites More sharing options...
Shrug ¯\_(ツ)_/¯ Posted April 13, 2021 Share Posted April 13, 2021 There are certainly differences between the two approaches. @GreenSock mentioned some in another thread when he created that helper function. On 3/24/2021 at 5:28 PM, GreenSock said: Improved performance in the way it handles scrubbing You can add any ScrollTrigger-related value to the object you pass in (trigger, start, end, onEnter, onLeave, onUpdate, markers, whatever.) so you get tons of flexibility He may eventually stop by this thread and comment also. 😉 3 Link to comment Share on other sites More sharing options...
lucky111 Posted April 13, 2021 Author Share Posted April 13, 2021 Thanks Shrug I hope @GreenSock will explain this in detail to us 1 Link to comment Share on other sites More sharing options...
GreenSock Posted April 22, 2021 Share Posted April 22, 2021 Yikes! I totally missed this thread, @lucky111. Sorry! Yes, I would definitely recommend the helper function in the docs, no question. It will perform significantly better because it doesn't constantly create a new tween over and over again on each tick to accomplish the scrubbing technique. Plus the non-GreenSock one didn't set overwrite: true, so it was creating a lot of conflicting tweens. You'd probably never notice functionally, but it's bad for performance. It gives you a lot more flexibility, as mentioned above - you can add any ScrollTrigger-related value to the object you pass in. You're not limited to "fast", "medium" and "slow" speeds - you can set ANY end value, like end: "+=2000" or whatever. But it still works with speed if you prefer that syntax. So overall it's more concise, it performs much better, and offers way more flexibility. I don't mean that as a knock on Chris's version - he built that when he was very new to ScrollTrigger. We all know what a genius he is with animation in general - I just have an unfair advantage of knowing all the ins and outs of ScrollTrigger (having built it) 2 Link to comment Share on other sites More sharing options...
lucky111 Posted April 29, 2021 Author Share Posted April 29, 2021 Thanks GreenSock I have implemented it in my project and it works very well. My next issue is should I use native scroll or should I use some scroll jacking Link to comment Share on other sites More sharing options...
andwhy Posted July 28, 2023 Share Posted July 28, 2023 Hello! Amazing solutions, thanks for this! I'd love to be able to have a local json as the path instead of a https link, I couldn't find a solution how to make this work yet, do you have any idea? path: '@/assets/animation_lkmhj2hi.json' FYI I am trying to add this in react using 'lottie-web' Link to comment Share on other sites More sharing options...
Rodrigo Posted July 28, 2023 Share Posted July 28, 2023 Hi @andwhy and welcome to the GreenSock forums! Thanks for being a Club GreenSock member and suporting GreenSock! 💚 The issue here could be with the fact that you are using an import path that uses an alias such as @/ for shortening the import path directly on the Lottie config. Maybe you would have to give that particular file a name like this: import lottiePath from "@/assets/animation_lkmhj2hi.json"; Then use lottiePath in your Lottie config as the animation data property, not the path property, like this: import lottieJson from "@/assets/my-lottie-file.json" gsap.registerPlugin(ScrollTrigger); export default function Scroll() { const ScrollRef = useRef(); const LottieRef = useRef(); const lottieTween = useRef(); useLayoutEffect(() => { const ctx = gsap.context(() => { if (!lottieTween.current) { //Animate lottie on scroll lottieTween.current = LottieScrollTrigger({ target: LottieRef.current, animationData: lottieJson, speed: 'medium', start: 'top top', end: 'bottom -100%', pin: ScrollRef.current, scrub: 1, }); } }); // <- Scope! return () => ctx && ctx.revert(); // <- Cleanup! */ }, []); return ( <div ref={ScrollRef} className="scroll"> <div ref={LottieRef} className="lottie"></div> </div> ); } Is important to note the fact that the lottie animation is being stored in a ref and we check if that ref already exists. This because on Strict Mode (since version 18) React runs the effect hooks twice, so you'll get a duplicated lottie ScrollTrigger instance that could cause some issues. Hopefully this helps. Happy Tweening! Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now