feat: Implement Animations for landing page
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user