Jump to content
Search Community

Rodrigo last won the day on April 13

Rodrigo had the most liked content!

Rodrigo

Administrators
  • Posts

    6,480
  • Joined

  • Last visited

  • Days Won

    281

Everything posted by Rodrigo

  1. 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!
  2. 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!
  3. 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!
  4. @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!
  5. 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!
  6. 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.
  7. 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!
  8. 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!
  9. 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!
  10. 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!
  11. 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!
  12. 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!
  13. 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!
  14. 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!
  15. 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!
  16. Sure thing! We'll keep you folks posted in this thread! Happy Tweening!
  17. 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!
  18. 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!
  19. Hi @manvanoss and welcome to the GSAP Forums! There is not a lot we can do without a minimal demo. That being said, setting up something in Vue is quite simple. We have a set of Vue starter templates in stackblitz: https://stackblitz.com/@gsap-dev/collections/gsap-vue3-starters Here is a super simple demo using Vue: https://stackblitz.com/edit/vitejs-vite-onqhee?file=src%2FApp.vue&terminal=dev Hopefully this helps. Happy Tweening!
  20. Hi, Maybe these demos can provide a good starting point: https://codepen.io/GreenSock/pen/oNJMgYp https://codepen.io/GreenSock/pen/ZEmrXWv Hopefully this helps. Happy Tweening!
  21. I fiddled with your demo in full view and can't seem to replicate the problem when resizing, maybe you can provide some particular steps in order to reproduce the issue. You can't snap the actual animations in the container one, but you can definitely snap the horizontal motion, keep in mind that these are two different ScrollTrigger instances. Happy Tweening!
  22. Yeah, be careful about this: gsap.killTweensOf('.caption'); If you run that before the Flip instance is completed it will have no effect because that particular tween hasn't been created yet. That tween is created in the onComplete callback of the Flip instance, so GSAP won't find any tween related to that selector, that's why either killing the Flip instance or using a boolean in the onComplete is the best alternative. You can use a ref to store the Flip instance in order to simplify that. Hopefully this helps. Happy Tweening!
  23. Hi, Sorry about the issues but yeah, without a demo that clearly illustrates the problem there is not a lot we can do 🤷‍♂️ The only thing I can think of is that somehow the markers are pushing the height of the document element so everything works as expected. You should review your setup in order to see if something in your HTML/CSS could be causing something that the markers are actually fixing, which would be quite weird TBH. Another option is that something else (like another JS package or CSS library) is interfering with this and causing the problem. Try removing some of them one by one and see if that fixes anything. As I was about to submit this I checked your site again and opened devtools and I noticed that you're using wordpress and that your body element has scroll-behavior: smooth, that could be a source of problems (linke 92): https://staging-chfp.shereewalker.com/wp-content/themes/CHFP/style.css?ver=1.0 Try overriding that in a custom CSS that is loaded after the theme's styles in order to see if it helps. Hopefully this helps. Happy Tweening!
  24. Hi, I've been fiddling a bit with your demo and besides the captions issue I can't reproduce other problems in your demo. I think the issue stems from the delay you have in your instance for showing the captions: gsap.to(imageElementsArray('.caption'), { delay: 2, // <- HERE duration: 0.5, opacity: 1, stagger: 0.15, ease: 'circ.inOut', onComplete: () => { // The srcSet on each image is controlled by tracking isGridView state setIsGridView(true) } }) I think a safer approach is to use the onComplete callback from the Flip instance. As soon as I remove that delay, the captions are no longer visible. Is worth mentioning that using the onComplete callback from the Flip instance also can cause this behaviour since when you toggle before the Flip instance is completed the onComplete callback will still be triggered. You could kill that Flip instance to prevent that callback from being called or use a simple boolean to prevent the captions tween from being created at all: const performLayoutFlip = contextSafe((container, scrollToId, captions) => { const selector = gsap.utils.selector(container); const state = Flip.getState( selector('.grid-container img, .flex-container img') ); container.classList.toggle('grid-container'); container.classList.toggle('flex-container'); Flip.from(state, { duration: 2, ease: 'power4.out', scale: false, fade: true, onComplete: () => { if (captions && showCaptions.current) { gsap.to('.caption', { duration: 0.5, opacity: 1, stagger: 0.15, ease: 'circ.inOut', onComplete: () => { setIsGridView(true); }, }); } if (document && scrollToId) { document .getElementById(scrollToId) .scrollIntoView({ behavior: 'smooth', block: 'center' }); } }, }); }); const clickHandler = contextSafe((event) => { const container = imagesRef?.current; const imageElementsArray = gsap.utils.selector(container); const switchingToGridView = container.classList.contains('flex-container'); if (event.target.tagName === 'IMG') { if (switchingToGridView) { performLayoutFlip(container, null, true); showCaptions.current = true; } else { showCaptions.current = false; gsap.killTweensOf('.caption'); // Fade out all captions before Flip gsap.to('.caption', { duration: 0.5, opacity: 0, ease: 'circ.inOut', onComplete: () => { performLayoutFlip(container, event.target.id); setIsGridView(false); }, }); } } }); Also all of this is not needed at all: const container = imagesRef?.current; const imageElementsArray = gsap.utils.selector(container); // Then gsap.to(imageElementsArray('.caption'), {/**/}); You already set your scope in the useGSAP hook to imagesRef so running this anywhere inside the useGSAP scope or any contextSafe call: gsap.utils.toArray(".caption"); Will return an array of the elements with the caption class that are in the scope of imagesRef.current, so that is quite redundant and wasteful. In fact since that is called inside the contextSafe scope you can just do this: gsap.to('.caption'), {/**/}); Since that particular GSAP instance will use the scope defined in the useGSAP hook to do the same. Here is a fork of your demo: https://stackblitz.com/edit/vercel-next-js-1kpj9n?file=pages%2Findex.jsx Hopefully this helps. Happy Tweening!
  25. Hey Nuno! Thanks for reporting back and sharing your work, looks really amazing! 🥳 I really liked the effect in the second image, great job!! 👏👏 Happy Tweening!
×
×
  • Create New...