Day 5: Beginning My Animation Journey with GSAP
Today marks my fifth day of learning GSAP, and I decided to revise and combine all the concepts I've learned so far into a small project. This project includes text animations, custom cursors, SVG path animations, timeline controls, and scroll-triggered animations.
The Project Overview
The project features:
A heading with text animation that splits and animates from the middle.
A custom cursor that changes when hovering over an image.
An SVG path animation that responds to mouse movements.
A navigation menu that animates on click.
A scrolling text animation that changes direction and rotates based on scroll input.
The Code
Here's the complete code for the project:
//HTML and CSS
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GSAP Project</title>
<style>
body {
font-family: Arial, sans-serif;
}
h1 {
text-align: center;
margin-top: 50px;
}
.cursor {
width: 20px;
height: 20px;
background-color: #000;
border-radius: 50%;
position: absolute;
pointer-events: none;
transition: transform 0.3s ease;
}
#image {
width: 100px;
height: 100px;
background-color: red;
margin: 50px auto;
}
#string {
width: 100%;
height: 200px;
background-color: #f0f0f0;
}
#nav {
position: fixed;
top: 20px;
right: 20px;
}
#full {
position: fixed;
top: 0;
right: -100%;
width: 100%;
height: 100%;
background-color: #333;
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
transition: right 0.8s ease;
}
.marque {
white-space: nowrap;
overflow: hidden;
}
.marque img {
display: inline-block;
margin: 0 20px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
</head>
<body>
<h1>Hello, GSAP!</h1>
<div class="cursor"></div>
<div id="image"></div>
<div id="string"><svg width="1000" height="200"><path d="M 10 100 Q 500 100 990 100" stroke="black" stroke-width="2" fill="none" /></svg></div>
<div id="nav"><i>Menu</i></div>
<div id="full">
<i>Close</i>
<h3>Item 1</h3>
<h3>Item 2</h3>
<h3>Item 3</h3>
</div>
<div class="marque">
<img src="https://via.placeholder.com/100" alt="Image 1">
<img src="https://via.placeholder.com/100" alt="Image 2">
<img src="https://via.placeholder.com/100" alt="Image 3">
</div>
//Javascript
function breakText() {
let h1 = document.querySelector("h1");
let h1text = h1.textContent;
let splited = h1text.split("");
let halfValue = Math.floor(splited.length / 2);
let clutter = "";
splited.forEach(function (elem, idx) {
if (idx < halfValue) {
clutter += `<span class="a">${elem}</span>`;
} else {
clutter += `<span class="b">${elem}</span>`;
}
});
h1.innerHTML = clutter;
}
breakText();
gsap.from("h1 .a", {
y: 50,
duration: 0.6,
delay: 0.5,
stagger: 0.15,
opacity: 0,
});
gsap.from("h1 .b", {
y: 50,
duration: 0.6,
delay: 0.5,
stagger: -0.15,
opacity: 0,
});
// Day 2: Custom Cursor
let crs = document.querySelector(".cursor");
let main = document.querySelector("#main");
let imgDiv = document.querySelector("#image");
document.addEventListener("mousemove", function (e) {
gsap.to(crs, {
x: e.clientX,
y: e.clientY,
duration: 0.6,
});
});
imgDiv.addEventListener("mouseenter", function () {
crs.innerHTML = "View more";
gsap.to(crs, {
scale: 4,
backgroundColor: "#ffffff74",
});
});
imgDiv.addEventListener("mouseleave", function () {
crs.innerHTML = "";
gsap.to(crs, {
scale: 1,
backgroundColor: "#000",
});
});
// Day 3: SVG Path Animation
let initialValue = "M 10 100 Q 500 100 990 100";
let finalValue = "M 10 100 Q 500 100 990 100";
let string = document.querySelector("#string");
string.addEventListener("mousemove", function (dets) {
initialValue = `M 10 100 Q ${dets.clientX} ${dets.clientY} 990 100`;
gsap.to("svg path", {
attr: { d: initialValue },
duration: 0.2,
ease: "power3.out",
});
});
string.addEventListener("mouseleave", function () {
gsap.to("svg path", {
attr: { d: finalValue },
duration: 1,
ease: "elastic.out(1, 0.2)",
});
});
// Day 4: Navigation Menu Animation
let navbar = document.querySelector("#nav i");
let icon = document.querySelector("#full i");
let tl = gsap.timeline();
tl.to("#full", { right: 0, duration: 0.8 });
tl.from("#full h3", {
x: 150,
duration: 0.5,
stagger: 0.1,
opacity: 0,
});
tl.from("#full i", { opacity: 0, x: 150 });
tl.pause();
navbar.addEventListener("click", function () {
tl.play();
});
icon.addEventListener("click", function () {
tl.reverse();
});
// Day 4: Scroll-Triggered Animation
window.addEventListener("wheel", function (dets) {
if (dets.deltaY > 0) {
gsap.to(".marque", {
transform: "translateX(-200%)",
duration: 6,
repeat: -1,
ease: "none",
});
gsap.to(".marque img", { rotate: 180 });
} else {
gsap.to(".marque", {
transform: "translateX(0%)",
duration: 6,
repeat: -1,
ease: "none",
});
gsap.to(".marque img", { rotate: 0 });
}
});
Explanation
Text Animation (Day 1):
The
breakText
function splits the text of the<h1>
element into individual characters and wraps them in<span>
elements with classes "a" and "b".GSAP animates the characters from the bottom with a staggered effect, creating a dynamic text animation.
Custom Cursor (Day 2):
The cursor follows the mouse movement using GSAP.
When hovering over the image, the cursor scales up and changes color, displaying "View more".
SVG Path Animation (Day 3):
The SVG path animates based on the mouse position, creating a wavy line effect.
When the mouse leaves the SVG area, the path smoothly returns to its original shape.
Navigation Menu Animation (Day 4):
A GSAP timeline animates the navigation menu when clicking the "Menu" icon.
The menu slides in, and its items fade and slide into view.
Clicking the "Close" icon reverses the animation, hiding the menu.
Scroll-Triggered Animation (Day 4):
The text and images in the marquee element scroll horizontally based on the user's scroll direction.
The images rotate 180 degrees when scrolling down and revert to their original position when scrolling up.
Conclusion
Combining all the concepts from the first four days, I created a small project that showcases the versatility and power of GSAP. This project includes text animations, custom cursors, SVG path animations, timeline controls, and scroll-triggered animations, providing a rich interactive experience. I'm excited to continue exploring GSAP and creating more complex animations in the future!
Subscribe to my newsletter
Read articles from Saksham basnet directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Saksham basnet
Saksham basnet
I am a Frontend Developer From Nepal ꔪ