Jump to content
Search Community

Rodrigo last won the day on April 17

Rodrigo had the most liked content!

Rodrigo

Administrators
  • Posts

    6,512
  • Joined

  • Last visited

  • Days Won

    282

Everything posted by Rodrigo

  1. Hi, I tested on an iPad running iOS 17.2 can't see the problem in neither Chrome nor Safari. You can try using will-change: transform; in the elements CSS and see if that helps. Also you can try using ScrollTrigger's normalizeScroll in order to have everything on the same thread: https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.normalizeScroll() Hopefully this helps. Happy Tweening!
  2. Hi, I don't have a Mac machine so I can't test in Safari, sorry about that. In an old laptop using Ubuntu 20 your codepen works good in both the latest Chrome and Firefox. Two things I noticed, you can use our Horizontal Seamless loop helper function for the marquee: https://gsap.com/docs/v3/HelperFunctions/helpers/seamlessLoop Here is a demo that uses ScrollTrigger to control the direction and speed of the marquee elements: https://codepen.io/GreenSock/pen/GRwePYw You can set will-change: transform; in your styles for the elements in the marquee in order to improve performance by the way. Also we have a Lottie & Scrolltrigger helper function as well that you can use to create a ScrollTrigger instance that controls that specific Lottie animation: https://gsap.com/docs/v3/HelperFunctions/helpers/LottieScrollTrigger You can also set a specific frame of the Lottie animation as the start offset (if you want to use a different frame than the first one which is the default), as Jack explains in this thread: Hopefully this helps. Happy Tweening!
  3. Hi, Yeah, this is a problem based on the order the ScrollTrigger instances are created doesn't match the order they appear. Ideally ScrollTriggers should be created in the order they appear, if that is not possible you can use the refreshPriority config option: refreshPriority number - it's VERY unlikely that you'd need to define a refreshPriority as long as you create your ScrollTriggers in the order they'd happen on the page (top-to-bottom or left-to-right)...which we strongly recommend doing. Otherwise, use refreshPriority to influence the order in which ScrollTriggers get refreshed to ensure that the pinning distance gets added to the start/end values of subsequent ScrollTriggers further down the page (that's why order matters). See the sort() method for details. A ScrollTrigger with refreshPriority: 1 will get refreshed earlier than one with refreshPriority: 0 (the default). You're welcome to use negative numbers too, and you can assign the same number to multiple ScrollTriggers. You can combine that with the sort method: https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.sort()/ So when the user either adds a new section or re-arranges the current sections use the refreshPriority option and then sort and refresh ScrollTrigger, something like this: const addSection = () => { // After adding a new section ScrollTrigger.refresh(); ScrollTrigger.sort(); }; const moveSection = () => { // After re-arranging the sections ScrollTrigger.refresh(); ScrollTrigger.sort(); }; You should find a way to either add a data attribute for the sections in order to set a refreshPriority value when a section is added or when they are re-arranged and use that to sort them accordingly. Hopefully this helps. Happy Tweening!
  4. Hi, Indeed this is mostly about creating a custom easing that works with your particular path, unfortunately this is mostly a trial and error approach. Good news is that we have the ease visualizer that can help you with this. Basically what you need is a linear (no easing) or slower ease for the vertical sections, so the drawing is slower in those sections, and faster/steeper easing for the horizontal sections. The reason is that you need the horizontal part to be as fast as possible because the element is still scrolling up/down while the path is being drawn in a horizontal way. I created a simple custom ease (doesn't resolve your issue though) so you can see in the ease visualizer what I mean: "M0,0 C0.025,0.021 0.401,0.312 0.401,0.312 0.401,0.312 0.5,0.5 0.5,0.5 0.5,0.5 0.7,0.7 0.7,0.7 0.7,0.7 0.77,0.876 0.77,0.876 0.77,0.876 0.983,0.989 1,1 " You can copy that string and paste it on our ease visualizer in order to see how that works, the faster parts are intended for horizontal sections and the slower ones for vertical sections: https://gsap.com/resources/getting-started/Easing Hopefully this helps. Happy Tweening!
  5. Hi, Is super difficult to troubleshoot issues without a minimal demo, but maybe you're looking for ScrollTrigger's Batch method: https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.batch() https://codepen.io/GreenSock/pen/NWGPxGZ Hopefully this helps. Happy Tweening!
  6. Hi, The stagger config option is not a valid one for the ScrollTrigger config object. What I don't really understand of your setup, is why you want to stagger something if you are already using a loop for creating the ScrollTrigger instances. Maybe you're looking for ScrollTrigger's batch method: https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.batch() Check the demos in that link see if that helps. If you keep having questions please include a minimal demo that illustrates what you're trying to do and where you're encountering problems. Happy Tweening!
  7. Hi, This seems more related to the calculations in your getWidth method rather than anything else. I forked your demo and removed all the ScrollTrigger code and got this: https://codesandbox.io/p/sandbox/gsap-scrolltrigger-forked-29wfjr?file=%2Fsrc%2Fcomponents%2FExperiencePage%2FExperiencePage.tsx%3A122%2C57 If you resize the window you'll see that the animation looks odd, again most likely because of the calculations in the getWidth method. I'd recommend you a different approach for this, perhaps make each slide the width of the screen or the section container and scale up/down the child elements of that slide. I did check if using revert instead of kill works and it seems it does: https://codesandbox.io/p/sandbox/gsap-scrolltrigger-forked-r5q7k8?file=%2Fsrc%2Fcomponents%2FExperiencePage%2FExperiencePage.tsx The issue I see with this approach is that you'd need to kill the ScrollTrigger instance as well and create everything again. Probably would be a good idea to debounce the resize event handler to avoid executing that code on every resize. Still I'm in favor of the first approach, try to simplify this as much as possible, create the animation without ScrollTrigger and without that getWidth method and make sure that is responsive, then add ScrollTrigger to the mix. Hopefully this helps. Happy Tweening!
  8. Hi @ladyofcode and welcome to the GSAP Forums! I forked your demo and updated the gsap trial version (running npm i -s gsap-trial in a new terminal on stackblitz) and I don't see anything that jitters: https://stackblitz.com/edit/sveltejs-kit-template-default-vjaxrz?file=src%2Flib%2FHorizontalScroller.svelte,src%2Fapp.css Also the reason for not seeing all the elements is because you copied all the styles from our ScrollSmoother demo that uses elements with position absolute, so those are taken from the documents flow and there is no scroll available because of that, once you remove that you can scroll all the way down (as you can see in the forked demo, see the app.css file). Also I changed scrub: 1 to scrub: true, since there is no need for that when using ScrollSmoother. If you can tell us exactly what is jittery and how to reproduce the issue it'd be great. Finally thanks for being a GSAP Club member and supporting GSAP! Hopefully this helps. Happy Tweening!
  9. Hey Keegan! You can share the debug URL: https://cdpn.io/pen/debug/WNWMoPe Is using ScrollTrigger normalizeScroll an option here? https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.normalizeScroll() if (ScrollTrigger.isTouch === 1) { ScrollTrigger.normalizeScroll(true); } Other than that honestly IDK, using SVH doesn't change a thing I'm afraid, maybe some of the CSS wizards around here can come up with something that clearly eludes me right now. Hopefully this helps. Happy Tweening!
  10. Hi, This happens because you have this on your CSS: .grid-tile { box-sizing: border-box; border-radius: 1em; height: 100%; display: flex; align-items: center; justify-content: center; padding: 0.5em; overflow: hidden; transition: 0.6s ease-out all; /* <- HERE */ background-color: darkseagreen; } That transition all kicks in after Flips handles all it's magic. If you comment that out everything seems to work as expected: https://codepen.io/GreenSock/pen/VwNQPjV Word of advice: NEVER use transition all in your css, that could lead to unexpected problems like this 😉 Hopefully this helps Happy Tweening!
  11. @iDVB, yeah this is mostly about positioning your instances in your timeline, but the pain point is when, meaning at what point during the lifecycle of the app/component that has to be done. The methods or approaches we suggest are based on the first thing you want to avoid, manually passing a magic number. In that case you could look into creating some state management (most likely using React context) solution that tells you when every child is created and then populate the master timeline. While this might sound simple it surely shouldn't be the simplest thing to implement, probably not extremely complex, but definitely not easy. You could look into the shiftChildren method: https://gsap.com/docs/v3/GSAP/Timeline/shiftChildren() Maybe create the master timeline and add the labels then when some child elements are created get the time of that label and shift all the children from the time of that label by the duration of that particular Tween/Timeline you're creating in the component. --- @cbravo If I need all the animations in the same parent component (something I avoid as much as possible because in a complex scenario like this, things get complicated), create all the animations using either forward refs (last resource) or using regular text selectors, which works since the child components are rendered before the parent ones, so the elements will be at the DOM at that time. Use a callback with React context to add to a master timeline indicating the position where it should be by hand in every component. In this case never animate a DOM element that is in the parent component, use this component only as a container and something that handles all that logic, nothing more, then place your components in your JSX in the order they should be added to the master timeline so you know that the order will be the one you expect. So in this later case there is no need to indicate a position for each timeline, maybe use the position parameter if you need to create a pause for some time between animations, so in the example @iDVB created do something like this: return ( <div> <Box id="box1" className="red" /> <Box id="box2" className="blue" /> <Box id="box3" className="green" /> </div> ); Finally I took some time to create a minimal demo with shifChildren and that could be what you're looking for, especially for the demo you posted originally: https://stackblitz.com/edit/vitejs-vite-aaoopl?file=src%2FApp.jsx&terminal=dev Hopefully this helps. Happy Tweening!
  12. Hi, When using useGSAP there is no need for manual cleanup, the hook does that for you, so you don't need to kill your timeline in the return statement. Setting the body element's style is OK though: https://gsap.com/resources/React Here is a simple demo showing how to implement GSAP MatchMedia in the useGSAP hook, as always just put your GSAP instances (including the MatchMedia one) inside the scope of the hook and everything should work: https://stackblitz.com/edit/vitejs-vite-pfhzkf?file=src%2FApp.jsx Hopefully this helps. Happy Tweening!
  13. Rodrigo

    Greensock for AS2

    Hi, I haven't written a single line of AS in over 10 years so I haven't looked in these files in quite some time, but I can see them in my downloaded ZIP file so yeah, most likely those are bonus plugins in the AS bundle.
  14. Rodrigo

    Greensock for AS2

    Hi @AlexC88 and welcome to the GSAP Forums! In your account go to the dashboard (hover the My Account button at the top right of the screen ↗️), there you'll see the available downloads for you and you'll also see an Archived link: Click on that and you'll see all the archived downloads available for your account: You probably wont see the Simply/Shockingly/Business alternatives, so just click on the AS2 one and that should download the ZIP file for flash/AS2 Hopefully this helps. Happy Tweening!
  15. Hi @rlaydtjs and welcome to the GSAP Forums! Unfortunately your demo is not working, you can fork one of our React starter templates from Stackblitz: https://stackblitz.com/@gsap-dev/collections/gsap-react-starters Finally since GSAP 3.12, we have the useGSAP() hook (the NPM package is here) that simplifies creating and cleaning up animations in React (including Next, Remix, etc). It's a drop-in replacement for useEffect()/useLayoutEffect(). All the GSAP-related objects (animations, ScrollTriggers, etc.) created while the function executes get collected and then reverted when the hook gets torn down. Here is how it works: const container = useRef(); // the root level element of your component (for scoping selector text which is optional) useGSAP(() => { // gsap code here... }, { dependencies: [endX], scope: container }); // config object offers maximum flexibility Or if you prefer, you can use the same method signature as useEffect(): useGSAP(() => { // gsap code here... }, [endX]); // simple dependency Array setup like useEffect() This pattern follows React's best practices. We strongly recommend reading the React guide we've put together at https://gsap.com/resources/React/ Happy Tweening!
  16. Hi, I'm not sure I follow 100% what you're trying to do but maybe something like this: https://codepen.io/GreenSock/pen/YzMYJMJ That's the approach I would follow in order to show/hide an element that has the height of the viewport, based on it's position in the viewport. Keep in mind that end: "bottom 95%" means that the ScrollTrigger end point will be at almost the bottom of the viewport (95%, with the top being 0%) and the bottom of the element will hit that almost immediately after the top passes the top of the viewport. Here is what the ScrollTrigger docs have about start, end and toggleActions: start String - Describes a place on the trigger and a place on the scroller that must meet in order to start the ScrollTrigger. So, for example, "top center" means "when the top of the trigger hits the center of the scroller" (and the scroller is the viewport by default). "bottom 80%" means "when the bottom of the trigger hits 80% down from the top of the viewport" (assuming vertical scroll). You can use keywords like "top", "bottom", "center" (or "left" and "right" if horizontal: true) or percentages like "80%" or pixel values like "100px". Percentages and pixels are always relative to the top/left of the element/scroller. You can even use a complex relative value like "top bottom-=100px" which means "when the top of the trigger hits 100px above the bottom of the viewport/scroller" end String - Describes a place on the endTrigger (or trigger if one isn't defined) and a place on the scroller that must meet in order to end the ScrollTrigger. So, for example, "bottom center" means "when the bottom of the endTrigger hits the center of the scroller". "center 100px" means "when the center of the endTrigger hits 100px down from the top of the scroller" (assuming vertical scroll). You can use keywords like "top", "bottom", "center" (or "left" and "right" if horizontal: true) or percentages like "80%" or pixel values like "100px". Percentages and pixels are always relative to the top/left of the element/viewport. You can also define a single relative value like "+=300" which means "300px beyond where the start is", or "+=100%" means "the height of the scroller beyond where the start is". "max" is a special keyword indicating the maximum scroll position. toggleActions String - Determines how the linked animation is controlled at the 4 distinct toggle places - onEnter, onLeave, onEnterBack, and onLeaveBack, in that order. The default is play none none none. So toggleActions: "play pause resume reset" will play the animation when entering, pause it when leaving, resume it when entering again backwards, and reset (rewind back to the beginning) when scrolling all the way back past the beginning. You can use any of the following keywords for each action: "play", "pause", "resume", "reset", "restart", "complete", "reverse", and "none". Hopefully this helps. Happy Tweening!
  17. Hi, This seems related to the fact that you're using height: 100% in all your elements. Better use 100vh, that seems to work the way you intend: https://codepen.io/GreenSock/pen/NWmXOLK Finally it seems that you posted here as well: If you create a new thread there is no need to post in other threads, is better to keep everything focused on just one thread, so if it's OK I'll go ahead and delete that post so we can track this one instead. Hopefully this helps. Happy Tweening!
  18. Hi @kanishk soni, Unfortunately there is no codepen link in your post and I don't see anything odd in the code you pasted. The only suggestion would be use vh instead of height: 100% and adding a height to the html and body elements. If you keep having issues, remember to include a minimal demo. Happy Tweening!
  19. Hi, This is a bit complicated basically from a state management point, actually this is mostly a state management issue. This is your code: // Parent component useGSAP( () => { const timeline = gsap.timeline(); timeline.to("#box1", { x: 100, duration: 2 }); timeline.add("myLabel"); timeline.to("#box2", { x: 100, rotate: 360, duration: 2 }); setMainTl(timeline); }, { scope: ref } ); // Child component useGSAP(() => { if (!mainTl) return; const nestedTl = gsap.timeline(); nestedTl.to("#box3", { x: 100, duration: 1 }); mainTl.add(nestedTl, "myLabel"); }, [mainTl]); So in react child components are rendered first, right? But the issue here is that when the child component first renders the main timeline doesn't exists yet. Then the parent component runs and the timeline is created. At that point the nested timeline is not added yet, in fact it doesn't exists yet so the label is created and then immediately on top of that label the next tween is added . After that the state of the parent timeline is updated using setMainTl. Only after that the child component is re-render and this time the nested timeline is created and added at that label. See the problem? This is not a GSAP issue but a react communication one. You should find the way to tell your parent component the duration of the child instances so you can add that duration to tween after the label using the position parameter. Another option is to use react context or a custom hook. Another option is to handle the master timeline in a different way and add the instances and labels after the maser timeline is created on every component. Honestly I never had to deal with something like this even after using GSAP in quite a few production react apps and components, what I can tell you is that I never used an approach like this. Sorry I can't be of more assistance. Happy Tweening!
  20. Hi @PixelPerfect and welcome to the GSAP Forums! Just use Flip's fit() method and a couple of loops: https://codepen.io/GreenSock/pen/xxepaeV https://gsap.com/docs/v3/Plugins/Flip/static.fit() Finally thanks for being a Club GSAP member and supporting GSAP! 💚 Hopefully this helps. Happy Tweening!
  21. Hi, Indeed that is not a simple thing to achieve but you should definitely create and execute any type of scroll (either direct or animated) after the Flip instance is completed. It doesn't make any sense to run that when the Flip animation has started or is still running IMHO as you have it now. On a quick glance in your demo I can't see anything with an actual ID attribute in your Figure component: <div ref={element} className="relative w-full h-full max-w-4xl" data-image-id={key} > <Image src={url} alt={alt} sizes={imageSizes} style={{ objectFit: 'contain', objectPosition: 'center', width: '100%', height: 'auto', }} onClick={clickHandler} onLoad={() => setIsLoaded(true)} className={cn( isLandscape ? '' : 'max-h-[90vh] object-cover', 'h-auto w-full cursor-pointer', )} /> <h3 style={{ opacity: 0 }} className="caption pt-2 text-xs sm:text-sm">Image caption</h3> </div> So I wouldn't expect this to actually work: gsap.to(window, { duration: 2, scrollTo: { y: document.getElementById(scrollToId), offsetY: 100 } }); So you're passing an id (scrollToId) but where can that ID be found? You could also explore the getBoundingClientRect method: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect This is beyond what we can do in these free forums since we need to focus our time in GSAP related issues and this is not a GSAP issue but mostly a logic and React setup one. Hopefully this helps. Happy Tweening!
  22. Hi, There are a few issues in your demo. First avoid animating the top position, that will trigger a layout and paint operations in the browser: https://web.dev/articles/animations-guide#triggers https://web.dev/articles/animations-overview#pipeline Is better to animate transforms instead of top as shown in these demos: https://codepen.io/GreenSock/pen/KKeJaqW https://codepen.io/GreenSock/pen/vYjqXLm Finally your sections don't match because by default a GSAP Tween has an ease of power1.easeOut: https://gsap.com/resources/getting-started/Easing That means that the animation will start faster and end a bit slower, in this cases is better to use ease: "none" so the progress is completely linear throughout the entire animation: gsap .timeline({ scrollTrigger: { trigger: refVerticalContainer.current, start: "top top", end: "bottom-=" + window.innerHeight, markers: true, scrub: true, }, }) .to(refRight.current, { top: "0vh", ease: "none", // <- LINEAR EASING }); Of course that is just how your code should look, I still recommend using transforms instead of top. Hopefully this helps. Happy Tweening!
  23. Sure thing! We'll keep you folks posted in this thread! Happy Tweening!
  24. Hi, Most likely this is related to the fact that you're animating the width property. Always avoid animating width/height/top/left properties because they require a paint and layout updates: https://web.dev/articles/animations-guide#triggers https://web.dev/articles/animations-overview#pipeline You can try the demos in this thread, the one from the GSAP collection and the one by @PointC: Hopefully this helps. Happy Tweening!
  25. Hi, There shouldn't be any issues in using GSAP Tweens/Timelines, ScrollTrigger and ScrollSmoother in any type of app (Svelte/SvelteKit, Vue/Nuxt, React/Next). We have a collection of SvelteKit starter templates on Stackblitz that you can check: https://stackblitz.com/@gsap-dev/collections/gsap-sveltekit-starters As you mention without a demo is hard for us to tell, maybe you have too many elements/components with an absolute or fixed position which are taken out of the document flow and kind of forces you to add some height to the body element, but that shouldn't be needed in normal circumstances. Again you can check our starter templates in Stackblitz and use the one for ScrollSmoother as a reference: https://stackblitz.com/edit/sveltejs-kit-template-default-dvnud9?file=src%2Froutes%2F%2Bpage.svelte Hopefully this helps. Happy Tweening!
×
×
  • Create New...