Jump to content
Search Community

Rodrigo last won the day on April 28

Rodrigo had the most liked content!

Rodrigo

Administrators
  • Posts

    6,653
  • Joined

  • Last visited

  • Days Won

    287

Everything posted by Rodrigo

  1. Hi, I don't have a lot of experience with THREE so I can't do a lot to replicate your issue. Most likely this seems related to the fact that you're passing an object to GSAP in a way it can't be handled. You need to target the x property of the scale object. One option I can think of is to create an array of objects that you can tween and use the onUpdate method to apply the changes to each cube element, but that would imply to loop through all the cubes in the callback in order to apply the scale values to each cube: const scales = gltf.scene.children.map(cube => { cube.castShadow = true; cube.receiveShadow = true; cube.scale.set(0.2, 0.2, 0.2); return { x: 0.2 }; }); Then you can run GSAP with advanced staggers on that array: gsap.to( scales, { duration: 2, x: 1, stagger: { amount: 0.1, grid: "auto", from: "center" }, onUpdate: updateScales, }); Sorry I can't be of more assistance, but this is not really a GSAP issue but a limitation of sorts in the way THREE (and most of the WebGL libraries I know for that matter) works when it comes to it's display objects/geometries. Hopefully this helps. Happy Tweening!
  2. Hi, The main issue is that you are running the conditional rendering logic before the animation happens. Here is a quick and simple way to demonstrate this flow. You pass the state property that renders the element, the element is rendered, then the animation is created and finally the IN animation runs. So far no problem. Then you switch the state property and the animation is created or it could be reversed, but a few milliseconds later, since you are conditionally rendering the element, it is removed from the DOM without the animation never being completed. You need two different state properties. One outside the component you want to conditionally render and animate and another inside of that component. The one outside the component should tell the component to render it's content and to start the OUT animation. The one inside the component should tell the component to start the IN animation and to not render the component anymore. It might sound complicated but is just basic React logic, or as a matter of fact any other of these frameworks if you want to do this manually. Is far simpler to use a third party component that handles all that inner logic for you. In the case of React React Transition Group. Here is a simple demo of using it for a modal element: https://stackblitz.com/edit/vitejs-vite-vlpbvk?file=src%2FApp.jsx,src%2FModal.jsx&terminal=dev As you can see the setup is far simpler and you don't have to worry with an extra state property inside or outside the component. Hopefully this helps. Happy Tweening!
  3. Hi @AllenIVe, I forked Blake's codepen, is just about some CSS: https://codepen.io/GreenSock/pen/RwEJzVV Hopefully this helps. Happy Tweening!
  4. Hi, I think the issue lies in the fact that you are removing an event listener on a different add() method in your MatchMedia instance: mm.add("(max-width: 767px)", () => { // This is defined inside this scope // Not available outside this add() method's callback const handleBurgerMenuClick = () => { ... }; burgerMenu.addEventListener("click", handleBurgerMenuClick); }); mm.add("(min-width: 768px)", () => { // Removing event listener // but handleBurgerMenuClick is not defined inside this scope burgerMenu.removeEventListener("click", handleBurgerMenuClick); }); GSAP MatchMedia has a cleanup function that is returned in the add method that allows you to do that: mm.add("(max-width: 767px)", () => { return () => { // optionally return a cleanup function that will be called when // none of the conditions match anymore (after having matched) } }); So in your case it would be like this: mm.add("(max-width: 767px)", () => { // This is defined inside this scope // Not available outside this add() method's callback const handleBurgerMenuClick = () => { ... }; burgerMenu.addEventListener("click", handleBurgerMenuClick); return () => burgerMenu.removeEventListener("click", handleBurgerMenuClick); }); mm.add("(min-width: 768px)", () => { // Don't care about that event listener here }); That seems to work in the way you intend: https://codepen.io/GreenSock/pen/GRPGaPj Give that a try and let us know how it works. Hopefully this helps. Happy Tweening!
  5. Rodrigo

    GSAP

    Hi @hexciaLondon and welcome to the GreenSock forums! I made some changes to your CSS and your code: https://codepen.io/GreenSock/pen/bGOKJjN Basically there were two issues. The width of the gallery container wasn't spreading based on the width of the boxes and you were passing a string value to GSAP: tl.to(gallery, { x: `-${gallery.offsetWidth}`, // This is a string scrollTrigger: { trigger: galleryWrapper, start: 'top top', end: `+=${gallery.offsetWidth}`, pin: true, scrub: 0.5, } }) There is no need to pass a string, although it won't cause a major issue though, but the width of the boxes container was basically the major problem. Hopefully this helps. Happy Tweening!
  6. Hi, Maybe the threads @alig01 shared in this post could help: Happy Tweening!
  7. Hi, Indeed ScrollSmoother has a speed config option that's allows you to do exactly what you're looking for. From the ScrollSmoother docs: speed Number - a multiplier for overall scroll speed, so 2 would make it scroll twice the normal speed, and 0.5 would make it scroll at half-speed. added in version 3.11.4. Hopefully this helps. Happy Tweening!
  8. Hi, Just use a click event handler that updates the state in order to play/reverse the timeline on an useEffect hook with that state as a dependency. The rest is pretty much all in there since the onComplete and onReverseComplete callbacks will do the rest. This basically a simple react question and not a GSAP one. I'd recommend you to check react's docs in order to get a better grasp of it and check the resources in our GSAP and React page, that I linked on my first post. Happy Tweening!
  9. Hi, This is a bit complex and mostly implies the starting and end points of each ScrollTrigger instance for each section, plus the start and end points of the instance that you want to scrub. That needs some extra space before the next section switch happens. Here is my initial approach to this: https://codepen.io/GreenSock/pen/QWzrRxm Hopefully this helps. Happy Tweening!
  10. Hi, The simplest way is to add a label at the start of the timeline, before every other instance: const tl = gsap.timeline({ defaults: { paused: false, ease: "none", duration: 2 }, scrollTrigger: {...} }); tl.add("start"); That adds an extra stop at the start of the timeline and probably would make all the margins and other stuff to offset everything 10 pixels down not needed, but you'd have to test and see. Here is a fork of your codepen: https://codepen.io/GreenSock/pen/GRPdaoo Other than that it would require to write all the logic for the snapTo on a function in order to check the direction of the ScrollTrigger instance, current progress and check where the ScrollTrigger instance should land. Hopefully this helps. Happy Tweening!
  11. Ahh OK. In that case going back to Draggable and using a proxy would be the best approach. Here is a simple demo: https://codepen.io/GreenSock/pen/zYyjXLW Hopefully this helps. Happy Tweeing!
  12. Hi, I didn't said that the examples in that thread are exactly like the ones in the site you linked, just a starting point. There is a bit more custom logic involved into creating that and is not an extremely simple endeavor. In terms of learning, I would start by creating an animation that does what you want, without the mouse follow feature, then create the mouse follow feature that adds calls a method in order to add the image and then animate it. Sure sounds simple but is not that simple. Unfortunately cool effects like that never are and the learning curve sometimes is steeper than we'd like. Good luck! Happy Tweening!
  13. Hi, There were a couple of logic issues in your codepen. This returned an empty array: gsap.utils.toArray(".container"); console.log(gsap.utils.toArray(".container")); // -> [] So that loop did nothing. Then you had a wrong selector in your ScrollSmoother setup: const smoother = ScrollSmoother.create({ content: "#content", smooth: 1, normalizeScroll: true, // ignoreMobileResize: true, effects: true, preventDefault: true }); There is no element with that ID on your DOM tree, so you have to change it to a class selector. This seems to work the way you expect: https://codepen.io/GreenSock/pen/RwEyEgd Hopefully this helps. Happy Tweening!
  14. Hi @Bolargent, The codepen example that Cassie created is doing something completely different. There is no actual masking involved. Just an element with specific dimensions, an overflow hidden and a large border-radius applied to it: .mask { width: 200px; height: 200px; border-radius: 50%; overflow: hidden; } What Cassie is doing is moving the child element of that one based on the mouse position. That plus some other CSS magic tricks plus some simple math achieves that particular effect. Study the codepen and look at the result in devtools to understand how it works. Hopefully this clear things up. Happy Tweening!
  15. Hi, Indeed it looks better with non breaking spaces. I updated the codepen example in my previous post. Happy Tweening!
  16. Hi @Bolargent and welcome to the GreenSock forums! This thread could provide a good starting point: Hopefully this helps. Happy Tweening!
  17. Hi, If you want to reverse the timeline as soon as it completes, is better to use repeat and yoyo. I had to create a completely blank example because your codepen has a lot of elements missing (or classes), so I'm getting a lot of warnings from GSAP that a target is not found: https://codepen.io/GreenSock/pen/GRPdwGB Hopefully this helps. Happy Tweening!
  18. Hi, There are a few things to notice here. The site you posted as an example doesn't use scrolling at all. That doesn't mean that is not possible, is just weird to have natural scroll, having the scroll bar visible and not being allowed to scroll. These examples combines ScrollTrigger with Observer: https://codepen.io/GreenSock/pen/ExEOeJQ https://codepen.io/GreenSock/pen/oNdNLxL Finally you are using your ScrollManager file as a React component. While I can see the value of abstraction and keeping your code more organized IMHO I don't see that as a good and solid approach. Keep in mind that in React child component are rendered first and then their parents, so the code in that particular file runs before the DOM elements are mounted in the DOM on t he first run, so you could get some errors there. Also you are not using effect hooks, GSAP Context or doing proper cleanup in your app. I'd strongly recommend you to create your GSAP code in the same file it'll be used at first and then start abstracting away and micro-optimizing your code. First make it work the way is supposed and make it as easy to follow as possible (comments are helpful here), then make it pretty. Finally read the resources in this page: Hopefully this helps. Happy Tweening!
  19. Hi, I would do it like this: https://codepen.io/GreenSock/pen/qBLYQZa Hopefully this helps. Happy Tweening!
  20. Hi, You are animating the height of the container and you are also animating the font size of that <h1> element, a change in the offset top value is totally expected. In fact, considering what you are doing right now, if the offset top value didn't change at all would be totally unexpected. Keep in mind that changing the height of an element that also affects the document height, pretty much throws off the board every calculation ScrollTrigger makes, so most likely any ScrollTrigger instance that is created after this one will be affected by the change in the document's height. The one solution I can see in this case is, given the fact that you are animating the height between known values (from X pixels height to Y pixels height) you can offset your following ScrollTrigger instances, or your calculations used in the ScrollTo plugin by that amount, in order to correct that height change in the document. Hopefully this helps. Happy Tweening!
  21. Hi, This is related to the initial position of the characters. Jack's original example has a different setup than the one you actually need in order to spread out the characters in the path. This seems to work as expected: https://codepen.io/GreenSock/pen/GRPdYMN Hopefully this helps. Happy Tweening!
  22. Hi, There are a few approaches to this: https://codepen.io/GreenSock/pen/eYbWqwE https://codepen.io/GreenSock/pen/xxmPWqa Hopefully this helps getting you started. Happy Tweening!
  23. Hi @Nordef and welcome to the GreenSock forums! Thanks for being a Club GreenSock member and supporting GreenSock! ? I think this is a better fit for the Observer Plugin rather than Draggable: https://greensock.com/docs/v3/Plugins/Observer Also I can't see the element that you should suppose to drag when the modal/sheet is not visible. On top of that I think you are over engineering this a bit IMHO, the approach I would use is far simpler (drag the fuchsia bar): https://stackblitz.com/edit/vitejs-vite-gmz1zq?file=src%2Findex.css,src%2FApp.jsx,src%2FOverlay.jsx&terminal=dev No need for that useCallback, since everything can be resumed into a single timeline and you can play/reverse that one using the onDragEnd callback from Observer and check the direction with the deltaY value. Also I noticed you are not using GSAP Context in your React app: https://greensock.com/docs/v3/GSAP/gsap.context() When using GSAP in React environments GSAP Context is your best friend since it allows you to scope your selectors inside and allows you to easily cleanup in the cleanup phase of the effect hooks. I strongly recommend you to check the information in this page: And the starter templates collection we have in Stackblitz: https://stackblitz.com/@GreenSockLearning/collections/gsap-react-starters Hopefully this helps. Happy Tweening!
  24. If the HTML/CSS can't be touched to achieve the result you're looking for, the simplest approach I can think is to give he start point of the ScrollTrigger instance a value bigger than the top of the viewport, perhaps 10 in order to emulate to some degree the result you're getting in the codepen due to the natural margin of the body tag: scrollTrigger: { start: "top 10", // when the top of the trigger gets to 10 px from the top of the viewport ... } Hopefully this helps. Happy Tweening!
  25. Hi, The reason the issue doesn't happen on your codepen is because the body has is natural margin of 8px, so the markers are not at the top of the viewport: If you add margin: 0 to the body tag those markers are at the top of the viewport and the issue happens. Now what strikes me as odd is that you have this section with home-banner class that is supposed to have a height of 50vw but the image-cases section is on top of that element. You can see it if you remove all the JS from your codepen demo: The red line there is a border-top property I added to the image-cases section, so as you can see this is a CSS issue and not a GSAP related one. You should review the grid display you have in your setup in order to make it work. Hopefully this helps. Happy Tweening!
×
×
  • Create New...