Hi good people,
I have spend lots of time searching, and trying to figure this one out by googling and fixing my code with various patches but I can't seem to fix the issue.
I have a portfolio website that I am building in nextJS:
https://markomalec.com
The problem I am having is that on every iPhone I tried my website on, as soon as I get to the "vertical timeline" part under the hero section, website starts lagging and stuttering hard.
The same sometimes happens on firefox on Android (I have s22 ultra).
I have tried several fixes and the last one I tried is adding a slight rotation to the animation. I have read it on another post that it might resolve the issue but it didn't.
I also tried removing everything from the DOM except the line that has scaleY.
Line does NOT have any shadow or anything and also it does have will-change in CSS.
I know you GSAP pros are asking for minimal demo and such, but I was perhaps hoping that showing a component where gsap is invoked with the website being live, you could see what is going on.
import React, { useLayoutEffect, useRef } from "react";
import { ExperienceType } from "~/types";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
interface ExperienceProps {
data: ExperienceType[];
}
const VerticalTimeline = ({ data }: ExperienceProps) => {
const lineRef = useRef(null);
const horizontalLine = useRef(null);
const timelineRef = useRef(null);
useLayoutEffect(() => {
const ctx = gsap.context(() => {
const tl = gsap.timeline({
scrollTrigger: {
trigger: timelineRef.current,
start: "100 60%",
end: "bottom 60%",
scrub: 2,
},
});
tl.to(lineRef.current, {
duration: 2,
scaleY: 1,
rotate: 0.1,
ease: "none",
transformOrigin: "top",
});
gsap.set(".timeline-entry", { opacity: 0 });
const timelineBoxes = gsap.utils.toArray(".timeline-entry") as Element[];
timelineBoxes.forEach((timelineBox) => {
gsap.to(timelineBox, {
opacity: 1,
scrollTrigger: {
trigger: timelineBox,
start: "100 60%",
toggleActions: "play resume none none",
},
});
});
}, timelineRef);
return () => ctx.revert();
}, []);
return (
<div className="timeline-section">
<div className="timeline-container" ref={timelineRef}>
<div className="guide-line" />
<div className="thin-line" ref={lineRef} />
{data.map((item, index: React.Key | null | undefined) => (
<div key={index} className={`timeline-entry`}>
<div className="cube_wrapper">
<div className="box">
<div className={`cube ${item.company}`}>
<div className="front" />
<div className="back" />
<div className="right" />
<div className="left" />
<div className="top" />
<div className="bottom" />
</div>
</div>
</div>
<div className="text-box">
<h4>{item.company}</h4>
<p className="date">{item.timeframe}</p>
<p className="skill_description">{item.description}</p>
<div className="skills_used">
{item.skills.split(", ").map((skill, i) => (
<span key={i}>{skill}</span>
))}
</div>
</div>
</div>
))}
<div className="horizontal-line" ref={horizontalLine} />
</div>
</div>
);
};
export default React.memo(VerticalTimeline);
Any help would be much apperciated, as I am struggling with this one for quite a while now.
Thanks GSAP-ers :)