Jump to content
Search Community

Rodrigo last won the day on April 24

Rodrigo had the most liked content!

Rodrigo

Administrators
  • Posts

    6,598
  • Joined

  • Last visited

  • Days Won

    285

Posts posted by Rodrigo

  1. The useGSAP hook has a dependency for at least React 16, but it doesn't use/install React 16:

      "dependencies": {
        "gsap": "^3.12.5",
        "react": ">=16"
      },

    If you already have React 18 installing the @gsap/react package won't change a thing and won't install another version of React.

     

    I just tested this on a demo here on my local machine using the latest version of Next without any issues. We only encountered some issues while importing the @gsap/react package from esm.sh, which solves by doing this:
     

    import React from "https://esm.sh/react@18.3.1";
    import ReactDOM from "https://esm.sh/react-dom@18.3.1";
    
    import gsap from "https://esm.sh/gsap";
    import { useGSAP } from "https://esm.sh/@gsap/react?deps=react@18.3.1";

    We'll update the dependencies on the hook to be at least version 17 of React.

     

    Finally it would be super helpful if you could create a minimal demo that reproduces this error.

     

    Happy Tweening!

    • Like 1
  2. Mhh... Why are you using intersection observer for something that can be done with ScrollTrigger?

     

    I think you are overcomplicating this quite a bit. If I was you  I'd create an extra prop for ScrollTrigger and if that prop has a ScrollTrigger configuration, you just need to check if is not falsy, instead of using just SplitText use ScrollTrigger to handle when the animation plays, something like this:

    See the Pen abxMRgp by GreenSock (@GreenSock) on CodePen

     

    I updated the demo I posted before so it uses ScrollTrigger

    https://stackblitz.com/edit/nuxt-starter-vzsxyp?file=app.vue

     

    The only detail is that this check is not needed with ScrollTrigger:

    completed && tween.progress(1);

    Hopefully this helps.

    Happy Tweening!

    • Like 1
  3. Hi,

     

    You also posted in this other thread:

    Where Jack suggested using ScrollTrigger's sort() method for solving this:

    https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.sort()/

     

    This works as expected:

    sectionB.forEach((section) => {
      
       const textElement = section.querySelector("span");
      //   Load some data, then initialize animation
      later(3000).then(() => {
        console.log("Loaded!!");
    
        const tl = gsap.timeline({
          scrollTrigger: {
            trigger: section,
            start: "top top",
            end: `+=2000`,
            markers: true,
            scrub: true,
            pin: true
          }
        });
    
        tl.to(textElement, {
          scale: 1.2,
          ease: "power1.inOut"
        });
        // Sort the ScrollTrigger instances
        ScrollTrigger.sort();
      });
    });

    This happens because the ScrollTrigger are not created in the order they appear on the screen, if that is not possible we recommend using the refreshPriority configuration in combination with the sort() method, from the ScrollTrigger docs:

    refreshPriority
    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.

     

    Hopefully this helps.

    Happy Tweening!

  4. 23 minutes ago, xtinepak said:

    One thing I'm noticing is that I've to scroll multiple times to change the slides between the sections. For example when the swiper section starts I've to scroll 3 or 4 times to go to the next section. Could you please let me know what needs to be done here?

    It takes only one wheel/touch event, but the previous animation  has to be completed first and we want to wait for some specific situations:

    let allowScroll = true; // sometimes we want to ignore scroll-related stuff, like when an Observer-based section is transitioning.
    let scrollTimeout = gsap.delayedCall(1, () => allowScroll = true).pause(); // controls how long we should wait after an Observer-based animation is initiated before we allow another scroll-related action

     

    3 minutes ago, xtinepak said:

    if we could add fade in/out effect for the swiper section instead of scroll that would be excellent?

    Sure thing, just tinker with the logic in the gotoPanel method, that's where everything happens in terms of animations:

    function gotoPanel(index, isScrollingDown) {
      // return to normal scroll if we're at the end or back up to the start
      if ((index === swipePanels.length && isScrollingDown) || (index === -1 && !isScrollingDown)) {
        intentObserver.disable(); // resume native scroll
        return;
      }
      allowScroll = false;
      scrollTimeout.restart(true);
    
      let target = isScrollingDown ? swipePanels[currentIndex] : swipePanels[index];
      gsap.to(target, {
        yPercent: isScrollingDown ? -100 : 0,
        duration: 0.75
      });
    
      currentIndex = index;
    }

    You can switch yPercent for opacity/autoAlpha without any issues.

     

    Hopefully this clear things up.

    Happy Tweening!

  5. No problemo! Also in these forums there are no stupid questions 👍

     

    That's just the Logical AND operator:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND

     

    Basically it checks if timer is truthy, if it is it'll clear the timeout. By default the timer variable is undefined which will return falsy and the clearTimeout won't be executed, same with the completed boolean. I want to set the progress of the tween to 1 only if the tween has run completely.

     

    Hopefully this clear things up.

    Happy Tweening!

    • Like 1
  6. Hi,

     

    The issue is in this funky useEffect hook  you have here:
     

    useEffect(() => {
      setInterval(() => {
        setState(Math.random());
      }, 1500);
    });

    That basically runs everytime the component is re-rendered since it has no dependencies array, but at the same time each time the interval is completed the state is updated, creating a new interval and running your custom hook again, so after the first interval is completed a new one is created and each new interval will create a new one, so this grows exponentially.

     

    Here is a fork of your demo without that and it has only two onLeave callbacks, which makes sense since the effect hooks are called twice on StrictMode:

    https://stackblitz.com/edit/react-pps835?file=src%2FApp.jsx

     

    Hopefully this clear things up.

    Happy Tweening!

  7. Hi,

     

    Actually in the demo the columns have a different height, the thing is that they are being animated in opposite directions.

     

    Here is a fork of the same demo with both columns animating in the same direction:

    See the Pen mdgoKVm by GreenSock (@GreenSock) on CodePen

     

    Finally this is most about the calculations needed to move each column on a given direction.

     

    Hopefully this clear things up.

    Happy Tweening!

  8. Hi @fraserYT and welcome to the GSAP Forums!

     

    You are using an extremely generic selector. I'd strongly recommend you to use a unique class in your elements even if it doesn't have any styles, just for selecting purposes. This seems to work the way you expect:

    <div class="header-icons">
      <div class="menu-item"></div>
      <div class="menu-item"></div>
      <div class="menu-item"></div>
      <div class="menu-item"></div>
      <div class="menu-item"></div>
      <div class="menu-item"></div>
    </div>
    gsap.to(".header-icons .menu-item", {
      opacity: 0,
      y: -80,
      stagger: 0.1,
      scrollTrigger: {
        trigger: ".full-row",
        start: 0,
        end: 230,
        scrub: 0.5,
        markers: true
      }
    });

    Here is a fork of your demo:

    See the Pen oNOVqKm by GreenSock (@GreenSock) on CodePen

     

    Hopefully this helps.

    Happy Tweening!

    • Like 1
  9. Hi,


    The video in your demo is over 130MB and it's dimensions are huge. As Cassie mentions rendering the video alone doesn't create any problems but together with other stuff, it can definitely become an issue.

     

    If you want to create some type of particles moving background and you want excellent performance I'd recommend PIXI's particle container:

    https://pixijs.com/8.x/examples/basic/particle-container

     

    You can check this demos by @OSUblake

    See the Pen BjNZYP by osublake (@osublake) on CodePen

     

    See the Pen PjrbWq by osublake (@osublake) on CodePen

     

    Happy Tweening!

  10. Ahh yeah I see the problem now. Roughly this is your HTML

    <div class="scroll-through-hero st-hero-animate sth-fadein-off" style="background-color: inherit;"></div>
    <div class="immersive-scroll-video" style="background-color: inherit;"></div>
    <div class="immersive-scroll-video" style="background-color: inherit;"></div>
    <div class="scroll-through-hero st-hero-animate sth-fadein-off" style="background-color: inherit;"></div>

    In your JS you're creating the ScrollTrigger instances for the elements inside the immersive-scroll-video elements and then for the scroll-through-hero elements. When using ScrollTrigger ideally create the instances in the order they appear on the screen as the user scrolls down, especially if you are pinning one or more ScrollTrigger instances.

     

    If you can't create your instances in the order they appear in the screen, then you can use the refreshPriority config option. From the ScrollTrigger docs:

    refreshPriority
    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.

     

    Here is the docs for the sort method:
    https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.sort()

     

    Hopefully this helps.

    Happy Tweening!

  11. Hi,

     

    I'm not 100% sure of what issue you're experiencing, but waiting for 1 tick of GSAP's ticker should be enough. As far as I can tell, after you revert your GSAP instances and create the new ones, it should take 1 tick to render the new ones, so that should be enough. Based on your demo this is how I would proceed:

    const tweenable = document.getElementById('tweenable')
    
    let tween, timer;
    
    const createTween = () => {
       tween = gsap.timeline().fromTo(tweenable, {opacity: 1}, {opacity: 0, duration: 1});
    };
    
    const revertTween = () => {
      tween && tween.revert();
      createTween();
    };
    
    window.addEventListener("resize", () => {
      timer && clearTimeout(timer);
      timer = setTimeout(() => {
        revertTween();
      }, 200);
    });
    
    createTween();

    Here is a fork of your demo:

    See the Pen oNOVzdg by GreenSock (@GreenSock) on CodePen

     

    Hopefully this helps.

    Happy Tweening!

  12. 11 hours ago, GregQP said:

    If you look at the StackBlitz I created you can see that instances of ScrollTrigger are firing their onleave event on instantiation. But as they haven’t been scrolled they shouldn’t fire an onleave event 

    That's because the first  ScrollTrigger instance is passed the end marker and the second one is passed the start marker, makes total sense:

    slsCFTH.pngYou have to take a look at the clamp feature in ScrollTrigger:

     

    11 hours ago, GregQP said:

    A react hook abstracts logic to make it reusable. ueaGSAP is the same. 
     

    The hook I created does the same except it also contains tweens and attaches the timeline for those tweens to a ScrollTrigger that then uses a master div as its scroller.  It’s how I designed it based on other answers in this forum.
     

    With the hook I can just pass a ref in from amy component and have it animate.  If I just used useGSAP I’d write a lot more code. Which is the cornerstone of react.. reusable functions that save you repeating yourself yourself 

    Yep I'm aware of what custom hooks do in React, I wrote parts of our useGSAP hook.

     

    Hopefully this helps.

    Happy Tweening!

  13. Hi,

     

    You could try clearing the inline styles applied by GSAP using clearProps on an onComplete callback:

    gsap.timeline({
      repeat: 1,
      yoyo: true,
      onComplete: () => gsap.set(element, { clearProps: "scale" }),
    })
      .to(element, { scale: 1.1, duration: 1, });

    Another option could be to try using will-change: transform on those images and see how that works.

     

    Hopefully this helps, if you keep having issues, please try to create a minimal demo so we can have a better look.

    Happy Tweening!

×
×
  • Create New...