Jump to content
GreenSock

Rodrigo last won the day on September 23

Rodrigo had the most liked content!

Rodrigo

Administrators
  • Posts

    5,037
  • Joined

  • Last visited

  • Days Won

    246

Community Answers

  1. Rodrigo's post in Having trouble with scrollTrigger inside forEach was marked as the answer   
    Hi,
     
    Basically the issue is that you are running an extra loop for the slides of each section.
     
    Here is a fork of your codepen:

    See the Pen KKboBBd by GreenSock (@GreenSock) on CodePen
     
    Hopefully this helps.
    Happy Tweening!
  2. Rodrigo's post in Draggable on Mousewheel/Idle was marked as the answer   
    Hi,
     
    You have some errors in the way you're using Observer's callbacks. You use them to animate the element and then once those animations are completed you update your Draggable instance:

    See the Pen dywMYxM by GreenSock (@GreenSock) on CodePen
     
    Hopefully this helps.
    Happy Tweening!
  3. Rodrigo's post in Horizontal scroll snap with different widths was marked as the answer   
    Hi,
     
    This example should provide a good starting point:

    See the Pen xxEQNBB by GreenSock (@GreenSock) on CodePen
     
    Hopefully this helps.
    Happy Tweening!
  4. Rodrigo's post in Scrolltrigger sequence pin next section to was marked as the answer   
    Hi,
     
    Here is another option:

    See the Pen wvRpZOp by GreenSock (@GreenSock) on CodePen
     
    Hopefully this helps.
    Happy Tweening!
  5. Rodrigo's post in Optimizing performance of multiple infinite horizontal loops was marked as the answer   
    Hi @jessicsw and welcome to the GreenSock forums!
     
    Given the current setup you have I don't know what can be improved. I tested in a very old laptop (10+ years) and I don't see any jittering. Since the helper function is optimized enough already. What you could try is use will-change: transform for the <li> element:
     
    https://stackblitz.com/edit/gsap-react-basic-f48716-ro4uan?file=src%2FApp.js,src%2Fstyle.css
     
    Beyond that I don't know what else can be done.
     
    Regarding the current approach you have, it seems to work very well, so I wouldn't change anything as long as it works as expected: If it ain't broken, don't fix it
     
    Hopefully this helps.
    Happy Tweening!
  6. Rodrigo's post in Responsive behavior using SplitText was marked as the answer   
    Hi Pedro,
     
    It seems that the revert method is not cleaning the height and width given to the SplitText target h1. This seems to resolve the issue:
    if (text) { text.revert(); gsap.set("h1", { clearProps: true, }); // Remove all inline styles applied by GSAP } Hopefully this helps.
    Happy Tweening!
  7. Rodrigo's post in Navigation Bar ScrollTTrigger was marked as the answer   
    Hi,
     
    Maybe the video and demo by @Carl in this thread can help:
     
    Happy Tweening!
  8. Rodrigo's post in Using gsap.set() to replace jQuery methods appears to be causing issues. was marked as the answer   
    Absolutely! You can create as many as you want, just keep in mind that every loop instance should have different targets to prevent unexpected results:

    See the Pen dyQNeRZ by GreenSock (@GreenSock) on CodePen
     
    Hopefully this helps.
    Happy Tweening!
  9. Rodrigo's post in matchMedia() was marked as the answer   
    Hi,
     
    Is really hard to find out what the issue could be without a minimal demo.
     
    Most likely this has to do with the fact that you are creating two different animations that affect the same targets and the same properties. Is better to create the animation inside each MatchMedia callback:
    mm.add('(max-width: 799px)', () => { let tlMed = gsap.timeline(); tlMed.from('#t-c1', { opacity: 0, x: -100, filter: 'blur(30px)', }); tlMed.from('#t-c2', { opacity: 0, x: 100, filter: 'blur(30px)', }); tlMed.from('#t-c3', { opacity: 0, x: -100, filter: 'blur(30px)', }); ScrollTrigger.create({ trigger: '#my-story', start: 'top 30%', end: 'bottom bottom', scrub: true, animation: tlMed, }); }); And follow the same pattern with the large screen animation.
     
    Hopefully this helps.
    Happy Tweening!
  10. Rodrigo's post in pinned item ignores margin placed was marked as the answer   
    Hi,
     
    OK I gotcha now, sorry for being such a knuckle-head about it, the single functioning neuron must be spinning in the wrong direction
     
    This is just about styles, since ScrollTrigger pin feature adds a position fixed to the elements being pinned, that takes the element out of the document's flow which creates this issue. You could just add some style to the <p> tag in your css:
    .o2lab__col p { width: 50%; } Another option is to use padding instead of margins:
    .mr-94 { padding-right: 94px; } .ml-94 { padding-left: 94px; } Hopefully this helps.
    Happy Tweening!
  11. Rodrigo's post in Smooth Movement was marked as the answer   
    Hi,
     
    You can tween the progress of a timeline and apply an ease in/out function, like this:

    See the Pen zYyPaJw by GreenSock (@GreenSock) on CodePen
     
    GSAP can tween the numeric value of any property on any object. Since Timelines are just objects, that can be done with a regular gsap.to() instance.
     
    Hopefully this helps.
    Happy Tweening!
  12. Rodrigo's post in Problem with infinite slider was marked as the answer   
    Hi @Oyno and welcome to the GreenSock forums!
     
    You should take a look at the Horizontal Endless Loop helper function:
     
    https://greensock.com/docs/v3/HelperFunctions#loop
     
    Hopefully this helps.
    Happy Tweening!
  13. Rodrigo's post in GSAP preloading + CSS animation (PNG Sequence) was marked as the answer   
    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!
  14. Rodrigo's post in how can I make a gradient animation to move on svg path specified was marked as the answer   
    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:

    See the Pen LYMLQvw by GreenSock (@GreenSock) on CodePen
     
    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!
  15. Rodrigo's post in I've failed to create a correct animation for an element for a negative x value in gsap.to() was marked as the answer   
    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:

    See the Pen eYbWqwE by GreenSock (@GreenSock) on CodePen
     
    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!
  16. Rodrigo's post in SplitText - Stagger the animation on between lines was marked as the answer   
    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:

    See the Pen YzdVdKe by GreenSock (@GreenSock) on CodePen
     
    Hopefully this helps.
    Happy Tweening!
  17. Rodrigo's post in Scrolltrigger - Update animation value on resize was marked as the answer   
    Hi,
     
    I'm not sure I follow 100% what you mean by this. ScrollTrigger has to do a few operations when the browser window resizes. After all that is completed and the instances' start and end points are updated, ScrollTrigger checks for the current scroll position and updates all the instances accordingly. Since you have scrub: true the update will be immediately. If you want for it to be smoother, you can use a number in scrub instead of the boolean.
     
    Finally you can change your code to this:
    scrollTrigger: { id: "NavTop", markers: true, trigger: "#intro", start: () => "bottom "+intro.offsetHeight, end: () => "+="+intro.offsetHeight , scrub: true, invalidateOnRefresh: true, onLeaveBack: () => document.getElementById("nav").style.removeProperty("top"), } That onLeaveBack callback does the same our onUpdate does, but instead of running all that logic on every update, it only changes the style of the element directly once, no need for conditional checks and more expensive code.
     
    Hopefully this helps.
    Happy Tweening!
  18. Rodrigo's post in Uncaught ReferenceError: ScrollTrigger is not defined? was marked as the answer   
    Hi
     
    Your custom script is being loaded before the bundle file. The bundle file should be a dependency of your custom file as well as jQuery.
     
    Give that a try and let us know how it works.
     
    Hopefully this helps.
    Happy Tweening!
  19. Rodrigo's post in Please gsap.registerPlugin(Draggable) TypeError: _toArray is not a function was marked as the answer   
    Hi,
     
    Actually it seems that you tried what I mentioned but you definitely didn't read the articles in the page I linked in my previous post.
     
    You have your timeline constructor in the outer scope of your component. Any re-render of the component will reset that particular instance and you're adding animations to it in the use effect. When working with React ALWAYS use GSAP Context as I also mentioned in my previous post. Create all your GSAP instances (Tweens, Timelines, ScrollTrigger, Draggable, etc) inside a GSAP Context instance and revert it on the cleanup phase of the useEffect/useLayoutEffect hooks.
     
    Unfortunately we don't have the time resources to go through all the code in your example, but there is definitely something in it that is creating this issue. Here is a super simple example that doesn't return any error and the Draggable green box works:
    https://stackblitz.com/edit/nextjs-qhrskj?file=pages%2Findex.js
     
    Hopefully this helps.
    Happy Tweening!
  20. Rodrigo's post in Pinning and Scrolltrigger refresh not responsive was marked as the answer   
    Hi,
     
    A few things. You are using ScrollTrigger MatchMedia:
    https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.matchMedia()
     
    That has been deprecated in favor of GSAP MatchMedia:
    https://greensock.com/docs/v3/GSAP/gsap.matchMedia()
     
    You are creating a timeline outside the MatchMedia scope, it would be a good idea to either create the timeline inside the MatchMedia scope or refresh it ScrollTrigger instance in the MatchMedia callbacks, kind of like you are doing it right now, but just that particular ScrollTrigger, no need to refresh everything.
     
    You have CSS transitions applied to an element with the .phone class. That could be a major issue as Jack explains here:
    Finally you have several ScrollTrigger configurations inside child instances on a Timeline. That is a logical issue since you have both a Timeline and a ScrollTrigger instance battling to control the progress of those child instances. From the ScrollTrigger docs:
     
    Can I have multiple nested ScrollTriggers in various child tweens in a timeline?
    Technically you could but it usually doesn't make sense. An animation's playhead is controlled by its parent timeline's playhead so as it sweeps over the children it updates their playheads accordingly. However, when you assign an animation to a ScrollTrigger, it gets paused and the ScrollTrigger instance controls its playhead. It wouldn't be good to have multiple things trying to control the same animation's playhead. It's typically best to either have one ScrollTrigger control the entire timeline or use independent tween, each with their own ScrollTrigger.
     
    I suggest you to correct all those things in order to clean up a little your example and see if that solves the issues you are having right now.
     
    Hopefully this helps.
    Happy Tweening!
  21. Rodrigo's post in Disabling Default Styles Applied by Draggable for Text Selection was marked as the answer   
    Hi,
     
    There is not a lot we can do without a minimal demo. Also I'm a bit confused, you mention that you want to prevent users from selecting the text of an element that can be dragged around using GSAP Draggable, and the plugin does exactly that with the styles it applies to the element.
     
    If you want to disable the instance and prevent the text from being selected after, then simply you can use clearProps to remove that particular style from the element after disabling the Draggable instance:
    const d = Draggable.create(".box", {...}); d[0].disable(); gsap.set(".box", { clearProps: "userSelect" }); Hopefully this helps.
    Happy Tweening!
  22. Rodrigo's post in GSAP Draggable instance with parallax effect on object was marked as the answer   
    Hi @51North and welcome to the GreenSock forums!
     
    Thanks for being a Club GreenSock member and supporting GreenSock!
     
    My approach would be to use a QuickTo instance in the onDrag and onThrowUpdate callbacks:
    https://greensock.com/docs/v3/GSAP/gsap.quickTo()
     
    Maybe something like this:

    See the Pen WNLRdXR by GreenSock (@GreenSock) on CodePen
     
    Hopefully this helps.
    Happy Tweening!
  23. Rodrigo's post in GLTF/GLB model ScrollTrigger snap scroll in to original position was marked as the answer   
    Hi,
     
    What you could try is that in your button event handler you can invalidate the timeline instance:
    https://greensock.com/docs/v3/GSAP/Timeline/invalidate()
    const tl = gsap.timeline({ scrollTrigger: { // all your ST config }, }); // Later on your code tl.invalidate(); Another option could be to manually refresh the particular ScrollTrigger instance and add invalidateOnRefresh in the ScrollTrigger config:
    const tl = gsap.timeline({ scrollTrigger: { // all your ST config invalidateOnRefresh: true, }, }); // Later on your code tl.scrollTrigger.refresh(); If this is not helping, please be super specific about what you're trying to do, kind of explain step by step the procedure of what you intend to do and what is your desired outcome, because right now is not 100% clear to me what you're trying to achieve here.
     
    Hopefully this helps.
    Happy Tweening!
  24. Rodrigo's post in Animating ellipses inside SVG, the bounding box is visible was marked as the answer   
    Hi,
     
    Sorry about the issues but I have almost no experience with SVG filters so I have no idea what could be the issue here.
     
    Just to clarify a few things, when you say that you couldn't reproduce this on codepen as it only happens on React and not in VanillaJS? That would be super weird.
     
    The only thing I can think of is using the Attribute Plugin to tween the values of the filters and lucky me it seems to work:
    timeline.current .to(containerRef.current, { backgroundColor: backgrounds[index].backgroundColor, }) .to( q(".ellipsea"), { attr: { cx: backgrounds[index].ellipseA.cx, cy: backgrounds[index].ellipseA.cy, rx: backgrounds[index].ellipseA.rx, ry: backgrounds[index].ellipseA.ry, fill: backgrounds[index].ellipseA.fill, }, // onUpdate: () => console.log('ellipseA update!') }, "<" ) .to( q(".ellipseb"), { attr: { cx: backgrounds[index].ellipseB.cx, cy: backgrounds[index].ellipseB.cy, rx: backgrounds[index].ellipseB.rx, ry: backgrounds[index].ellipseB.ry, fill: backgrounds[index].ellipseB.fill, }, }, "<" ) .to( q(".filtera"), { attr: { x: backgrounds[index].filterA.x, y: backgrounds[index].filterA.y, width: backgrounds[index].filterA.width, height: backgrounds[index].filterA.height, }, }, "<" ) .to( q(".filterb"), { attr: { x: backgrounds[index].filterB.x, y: backgrounds[index].filterB.y, width: backgrounds[index].filterB.width, height: backgrounds[index].filterB.height, }, }, "<" ); https://greensock.com/docs/v3/GSAP/CorePlugins/AttrPlugin
     
    Here is a fork of your sandbox, I changed the duration to make it faster and moved the repetitive configs to the defaults object in the Timeline constructor:
    https://codesandbox.io/s/delicate-haze-jk3m2c?file=/src/BackgroundGradient.tsx
     
    Hopefully this helps.
    Happy Tweening!
  25. Rodrigo's post in Animate pseudo-elements like `::before` was marked as the answer   
    Hi,
     
    The reason for that is the way you have your color string. This seems to work the way you expect:
    .pinned-active { --pinned-active-black: rgba(14, 14, 14, 0); } Then in your JS:
    sectionTl.current.to(section, { "--pinned-active-black": "rgba(14, 14, 14, 0.6)", y: () => -100, duration: 1, scrollTrigger: { ... } }); Hopefully this helps.
    Happy Tweening!
×