Jump to content
Search Community

scrollTrigger.refresh() makes IOS lag (only Iphone and Ipad)

astrick

Recommended Posts

Posted

Hi, thank you for your help!.
I'm struggling on only IOS. I tested on Macbook, Samsung, GooglePixel8, they got no issue at all except IOS (Iphones).
.
Behavior, I used everytime when `scrollTrigger.refresh()` got executed on IOS (Tested on Iphone11). I will have a mini-lag. So, I've tested on 9 years old Samsung and I got no issue at all. 
.
So, everytime when I use scrollTrigger + scrub for increasing my element's width and height. The current width and height in scrollTrigger won't update their size (checked by markers). So, I've to use `scrollTrigger.refresh()` to fix this OR open dev tools to update the viewport again.
It will get more worst when I need to use onUpdate +  `scrollTrigger.refresh()`
.
This is how my code looks like (So, without onUpdate e.g. onStart or onComplate. They will also appear this bug as well only on IOS). 

    if (window.innerHeight > window.innerWidth) {
      gsap.to(".aboutVideo", {
        scrollTrigger: {
          trigger: ".about__video",
          start: "bottom bottom",
          end: "center end",
          scrub: 0.5,
        },
        onUpdate: () => {
          ScrollTrigger.refresh();
        },
      });
    }

I have the Netlify link for testing, but I would like to share it once when it’s done. I’d love for GSAP to consider it for a “Site of the Day” feature or something like that.

I really want to show it to them, but I’m afraid that if I share it now, they might not consider it.
Here is my link: https://everymatrix-porchelab.netlify.app/ ( I don't care anymore😞)


My full code is here

//Dependencies
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import SplitText from "gsap/SplitText";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { TextPlugin } from "gsap/TextPlugin";
gsap.registerPlugin(ScrollTrigger, SplitText, TextPlugin);

const InitLogic = () => {
  const historyTimeline = [
    {
      title: "The Visionary Engineer",
      description:
        "“In 1931, Ferdinand Porsche founded a firm built on innovation and driven by passion.”",
    },
    {
      title: "The First Porsche Legend",
      description:
        "“In 1948, Ferry Porsche built the 356, the first Porsche born from pure passion.”",
    },
    {
      title: "The Designer of Legends",
      description:
        "“In 1963, Butzi Porsche shaped the 911, defining timeless performance.”",
    },
    {
      title: "Porsche in the Spotlight",
      description:
        "“In 1970,  Porsche ignited the world’s tracks; performance pulsed in its DNA.”",
    },
    {
      title: "Breaking Boundaries",
      description:
        "“In 1986, the 959 fused technology and speed, redefining every limit.”",
    },
    {
      title: "A New Era (2000s)",
      description:
        "“In 2002, Porsche entered new roads, blending sport and daily life seamlessly.”",
    },
  ];

  //=====================================================================================

  useGSAP(() => {
    //ScrollTrigger
    gsap.to(".homepageContent", {
      scrollTrigger: {
        trigger: ".homepageHero",
        start: "bottom 100%",
        end: "bottom 65%",
        scrub: 0.5,
      },
      backgroundColor: "white",
      duration: 1,
    });
    gsap.fromTo(
      ".section__about",
      { backgroundColor: "black", color: "white" },
      {
        scrollTrigger: {
          trigger: ".homepageHero",
          start: "bottom 100%",
          end: "bottom 65%",
          scrub: 0.5,
        },
        backgroundColor: "white",
        color: "black",
        duration: 1,
      }
    );
    gsap.fromTo(
      ".homepageHero",
      { opacity: 1 },
      {
        scrollTrigger: {
          trigger: ".homepageHero",
          start: "bottom 100%",
          end: "bottom 60%",
          scrub: 1,
        },
        opacity: 0,
        filter: "blur(5px)",
        backgroundPositionY: window.innerWidth < 1024 ? "80%" : "300%",
      }
    );
    gsap.fromTo(
      ".homepageHero__videoBG",
      { opacity: 1 },
      {
        scrollTrigger: {
          trigger: ".homepageHero",
          start: "bottom 100%",
          end: "bottom 60%",
          scrub: 1,
        },
        opacity: 0,
        filter: "blur(5px)",
        y: "-10%",
      }
    );
    gsap.fromTo(
      ".aboutText1",
      { y: -700 },
      {
        scrollTrigger: {
          trigger: ".homepageHero",
          start: "bottom 60%",
          end: "100% -30%",
          scrub: 0.4,
        },
        y: 250,
      }
    );
    gsap.fromTo(
      ".aboutText1",
      { opacity: 0 },
      {
        scrollTrigger: {
          trigger: ".homepageHero",
          start: "bottom 60%",
          end: "100% top",
          scrub: 0.4,
        },
        opacity: 1,
      }
    );
    gsap.fromTo(
      ".aboutImage1",
      { y: -500, opacity: 0 },
      {
        scrollTrigger: {
          trigger: ".homepageHero",
          start: "bottom 60%",
          end: "100% -30%",
          scrub: 0.4,
        },
        y: 250,
        opacity: 1,
      }
    );
    gsap.fromTo(
      ".innerAboutImage1",
      { width: "90%" },
      {
        scrollTrigger: {
          trigger: ".homepageHero",
          start: "bottom 60%",
          end: "100% -30%",
          scrub: 0.4,
        },
        width: "100%",
      }
    );

    //Container2
    gsap.fromTo(
      ".aboutContainer2",
      { y: 100, opacity: 0, zIndex: 1 },
      {
        scrollTrigger: {
          trigger: ".aboutContainer2",
          start: "top 75%",
          end: "top center",
          scrub: 0.4,
        },
        y: 150,
        opacity: 1,
      }
    );
    gsap.fromTo(
      ".innerAboutImage2",
      { width: "95%" },
      {
        scrollTrigger: {
          trigger: ".aboutContainer2",
          start: "top 75%",
          end: "top center",
          scrub: 0.4,
        },
        width: "100%",
      }
    );
    gsap.fromTo(
      ".aboutText2",
      { y: 150, opacity: 0 },
      {
        scrollTrigger: {
          trigger: ".aboutContainer2",
          start: "top center",
          end: "bottom 50%",
          scrub: 0.4,
        },
        y: 0,
        opacity: 1,
      }
    );
    gsap.fromTo(
      ".aboutVideo",
      { y: 20 },
      {
        scrollTrigger: {
          trigger: ".aboutVideo",
          start: "bottom bottom",
          end: "bottom top",
          scrub: 0.4,
        },
        y: 50,
      }
    );
    gsap.fromTo(
      ["body", ".section__about"],
      { backgroundColor: "white" },
      {
        scrollTrigger: {
          trigger: ".section__about",
          start: "bottom top",
          end: "top bottom",
          scrub: 0.4,
        },
        backgroundColor: "black",
      }
    );

    gsap.fromTo(
      [".section__about", ".homepageContent"],
      { background: "white" },
      {
        scrollTrigger: {
          trigger: ".about__video",
          start: "center bottom",
          end: "end end",
          scrub: 0.4,
        },
        onStart: () => {
          ScrollTrigger.refresh();
        },
        backgroundColor: "black",
      }
    );

    gsap.to(".aboutVideo", {
      scrollTrigger: {
        trigger: ".about__video",
        start: "bottom bottom",
        end: "end end",
        scrub: 0.4,
      },
      width: "100%",
      height: "100vh",
    });
    //Fixing bug
    if (window.innerHeight > window.innerWidth) {
      gsap.to(".aboutVideo", {
        scrollTrigger: {
          trigger: ".about__video",
          start: "bottom bottom",
          end: "center end",
          scrub: 0.5,
        },
        onUpdate: () => {
          ScrollTrigger.refresh();
        },
      });
    }
    //

    gsap.to(".innerAboutImage2", {
      scrollTrigger: {
        trigger: ".innerAboutImage2",
        start: "80% bottom",
        end: "bottom start",
        scrub: 0.4,
      },
      translateY: "-15%",
    });
    // loadingScreen
    gsap.to(
      [
        ".loadingscreen__background--porsche",
        ".loading1",
        ".loading2",
        ".loading3",
        ".loading4",
      ],
      {
        x: "-100%",
        opacity: 0,
        duration: 0.3,
        delay: 0,
        ease: "power4.out",
        stagger: 0.1,
        onComplete: () => {
          gsap.to(".loadingscreen__container", {
            display: "none",
          });
        },
      }
    );

    gsap.fromTo(
      ".nav__item.nav__item--logo",
      { opacity: 0.001, y: -60 },
      {
        opacity: 1,
        y: -30,
        delay: 1,
        duration: 1,
        ease: "back.out",
      }
    );

    gsap.fromTo(
      ".nav__item--hamburger",
      { opacity: 0.01 },
      { opacity: 1, delay: 1.25, duration: 0.5 }
    );
    gsap.fromTo(
      ".article__title",
      { opacity: 0.01, y: 20 },
      { opacity: 1, y: 0, delay: 0.5, duration: 0.75 }
    );
    gsap.fromTo(
      ".article__description",
      { opacity: 0.01, y: 20 },
      { opacity: 1, y: 0, delay: 1, duration: 1 }
    );
    gsap.to(".historySection__explaination", {
      opacity: 1,
      color: "#fff",
      scrollTrigger: {
        trigger: ".historySection__explaination",
        start: "center center",
        end: "5% top",
        scrub: 1,
      },
    });
    gsap.to(".historySection__explaination", {
      scrollTrigger: {
        trigger: ".historySection__explaination",
        start: "center center",
        end: "+=4000px top",
        scrub: 1,
        pin: true,
      },
    });
    historyTimeline.forEach((element, index) => {
      // animate image zoom & fade
      gsap.to(`.historyImage${index}`, {
        scrollTrigger: {
          trigger: `.historyImage${index}`,
          start: "top 70%",
          end: "bottom top",
          scrub: 0.4,
        },
        onComplete: () => {
          ScrollTrigger.refresh();
        },
        opacity: 1,
        filter: "blur(0px)",
        width: "60%",
      });
      // set initial title & description to first timeline
      gsap.set(".historySection__title", {
        text: historyTimeline[0].title,
        opacity: 1,
      });
      gsap.set(".historySection__description", {
        text: historyTimeline[0].description,
        opacity: 1,
      });

      // change text dynamically when each image becomes active
      ScrollTrigger.create({
        trigger: `.historyImage${index}`,
        start: window.innerHeight > window.innerWidth ? "30% 70%" : "top 70%",
        end:
          window.innerHeight > window.innerWidth
            ? "bottom center"
            : "bottom top",
        scrub: 0.3,
        onEnterBack:
          index === 0
            ? () => {
                gsap.to(".section__about", {
                  backgroundColor: "#000",
                });
              }
            : undefined,
        onToggle: (self) => {
          if (self.isActive) {
            gsap.to(
              [".historySection__title", ".historySection__description"],
              {
                opacity: 0,
                duration: 0.2,
                onComplete: () => {
                  gsap.to(".historySection__title", {
                    text: element.title,
                    duration: 0.2,
                    delay: 0,
                    ease: "power2.out",
                    opacity: 1,
                  });
                  gsap.to(".historySection__description", {
                    text: element.description,
                    duration: 0.2,
                    delay: 0,
                    ease: "power2.in",
                    opacity: 1,
                  });
                },
              }
            );
          }
        },
      });
    });
    gsap.to(".historySection__historyContainer", {
      opacity: 0,
      duration: 1,
      ease: "power2.inOut",
      scrollTrigger: {
        trigger: ".historyImage5",
        start: "center center",
        end: "bottom 25%",
        scrub: 1,
      },
    });
    gsap.to(".historyPresent__presentEraImg", {
      opacity: 1,
      duration: 1,
      ease: "power2.inOut",
      scrollTrigger: {
        trigger: ".historyPresent__container",
        start: "top center",
        end: "top top",
        scrub: 1,
      },
    });
    gsap.to(".historyPresent__presentEraLogo", {
      filter: "brightness(0) invert(1) blur(0.5px)",
      opacity: 1,
      duration: 1,
      ease: "power2.inOut",
      scrollTrigger: {
        trigger: ".historyPresent__container",
        start: "top center",
        end: "top top",
        scrub: 1,
      },
    });
    gsap.to(".historyPresent__container", {
      scrollTrigger: {
        trigger: ".historyPresent__presentEraImg",
        start: "top top",
        end: "+=3000px bottom",
        scrub: 0.3,
        pin: true,
      },
    });

    gsap.to(".historyPresent__presentEraLogo", {
      filter: "brightness(0) invert(1) blur(0)",
      top: "10%",
      ease: "power4.in",
      scrollTrigger: {
        trigger: ".historyPresent__presentEraImg",
        start: "top top",
        end: "+=2000px bottom",
        scrub: 0.3,
      },
    });
    gsap.to(".historyPresent__presentEraChangingImg", {
      filter: "blur(0px)",
      ease: "power4.in",
      scrollTrigger: {
        trigger: ".historyPresent__presentEraImg",
        start: "top top",
        end: "+=2000px bottom",
        scrub: 0.3,
      },
    });
    gsap.to(".historyPresent__presentEraChangingImg", {
      opacity: 1,
      ease: "power4.in",
      scrollTrigger: {
        trigger: ".historyPresent__presentEraImg",
        start: "top top",
        end: "+=2000px bottom",
        scrub: 0.3,
      },
    });
    gsap.fromTo(
      ".historyPresent__presentEraMessage",
      { opacity: 0, y: -20 },
      {
        filter: "blur(0px)",
        ease: "power4.in",
        opacity: 1,
        y: 0,
        scrollTrigger: {
          trigger: ".historyPresent__presentEraImg",
          start: "top top",
          end: "+=2000px bottom",
          scrub: 0.3,
        },
      }
    );

    gsap.to(".historyPresent__container", {
      opacity: 0,
      filter: "blur(5px)",
      scrollTrigger: {
        trigger: ".chooseCar__container",
        start: "top bottom",
        end: "top center",
        scrub: 0.3,
      },
    });

    gsap.to(".chooseCar__openingMessage", {
      color: "#fff",
      filter: "blur(0px)",
      scrollTrigger: {
        trigger: ".chooseCar__container",
        start: "top 60%",
        end: "top top",
        scrub: 0.3,
      },
    });

    gsap.to(".chooseCar__carList", {
      opacity: 1,
      filter: "blur(0px)",
      scrollTrigger: {
        trigger: ".chooseCar__openingMessage",
        start: "top 60%",
        end: "top top",
        scrub: 0.3,
      },
    });
  }, []);

  //History section
  useGSAP(() => {
    document.fonts.ready.then(() => {
      const split = new SplitText(".historySection__headLine", {
        type: "words",
        aria: "hidden",
      });
      gsap.fromTo(
        split.words,
        { opacity: 0, y: 30 },
        {
          opacity: 1,
          y: 0,
          ease: "none",
          stagger: 0.1,
          scrollTrigger: {
            trigger: ".historySection__headLine",
            start: "bottom bottom",
            end: "center 35%",
            scrub: 0.4,
          },
        }
      );

      gsap.to(".historySection__historyHR", {
        opacity: 1,
        y: 0,
        ease: "none",
        stagger: 0.1,
        scrollTrigger: {
          trigger: ".historySection__headLine",
          start: "600% bottom",
          end: "center 20%",
          scrub: 0.4,
        },
        width: "100%",
      });
      gsap.to(".about__video", {
        opacity: 0,
        scrollTrigger: {
          trigger: ".historySection__headLine",
          start: "bottom bottom",
          end: "top 25%",
          scrub: 0.4,
        },
        onStart: () => {
          ScrollTrigger.refresh();
        },
      });
    });
  }, []);

  return <></>;
};

export default InitLogic;

image.thumb.webp.b6b9f29d11411a9a3bc123c5a2317a2b.webp

Posted

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependencies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen.

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import GSAP as shown in the Install Helper in our Learning Center : 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Posted

Hi,

 

Besides echoing the need of a minimal demo (special emphasis on minimal) I can give you a few recommendations.

 

Avoid doing this on mobile devices:

gsap.fromTo(
  ".homepageHero",
  { opacity: 1 },
  {
    scrollTrigger: {
      trigger: ".homepageHero",
      start: "bottom 100%",
      end: "bottom 60%",
      scrub: 1,
    },
    opacity: 0,
    filter: "blur(5px)",
    backgroundPositionY: window.innerWidth < 1024 ? "80%" : "300%",
  }
);

Filters are just terrible for performance, especially on small underpowered devices, so avoid that especially if you are combining it with moving the background on the same element. Never animate the trigger element of a ScrollTrigger instance, sure in this case is just the opacity and other properties that don't move the element, but if you move the same element ScrollTrigger uses as a trigger on the Y axis you could end up with unexpected results. Always use another element as the trigger.

 

You can also use GSAP MatchMedia for creating different animations for mobile and small devices:

https://gsap.com/docs/v3/GSAP/gsap.matchMedia()

 

Also never do this:

gsap.to(".aboutVideo", {
  scrollTrigger: {
    trigger: ".about__video",
    start: "bottom bottom",
    end: "center end",
    scrub: 0.5,
  },
  onUpdate: () => {
    ScrollTrigger.refresh();
  },
});

The onUpdate callback might run up to 60 times per second so this is not going to be good for performance, in this case since you have this attached to a ScrollTrigger instance with scrub it will run several times during that ScrollTrigger instance which in terms will affect the same ScrollTrigger as well. Also I saw that you have that same approach a few times in your code, you're creating a gsap.to() instance with no animations just to use ScrollTrigger, that is not needed, you can use ScrollTrigger.create() for that:

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

 

Happy Tweening!

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...