I created a website in Next.JS. I used the Pin plugin from GSAP. On the Desktop version of the Webiste the images and the text are performant and there is no lag at all. When I switch to the Mobile Version then the images and the text lag behind. (it is even more noticeable on the phone) What causes the GSAP Performance differences between Desktop and Mobile and could Next.JS be causing the problem? Link to Demo: https://artist-website-seven.vercel.app/
I tried using fromTo rather than pin, but this created it's own seperate problems.
First Component:
"use client";
import React, { useLayoutEffect } from "react";
import clsx from "clsx";
import Image from "next/image";
import BackgroundImage from "./BackgroundImage";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { SparklesCore } from "../components/ui/sparkles";
import { Nunito } from "next/font/google";
export const title = Nunito({
subsets: ["latin"],
weight: ["600"],
});
gsap.registerPlugin(ScrollTrigger);
const LandingPage = () => {
useLayoutEffect(() => {
gsap.to("#pinSection", {
y: 0,
scrollTrigger: { pin: "#pinSection", start: "top top", end: "+=1000" },
});
}, []);
return (
<main id="pinSection">
<SparklesCore
background="transparent"
minSize={0.4}
maxSize={3}
particleDensity={10}
className="w-full h-full -z-50 absolute"
particleColor="#FFFFFF"
/>
<BackgroundImage
source="/images/test1.jpg"
x={1}
y={1}
id="image6"
start="+=100"
zIndex="-z-10"
/>
<BackgroundImage
source="/images/test2.jpg"
x={-70}
y={-150}
id="image5"
start="+=20"
zIndex="z-0"
/>
<BackgroundImage
source="/images/test3.jpg"
x={-50}
y={-19}
id="image1"
start="+=15"
zIndex="-z-10"
/>
<BackgroundImage
source="/images/test4.jpg"
x={99}
y={80}
id="image2"
start="+=30"
zIndex="-z-10"
/>
<BackgroundImage
source="/images/test5.jpg"
x={39}
y={-80}
id="image8"
start="+=0"
zIndex="-z-10"
/>
<BackgroundImage
source="/images/test6.jpg"
x={50}
y={70}
id="image7"
start="+=40"
zIndex="-z-10"
/>
<BackgroundImage
source="/images/test7.jpg"
x={80}
y={-150}
id="image3"
start="+=20"
zIndex="z-0"
/>
<BackgroundImage
source="/images/test8.jpg"
x={-80}
y={100}
id="image4"
start="+=15"
zIndex="-z-10"
/>
<section className="h-screen w-screen flex justify-center items-center">
<h1
className={clsx("text-5xl lg:text-[10rem] md:text-[8rem] xl:text-[13rem]", title.className)}
id="heroTitle"
>
HEADDING
</h1>
</section>
</main>
);
};
export default LandingPage;
Second Component:
"use client";
import Image from "next/image";
import React, { useLayoutEffect, useState } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import clsx from "clsx";
gsap.registerPlugin(ScrollTrigger);
interface BackgroundImageProps {
source: string;
x: number;
y: number;
id: string;
start: string;
zIndex: string;
}
const BackgroundImage = ({ source, y, x, id, start, zIndex }: BackgroundImageProps) => {
useLayoutEffect(() => {
gsap.fromTo(
`#${id}IMAGE`,
{ scale: 1.5 },
{
scale: 1,
duration: 2.5,
ease: "cubic-bezier(0.17, 0.67, 0.83, 0.67)"
}
);
gsap.fromTo(
`.${id}`,
{ scale: .5 },
{
scale: 1,
duration: 1,
ease: "cubic-bezier(0.17, 0.67, 0.83, 0.67)"
}
);
}, []);
const [windowWidth, setWindowWidth] = useState(0);
useLayoutEffect(() => {
const updateWidth = () => {
setWindowWidth(window.innerWidth);
};
updateWidth();
window.addEventListener("resize", updateWidth);
return () => window.removeEventListener("resize", updateWidth);
}, []);
useLayoutEffect(() => {
if (windowWidth === 0) return;
if (windowWidth < 500) {
gsap.fromTo(
`.${id}`,
{ x: x, y: y, opacity: 1 },
{
x: x * 10,
y: y * 10,
opacity: 0,
scrollTrigger: {
start: start,
end: "+=1000",
scrub: true,
},
}
);
} else if (windowWidth < 1024) {
gsap.fromTo(
`.${id}`,
{ x: x * 3, y: y * 1, opacity: 1 },
{
x: x * 10,
y: y * 10,
opacity: 0,
scrollTrigger: {
start: start,
end: "+=1000",
scrub: true,
},
}
);
} else {
gsap.fromTo(
`.${id}`,
{ x: x * 6, y: y * 1.7, opacity: 1 },
{
x: x * 10,
y: y * 10,
opacity: 0,
scrollTrigger: {
start: start,
end: "+=1000",
scrub: true,
},
}
);
}
}, [windowWidth]);
return (
<div className={clsx("h-screen w-screen absolute flex items-center justify-center", zIndex)}>
<div
className={clsx(
"h-44 w-32 relative overflow-hidden rounded-md sm:h-60 sm:w-52 lg:h-96 lg:w-80 drop-shadow-glow",
id
)}
>
<Image
src={source}
alt="missing Background Image"
objectFit="cover"
layout="fill"
id={id + "IMAGE"}
/>
</div>
</div>
);
};
export default BackgroundImage;