1
0

feat: Implement Animations for landing page

This commit is contained in:
2026-03-04 15:49:53 +01:00
parent f8065f06cd
commit 7f44ed1112
10 changed files with 768 additions and 347 deletions
+79 -2
View File
@@ -47,7 +47,7 @@ const services: Array<ComponentProps<typeof ServicesCard>> = [
</p>
</div>
<ul>
<ul class="cards">
{services.map((service) => <ServicesCard {...service} />)}
</ul>
</div>
@@ -86,7 +86,7 @@ const services: Array<ComponentProps<typeof ServicesCard>> = [
}
}
ul {
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
@@ -98,3 +98,80 @@ const services: Array<ComponentProps<typeof ServicesCard>> = [
margin-top: 7rem;
}
</style>
<script>
import { gsap } from "gsap";
import { SplitText } from "gsap/SplitText";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(SplitText);
gsap.registerPlugin(ScrollTrigger);
const servicesSection = document.querySelector(".services");
if (servicesSection) {
const tl = gsap.timeline({
scrollTrigger: {
trigger: servicesSection,
start: "top 60%",
},
});
tl.addLabel("heading", 0);
tl.addLabel("text", 0.3);
tl.addLabel("cards", 0.8);
new SplitText(servicesSection.querySelector("h2"), {
type: "words, chars",
autoSplit: true,
mask: "chars",
charsClass: "char",
onSplit: (self) => {
tl.from(
self.chars,
{
duration: 1,
yPercent: -120,
scale: 1.2,
stagger: 0.015,
ease: "expo.out",
onComplete: () => self.revert(),
},
"heading",
);
},
});
new SplitText(servicesSection.querySelector("p"), {
type: "lines, words",
autoSplit: true,
mask: "lines",
linesClass: "line",
onSplit: (self) => {
tl.from(
self.lines,
{
duration: 1.5,
yPercent: 105,
stagger: 0.06,
ease: "expo.out",
onComplete: () => self.revert(),
},
"text",
);
},
});
tl.from(
servicesSection.querySelectorAll(".cards > *"),
{
duration: 1,
opacity: 0,
yPercent: 5,
stagger: 0.15,
ease: "expo.out",
},
"cards",
);
}
</script>