Jump to content
Search Community

Rodrigo last won the day on April 22

Rodrigo had the most liked content!

Rodrigo

Administrators
  • Posts

    6,556
  • Joined

  • Last visited

  • Days Won

    284

Everything posted by Rodrigo

  1. Hi @Philibert and welcome to the GreenSock forums! I'm not in front of my computer now but based on the code you posted and the description you give this might be a perfect fit for the horizontal endless loop helper function: https://greensock.com/docs/v3/HelperFunctions#loop You can combine it with ScrollTrigger to achieve nice effects like this https://codepen.io/GreenSock/pen/GRwePYw Or you can use the Observer Plugin to get the same effect: https://codepen.io/GreenSock/pen/zYaxEKV https://greensock.com/docs/v3/Plugins/Observer Hopefully this helps. Happy Tweening!
  2. Hi, It would be good to know what type of framework you are using (React, Vue, Svelte, etc.) in order to get a better grasp of the situation. I assume that in development mode on your local machine everything is working OK. Have you tried creating a production build of your app and test it on your local machine? Also what bundling system are you using, Webpack, Vite, other? Finally, correct me if I'm wrong, but I believe that Github pages don't work in the way providers like Netlify, Vercel, etc. do, meaning that when you create a new push to the repo, the app is not build and created, but that is something you have to do on your own. Honestly I haven't used GH pages a lot so I couldn't really tell, since the few times I've done it I created the gh-pages branch and push the files to make everything work by hand and not using some sort of package or CI/CD pipeline. Happy Tweening!
  3. Hi @MJ. Saei and welcome to the GreenSock forums! Is great to hear that you were able to solve it! ? I'm not an expert on CSS Transitions (as you might've guess we favor GSAP around here ), but it seems that they start running as soon as the element is added to the DOM, so that control you gain with the DOM Content Loaded method gives you to add that particular style. Another options could be to use the load event: https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event Or use David Desandro's Images Loaded library: https://imagesloaded.desandro.com/ Hopefully this helps. Happy Tweening!
  4. Hi, The main issue here is that you are not doing anything that will cause an actual animation. This is more related to fact that you are missing how actually Flip works. Flip takes the current state of the element, then you change something that alters the size and/or position of the element and finally you tell Flip to animate from the state you recorded to the state the element has after those changes. Here is a simple example showing that: https://codepen.io/GreenSock/pen/wvRqQmr Then in terms of your React code is better to get the state of the element inside the GSAP Context instance and not outside. Because of the double call in effect hooks on React Strict Mode (in development) that particular state will be removed. Here is a simple example of using Flip and reparenting on a React app: https://stackblitz.com/edit/vitejs-vite-bpwfpk?file=src%2FApp.jsx Hopefully this helps. Happy Tweening!
  5. Hi @DonDraper and welcome to the GreenSock forums! That most likely has to do with the calculations being made for your smooth scroll functionality and the pin space added by GSAP in order to pin the horizontal section. Maybe try using the refresh event handler to update or re-create your smooth scroll: https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.addEventListener() Also maybe take a look at this codepen by @OSUblake https://codepen.io/osublake/pen/QqPqbN Unfortunately we don't have the time resources to provide this type of help, especially since GSAP already has a smooth scrolling plugin, ScrollMoother: https://greensock.com/scrollsmoother/ @akapowl, one of the forums superstars, has created some great examples for integrating ScrollTrigger with other alternatives like Locomotive: https://codepen.io/akapowl/pen/wvJroYy And this using smooth scrollbar: https://codepen.io/akapowl/pen/poeoONq Finally you could check Lenis: https://lenis.studiofreight.com/ Good luck with your project. Happy Tweening!
  6. Hi, I read this a few times and had a look at the codepen, but I'm still a bit lost about what the issue is here. The few advice I can offer is to never use margin/padding or anything else that changes the vertical position of an element that triggers a ScrollTrigger instance, that could cause some unexpected behaviour. Another thing you could try is to use immediateRender: false in your ScrollTrigger confiuration object: scrollTrigger: { ... immediateRender: false, ... } If you keep having issues, please be super specific about what is not working and how we can see that in your codepen demo. Hopefully this helps. Happy Tweening!
  7. Hi, @mvaneijgen is right check the height of the section and use the logic in this example: https://codepen.io/GreenSock/pen/NWMZrbj Hopefully this helps. Happy Tweening!
  8. Hi @johndunking, Maybe try deleting your package-lock.json file and push those changes to your repo in order to force the creation of a new one and see if that helps. Also as Paul mentions do your best to keep your repo private, otherwise you'll be exposing the files you paid for, to everyone that visits the URL. Please let us know how that works. Happy Tweening!
  9. Hi, You have a couple of errors in your code. The first one is that GSAP MatchMedia is actually an instance of GSAP Context with more capabilities, so reverting the MatchMedia instance is enough, no need to create a GSAP Context instance in your code like this: let mm = gsap.matchMedia(); mm.add('(min-width: 800px)', () => { let ctx = gsap.context(() => { ... }); return () => { ctx.revert(); }; }); But that is just some unnecessary code, that's it. The real problem is this: useLayoutEffect(() => { gsap.registerPlugin(ScrollTrigger); let mm = gsap.matchMedia(); mm.add('(min-width: 800px)', () => { ... }); mm.revert(); }); Basically you are reverting your MatchMedia instance as soon as you create it, so nothing happens regardless of the screen size. The cleanup phase on an effect hook is a function that is returned, like this: useLayoutEffect(() => { gsap.registerPlugin(ScrollTrigger); let mm = gsap.matchMedia(); mm.add('(min-width: 800px)', () => { ... }); return () => mm.revert(); }); In order to correctly grasp this concept read more regarding useEffect and useLayoutEffect hooks: https://react.dev/reference/react/useEffect https://react.dev/reference/react/useLayoutEffect https://react.dev/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed Hopefully this helps. Happy Tweening!
  10. Rodrigo

    3D carousel

    Hi, Is not a thing that we don't provide help or guidance if we don't get paid. Is an issue of best administrating our time resources, nothing more. For example there are many things that we see here in the forums that I would love to dedicate myself into re-creating, but that would involve leaving many questions here in the forums as well as other parts of our jobs unattended, nothing more. I think the issue in your example resides mostly on the styles, that's why I added the link for David DeSandro's resources since, most I've learn about 3D transforms, it was from his resources. Good luck with your project! Happy Tweening!
  11. Hi, I read this a few times and spend some time with your codepen example trying to reproduce these steps without any success: In fact I never even saw the red square move. Is really unclear to me what exactly you are trying to do and I can't seem to grasp this as well: What exactly you mean when you say hide some specific tweens, but show them. A video editor timeline is a big undertaking with several layers of complexity, so trying to fully understand all of it would be near impossible. The best option is to explain what you expect to happen in your demo when clicking each button in order to understand what you're trying to do and give you a nudge in the right direction. Please be as simple as possible in order to correctly grasp your intentions here. Happy Tweening!
  12. Hi, The issue has to be in this calculation: let activeTabPosition = activeTab.getBoundingClientRect().x; let selectorPosition = selector.getBoundingClientRect().x; let slideDistance = (activeTabPosition - selectorPosition) You are getting the current active element and the target. When you go back to an element before that value is negative. Keep in mind that, regardless where an element is first rendered, it's transform X value is zero, so for example if you go to the first element, that value has to be zero if the indicator is in the same position. Normally in this cases is better to add some console logs to your code in order to see what numbers you are getting from the calculations and see if they match with what you are expecting. In the case of my example, the only calculation I make is to get the offset of the button child node, because I'm attaching the indicator to that element, but if you want the indicator to use the entire width, that wouldn't be necessary. Hopefully this clear things up. Happy Tweening!
  13. Hi, That sounds like a tricky scenario, definitely not simple. My first approach would be to use a global mask over the paths in order to create the effect. This requires to duplicate the paths of course, but is the simplest I can think of: https://codepen.io/GreenSock/pen/LYMLQvw Other than that is using individual masks for each path or for certain groups of paths and do something similar. Then is individual masks for each path and use the Motion Path plugin for each mask, but if you are talking of thousands of lines, that approach will make me switch careers and become a farmer or a plumber, because it would meant a lot of work unless you can loop through your paths, create and add the mask to the SVG for each path, create a GSAP instance (or add one to a timeline) and feed that data to the MotionPath Plugin. Like I said not simple. Hopefully this helps. Happy Tweening!
  14. Hi, Just add more scroll space with the end point of your ScrollTriggers and give that animation a longer duration. More scroll space means more pixels have to be scrolled in order to complete the animation. A longer duration means that more of that scroll distance will be used for that particular animation: const tl = gsap.timeline({ scrollTrigger: { trigger: "#sect1", start: "0 0", end: "+=200%", scrub: true, pin: true } }); const rects = document.querySelectorAll("#sect1 .wrapper"); tl.from(["#sect1 h2", "#sect1 .card"], { opacity: 0 }).fromTo( rects, { y: "100vh" }, { y: "-100vh", duration: 1 } ); The default duration of a GSAP instance is 0.5 seconds, so in this case we have an instance that is 0.5 seconds and another that is 1 second (double). The timeline is spread over 200%, that is twice the height of the viewport, so 67% of the scroll distance will scrub the first animation and 133% of the scroll will scrub the second, which makes it last longer. This video made by @Cassie explains that in a visual way: If it works it works, right? Right now you have a clean, simple and easy to follow code that is doing what is supposed to, so in my book at least there is nothing that has to be changed there. Sorry but I don't follow what you mean with this. Please be more specific or create a new minimal demo that illustrates this behaviour only. Hopefully this helps. Happy Tweening!
  15. Hi, I had a quick glance at your code and instead of trying to solve the issue there I created an example using page transitions and the helper function: https://stackblitz.com/edit/nuxt-starter-dhwrqn As you can see it works as expected on route changes, so there must be something else in your setup that is causing this. Hopefully this helps. Happy Tweening!
  16. Rodrigo

    3D carousel

    Hi, Also take a look at this page: https://3dtransforms.desandro.com/ David goes into a lot of details explaining how everything works and even has a dedicated section for a carousel. Hopefully this helps. Happy Tweening!
  17. Hi @CrPalomino and welcome to the GreenSock forums! There are three things that are causing issues in your app in terms of HTML and some GSAP issues. Besides that you might have to tinker with your CSS but your demo has over 700 lines of CSS and we don't have the time resources to comb through all that. First your demo is missing the closing tags for <section> and <div class="wrapper> so that definitely creates an issue. Then you are using very old versions of GSAP and ScrollTrigger and the version of the GSAP Core is different than the version of ScrollTrigger. Always use the latest versions and be sure that they match. Right now we're on version 3.12.2. Also is important to not pin elements inside another element that is pinned. Right now you are pinning the video section but you already have pinned the main wrapper here: ScrollTrigger.create({ animation:tl, trigger:'.wrapper', start:"top top", end:"+=1200", scrub:1, pin:true, ease:"ease", }) That could definitely be a source of issues. Also is a better idea to create your ScrollTrigger instances in a logical order. So I'd create the one that pins the wrapper first and then create the ScrollTrigger instance that animates the video and the other sections. Finally you are creating an animation with a very large scale but there is no overflow hidden anywhere in a parent of that element, therefore that adds A LOT of extra scrolling space. If you comment line 85 in my example and uncomment line 86 you'll see the difference: https://codepen.io/GreenSock/pen/LYMLPrK That at least shows the footer so is a step in the right direction. Hopefully this helps. Happy Tweening!
  18. Hi @Francis Paul Musango and welcome to the GreenSock forums! Is really hard for us to do much without a minimal demo. We also have a collection of starter templates using GSAP and React here: https://stackblitz.com/@GreenSockLearning/collections/gsap-react-starters Also when using GSAP in React environments, GSAP Context is the best friend you can have: https://greensock.com/docs/v3/GSAP/gsap.context() Also check the resources in this page to better learn how to use GSAP in React apps: Finally, despite not providing a minimal demo and due to the fact that your question was clear in terms of what you are trying to do and that achieving that is not extremely complicated I created this simple example: https://codepen.io/GreenSock/pen/eYbWqwE In the future though, do your best to provide a minimal demo that clearly illustrates what you're trying to do and the problems you're facing. Hopefully this helps. Happy Tweening!
  19. Hi, In your script tags you have an extra slash: <script src="/gsap//minified/ScrollSmoother.min.js"></script> <script src="/gsap//minified/MorphSVGPlugin.min.js"></script> <script src="/gsap//minified/SplitText.min.js"></script> But the main reason is this: var israelflagfix = ScrollTrigger.create({ trigger: "#part1", start: "top top", end: "bottom +=50%", endTrigger: "#part1", pin: "#israelflag", // pinspacing: false, markers: false }); console.log(israelflagfix); gsap.fromTo( ".israelflag_paths", { drawSVG: "0%" }, { scrollTrigger: { trigger: "#part1", start: "10% 80%", end: "40% 90%", endTrigger: "#part1", containerAnimation: israelflagfix, // HERE scrub: 1, markers: false }, drawSVG: "100%" } ); A Container Animation must be a GSAP Tween or Timeline instance. Right now you're passing a ScrollTrigger instance in almost every other ScrollTrigger you are creating. As soon as you comment that out the error is gone. In order to learn what Container Animation is and how it works please check this Blog Post: https://greensock.com/3-8#containerAnimation Also from the ScrollTrigger docs: containerAnimation Tween | Timeline - A popular effect is to create horizontally-moving sections that are tied to vertical scrolling but since that horizontal movement isn't a native scroll, a regular ScrollTrigger can't know when, for example, an element comes into view horizontally, so you must tell ScrollTrigger to monitor the container's [horizontal] animation to know when to trigger, like containerAnimation: yourTween. See a demo here and more information here. Caveats: the container's animation must use a linear ease ( ease: "none"). Also, pinning and snapping aren't available on containerAnimation-based ScrollTriggers. You should avoid animating the trigger element horizontally or if you do, just offset the start/end values according to how far you're animating the trigger. Is states there that the type has to be a Tween|Timeline, not a ScrollTrigger instance. Finally the reason you weren't seeing the error in the older version is because Container Animation was not introduced yet, so ScrollTrigger was just ignoring that configuration option. Hopefully this clear things up. Happy Tweening!
  20. Hi @ceneuve and welcome to the GreenSock forums! Indeed is not very clear to me exactly what is the issue here. By looking at your codepen example, the only GSAP code I found: gsap.to(window, { duration: currentDuration, scrollTo: { y: currentPosition }, ease: "slow(0.7, 0.7, false)", onComplete: () => { isAnimating = false; // Establecer que la animación ha terminado } }); Is doing exactly what is supposed to do so maybe I'm missing something here ?‍♂️ Also I noticed you are using JS to apply different styles in different screen sizes. Why not just use CSS Media Queries? https://developer.mozilla.org/en-US/docs/Web/CSS/@media Based on the example you have you can look at using ScrollTrigger and Observer in combination with the ScrollTo Plugin as well: https://greensock.com/docs/v3/Plugins/Observer https://greensock.com/docs/v3/Plugins/ScrollTrigger Is worth mentioning that the Observer Plugin is baked into ScrollTrigger, so you don't need to add that file or link as well, ScrollTrigger should be enough: https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.observe() If you keep having issues please be very specific regarding what you want to achieve, what is not working and make sure that your minimal demo (please keep it as minimal as possible) reflects that. Also if it helps clarifying the situation, include a link that shows the functionality you're trying to achieve. Hopefully this helps. Happy Tweening!
  21. Hi, If you want to start every line 0.3 seconds apart of each other, first create a SplitText for the paragraph using just lines and a main timeline. Then loop through those lines and create a new SplitText instance in order to split every line into characters. Then add an instance to the timeline for each line and use the position parameter to start each instance 0.3 seconds after the previous one. const split = new SplitText("p", { type: "lines" }); const tl = gsap.timeline({ paused: true }); split.lines.forEach((line, i) => { const lineSplit = new SplitText(line, { type: "chars" }); tl.from( lineSplit.chars, { y: 25, opacity: 0, stagger: 0.025 }, i * 0.3 ); }); tl.play(); Here is a simple example: https://codepen.io/GreenSock/pen/YzdVdKe Hopefully this helps. Happy Tweening!
  22. Hi, I'm far from being a CSS wizard, so this is the best solution I can come up with: https://codepen.io/GreenSock/pen/PoXmxzJ Is not elegant but it works ?‍♂️ Hopefully this helps. Happy Tweening!
  23. Hi @herougan and welcome to the GreenSock forums! It seems that you are another victim of React's doble effect call on Strict Mode: React 18 runs in "strict" mode locally by default which causes your useEffect() to get called TWICE! Very annoying. It has caused a lot of headaches for a lot of people outside the GSAP community too. .from() tweens use the CURRENT value as the destination and it renders immediately the value you set in the tween, so when it's called the first time it'd work great but if you call it twice, it ends up animating from the from value (no animation). It's not a GSAP bug - it's a logic thing. For example, let's say el.x is 0 and you do this: useEffect(() => { // what happens if this gets called twice? gsap.from(el, {x: 100}) }, []); The first time makes el.x jump immediately to 100 and start animating backwards toward the current value which is 0 (so 100 --> 0). But the second time, it would jump to 100 (same) and animate back to the current value which is now 100 (100 --> 100)! See the issue? In GSAP 3.11, we introduced a new gsap.context() feature that solves all of this for you. All you need to do is wrap your code in a context call, and then return a cleanup function that reverts things: // typically it's best to useLayoutEffect() instead of useEffect() to have React render the initial state properly from the very start. useLayoutEffect(() => { let ctx = gsap.context(() => { // all your GSAP animation code here }); return () => ctx.revert(); // <- cleanup! }, []); One of the React team members chimed in here if you'd like more background. This seems to work in the way you intend: useEffect(() => { const ctx = gsap.context(() => { gsap .timeline({ scrollTrigger: { trigger: '.blinder__image--dark', start: 'top 0%', end: () => `+=${blinder_height}vh`, scrub: true, pin: '.blinder__cover--left', pinSpacing: false, }, }) .fromTo( '.blinder__cover--left', { opacity: 0.5 }, { opacity: 0.1, xPercent: 50, } ); gsap .timeline({ scrollTrigger: { trigger: '.blinder__image--dark', start: 'top 0%', end: () => `+=${blinder_height}vh`, scrub: true, pin: '.blinder__cover--right', pinSpacing: false, }, }) .fromTo( '.blinder__cover--right', { opacity: 0.5 }, { opacity: 0.1, xPercent: -50, } ); gsap.timeline({ scrollTrigger: { trigger: '.blinder__image--dark', start: 'top 0%', end: () => `+=${blinder_height}vh`, scrub: true, pin: true, markers: true, }, }); }); return () => ctx.revert(); }, []); I recommend you to check the resources in this page: We also have a collection of starter templates using GSAP and React: https://stackblitz.com/@GreenSockLearning/collections/gsap-react-starters Hopefully this helps. Happy Tweening!
  24. Hi, I had a better look at this and it seems to me that the issue could be related to some odd way Nuxt is handling routing. I tried the watcher approach but watchers don't fire after the unmount hook has been triggered, so the only way I found to make it work is to add a delay to the revert method in the unmount hook that is equal to the overlay in animation: let ctx; // later this is the GSAP Context instance of this page onUnmount(() => { // The duration of the delayed call is equal to // the duration of the overlay in animation gsap.delayedCall(0.6, () => { ctx && ctx.revert(); }); }); This prevents the issue from happening. Is ugly and a hack more than a robust solution and I definitely don't like it but so far is the only thing that seems to be working. Of course in your layout you can export the duration of the overlay animation in order to not hard code it on every page or even further you can export a helper method that reverts the context you pass as an argument and import the duration in that particular file, then on every page import that helper method to run it on the unmount hook. I'll update the example and let you know about it. Finally in order to confirm this, I'll create an example using Vue and Vue Router in order to see if the result is the same or not. That should confirm if this is a Vue issue or Nuxt issue. Please stand by and thanks for your patience. Happy Tweening!
×
×
  • Create New...