Jump to content

Rodrigo last won the day on May 30

Rodrigo had the most liked content!


  • Posts

  • Joined

  • Last visited

  • Days Won


Rodrigo last won the day on May 30

Rodrigo had the most liked content!

About Rodrigo

Profile Information

  • Gender
  • Location
    Santiago - Chile

Recent Profile Visitors

37,075 profile views
  1. Hi, What Cassie means by z-index is to have the element on top of everything at all times, something like z-index: 1000; that normally is enough if you have other elements in your page with z-index of their own. Also there is a problem with using pageX and pageY. Those values are relative to the top of the document. If you have a browser window that reports a height of 900px and you scroll 200px down, if you put your mouse pointer at the top of the browser window the value of pageY is going to be 200 and not 0. So as you scroll down the vertical position of the mouse gets further down the screen until after scrolling 900px you'll never see it again unless you scroll up. document.addEventListener("mousemove", (e) => { cursor.style.left = e.clientX + "px"; cursor.style.top = e.clientY + "px"; }); That works the way you intend. Finally I'd recommend you to use GSAP QuickTo for this as seen in this example: https://codepen.io/GreenSock/pen/xxpbORN Hopefully this helps. Happy Tweening!
  2. Hi @Tung Shark and welcome to the GreenSock forums! First thanks for being a Club GreenSock member and supporting GreenSock! 💚 There are a mix of issues in your setup, some are GSAP related and other are just HTML/CSS related. For example the cards container has a width of 100% but no height and since all it's children have an absolute position, the natural height of the parent is zero, so giving it a height of 100vh seems to work. Then you had this on your ScrollTrigger config: end: wheight * 5 + ' bottom', duration: 1, ScrollTrigger doesn't recognize duration as a config option so that's just ignored. Also if you want a ScrollTrigger to extend 5 times the height of the viewport just pass a relative percentage value like this: end: "+=500%" and ScrollTrigger will do the rest for you. Finally you don't need to pass this to a GSAP animation: stagger: 0.2, start: () => "top top", end: () => 'bottom bottom', Start and end are just for the ScrollTrigger config and are ignored in a GSAP animation. I forked your codepen and made a few changes to it and seems to work the way you intend: https://codepen.io/GreenSock/pen/LYgwPwZ Hopefully this helps. Happy Tweening!
  3. Hi, I updated the codepen to make the image animation visible as you scroll using the callback events: https://codepen.io/GreenSock/pen/OJBeeYG As for scrubbing the image Flip animation you can check this example: https://codepen.io/GreenSock/pen/bGxOjeP Making it work like that would require a second ScrollTrigger instance for moving the image to the final position, maybe using a wrapper around the image. Unfortunately we don't have the time resources to provide custom solutions for our users. I suggest you to study that codepen and see how it works. In this thread you can find some explaining about how that particular approach works: I'm not seeing any performance issue on Chrome and Firefox in Ubuntu 20 && 22. As for doing that without Flip, sure it can be done but it would require for you to create all the custom logic for that, something that Flip already does and it's highly optimized as it is. Hopefully this helps. Happy Tweening!
  4. Hi, You could check this example for some inspiration as well: https://codepen.io/GreenSock/pen/NWMZrbj Hopefully this helps. Happy Tweening!
  5. Hi, I just checked your codepen and after a resize everything works as expected. I keep seeing all the callbacks there, maybe I'm missing something 🤷‍♂️ There could be something else in your setup that's causing this, unfortunately a video doesn't tell us the whole story and as stated before your codepen is working as expected. One alternative could be to test next release's beta files: https://assets.codepen.io/16327/gsap-latest-beta.min.js https://assets.codepen.io/16327/ScrollTrigger.min.js Give those a try and let us know. Hopefully this helps. Happy Tweening!
  6. Hi, There are a few issues in your example: In React child components are rendered before their parents, so your endpage component gets rendered before that. In your endpage component you have this: const tl = gsap.timeline({ scrollTrigger: { trigger: '#custom-page-footer', start: 'top center', end: '+=100', scrub: true, markers: true, toggleActions: 'play reverse play reverse', }, }); tl.to('.nav-cta-join-the-fast-lane', { opacity: 0, duration: 0.1, }); tl.to('.nav-gushwork-logo', { opacity: 0, duration: 0.1, }); But none of those three selectors are present in the HTML so GSAP is not doing anything. Because of that the start and end markers are set to the top of the viewport. Without those elements those positions will not be fixed. In order to solve the rendering order issue, use refreshPriority in your ScrollTrigger configs. From the ScrollTrigger docs: 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. So the ScrollTrigger instance in your endpage component should have a higher number than the one in the index component. Hopefully this helps. Happy Tweening!
  7. Hi, I don't think there is need for all that &nbsp; there, maybe just a different HTML could be enough: <blockquote style="font-size: 18.21px; width: 305.735px; height: 55.8393px; font-style: normal; font-family: Roboto-Regular, gfs; text-decoration: none; transform: translate(144.927px, 0.663px); max-width: calc(100% - 22.7625px); text-align: center; text-transform: none; background: rgb(0, 0, 0); color: rgb(255, 255, 255); letter-spacing: 0em; line-height: 1.2; word-break: break-word; padding: 6px;"> <p class="sc-bdxVC lcokJp"> tom hello hello there how are you<br>rom<span class="right">hello</span> </p> </blockquote> <br> With this CSS: .right { margin-left: 25%; } Here is a fork of your codepen using the latest version of GSAP and SplitText as well: https://codepen.io/GreenSock/pen/jOejgYV Hopefully this helps. Happy Tweening!
  8. Hi @i_dont_understand_gsap and welcome to the GreenSock forums! I see that you're not using GSAP Context in your code and that you're not doing proper cleanup in your effect hook. Since React 18 is super important to cleanup in your effect hook as explained here: Here you can learn more about GSAP Context: https://greensock.com/docs/v3/GSAP/gsap.context() Finally take a look at the resources in this page to get a better grasp about using GSAP in your React projects: Hopefully this helps. Happy Tweening!
  9. Hi, For the image part you could use the Flip Plugin in combination with ScrollTrigger. There are two approaches and both rely on reparenting the target element. This one uses ScrollTrigger srcub for the Flip animation and is a bit more complex in order to accommodate for window resizes: https://codepen.io/GreenSock/pen/bGxOjeP This one is simpler and it uses the callbacks ScrollTrigger has for moving the image: https://codepen.io/GreenSock/pen/yLjKPEm As for the letters, you are making one of the ScrollTrigger mistakes we have referenced in the docs: let tl = gsap.timeline({ scrollTrigger: { trigger: ".secondPinArea", pin: true, markers: false, start: "top top", scrub: 1, end: "+=" + pinAmount } }); ///Fade the letters C(O)DING in -- more failure gsap.utils.toArray(".secondPinArea div").forEach((section) => { tl.from(section, { opacity: 0, immediateRender: false, scrollTrigger: { trigger: ".secondPinArea", anticipatePin: 1, start: "top top", end: "+=50", markers: true } }); }); Here you have a Timeline instances. Timelines are, among other things, containers of animations and they control the position of each animation's playhead. On top of that you have ScrollTrigger that ties up the progress of the Timeline to the scroll position. So far so good. Then you add an instance for each element in the loop to the same Timeline and create a ScrollTrigger for each particular instance. So now you have the Timeline trying to control the playhead of each instance, that particular timeline progress is updated by the scroll position, but at the same time the ScrollTrigger instance of each instance is also fighting to control each instance's progress with a different scroll amount. Sure the start point is the same but the end point is not. So at the end who has control of the instances in the loop? The timeline, ScrollTrigger? See the issue? The main point is not put ScrollTrigger on instances that are in a Timeline, create your ScrollTrigger in the timeline. Also you don't need to run a loop and add each instance to the timeline, just pass the selector to GSAP and use Staggers: let tl = gsap.timeline({ scrollTrigger: { trigger: ".secondPinArea", pin: true, markers: false, start: "top top", scrub: 1, end: "+=" + pinAmount } }); tl.from(".secondPinArea div", { opacity: 0, stagger: 0.1, }); Here is a fork of your codepen: https://codepen.io/GreenSock/pen/OJBeeYG Hopefully this helps. Happy Tweening!
  10. Hi @Brian_Open and welcome to the GreenSock forums! I don't think container animation is what you're looking for actually. If you check the example you posted the faster horizontal animation is not linked to the scroll bar but to the wheel event. I think a far better approach is to have a single timeline that has both horizontal animations, each with a different duration and also different number of repeats so the total time of each loop is the same. So the faster animation is 3 seconds and repeats 9 times (30 seconds, remember that the first run counts as a repeat ) and the slower is 10 seconds and repeats 2 times (30 seconds) . Here is a super simple example of this approach: https://codepen.io/GreenSock/pen/WNaqzOW Is worth noticing that this approach should allow you to use the container animation if you want/need to use that feature. Hopefully this helps. Happy Tweening!
  11. Hi @Harry J and welcome to the GreenSock forums! I don't think the last example in this thread is designed to work the way you intend. Maybe a better option would be to use the Horizontal Loop function helper with a small update I made to it in order to change the direction based on the drag direction: https://codepen.io/GreenSock/pen/mdzZXKm Now this example has some small changes I added to the helper function, so I can't guarantee that this is 100% bullet proof. In the tests I ran it seems to hold water. Here you can see the original version: https://greensock.com/docs/v3/HelperFunctions#loop Hopefully this helps. Happy Tweening!
  12. Hi, Yeah for some reason codesandbox is being weird, it wouldn't be the first time 🤷‍♂️ Instead of finding a way to make the sandbox link work I ported the example to Stackblitz: https://stackblitz.com/edit/stackblitz-starters-91fcze?description=A create-react-app project based on react and react-dom&file=src%2FApp.js&title=React Starter I recommend you that for future questions just use Stackblitz, far more stable and less troubles than in codesandbox. Happy Tweening!
  13. Hi, You have an odd setup IMHO. Why you have a useEffect listening for a change in a ref when you could just create a method and call it from the onComplete callback. Also right now you're toggling the isTweening value twice, when you animate the texts and when you animate the slides. I think this is a far better approach that uses GSAP Context correctly in order to properly cleanup all your GSAP instances in case the component is unmounted: https://codesandbox.io/s/withered-cookies-oe6smp?file=/src/App.js Hopefully this helps. Happy Tweening!
  14. Hi, This is a far more complicated logic issue. The problem here is that at certain points the Y position of the rec is the same while the progress of the timeline keeps increasing as you scroll. This generates odd values for this: gsap.ticker.add(() => gsap.to(section_2_container, { x: 0, y: -( gsap.getProperty(rec, "y") - ((window.innerHeight - rec.clientHeight) * section_2.progress()) ) }) ); I tried different approaches for this, taking into account the Y position of the element in order to not move the container, but all of them resulted in space at the bottom of the element, which is the initial problem you had (I remember the other thread you created about this). I think the best course of action is a different approach for this: https://codepen.io/GreenSock/pen/xxyoLRz You can also explore the custom ease helper function by switching the ease option in the config object by changing it to this: // immediateRender: true, ease: pathEase(path), This might not be exactly what you need, but solving the issue you have in your current setup is a custom logic work that's beyond the scope of what we can do in these free forums. Unfortunately we don't have the time resources to provide that kind of custom work for our users. You can contact us for a consulting work or post in the Jobs & Freelance forums if you want. Hopefully this helps. Happy Tweening!
  15. Hi, The only thing I can spot is this: if (splits.length) { splits.forEach((split, idx) => { split.revert(); if (tl) { split.elements.forEach((el) => { gsap.set(el, { clearProps: true }); }); } }); } No need to do clearProps after the revert method. The revert method does that for you, so this will have the same effect: if (splits.length) { splits.forEach((split, idx) => { split.revert(); }); } Also this shouldn't have any effect whatsoever: const tl = gsap.timeline({ pause: true, scrollTrigger: { trigger: rowJobs, toggleActions: "play pause resume reset", start: "25% bottom", markers: true, }, onStart: () => { // refresh scrollTrigger on page load to ensure correct scrollTrigger start/end tl.scrollTrigger.refresh(); } }); I don't see the use of that particular refresh method there, when the timeline that has that particular ScrollTrigger config starts, to refresh it's own ScrollTrigger instance. ScrollTrigger already watches for resize events so there is no need for that, if that's what you're aiming for. Other than that your code is quite clear. Hopefully this helps. Happy Tweening!