We’ve been exploring GSAP (GreenSock Animation Platform) lately and wanted to share a breakdown of a recent project. If you’re new to GSAP, this project is a great way to get started with scroll-based animations!
What We’re Building
We’ll create a scroll-driven day-to-night transition using SVG elements. The animation will include:
- Sun and Moon following a curved path as you scroll.
- Sky changing colours to simulate day and night.
- Stars appearing as the night sets in.
- Text changes that animate based on the time of day.
1. Setting Up the HTML and CSS
First, let’s set up a basic HTML structure. We’ll include SVG elements for the sun, moon, and a path they’ll follow. We’ll also add a sky background and some stars.
<section class="container">
<!-- Background sky div that changes color to simulate day and night -->
<div class="sky"></div>
<!-- SVG containing the sun, moon, and the path they will follow -->
<svg class="circle-svg" viewBox="0 0 550 300">
<!-- A path that defines the trajectory for the sun and moon animations -->
<path class="circle-path" d="M 550 300 a 10 10 0 0 0 -550 0" fill="transparent"/>
<!-- The sun element, initially positioned at (40, 40) -->
<circle fill="#FDCA48" class="sun" cx="40" cy="40" r="40"></circle>
<!-- The moon element, also initially positioned at (40, 40) -->
<circle fill="#FFEFC4" class="moon" r="40" cx="40" cy="40"></circle>
</svg>
<!-- Container for stars that appear during the night -->
<div class="stars">
<!-- Individual star elements that are hidden initially -->
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
</div>
<!-- "HELLO WORLD!" text displayed during the day -->
<h1 class="hello-world"><span>HELLO WORLD!</span></h1>
<!-- "BYE WORLD!" text displayed during the night -->
<h1 class="bye-world"><span>BYE WORLD!</span></h1>
<!-- Grass element that stays at the bottom of the screen -->
<div class="grass"></div>
</section>
Next, some basic CSS to style our elements. We position the sky, stars, sun, and moon and set up classes for our text.
html, body, * {
margin: 0;
padding: 0;
}
.container {
height: 100vh;
.sky {
background-color: #B7F2FF;
height: 100vh;
width: 100%;
position: fixed;
top: 0;
}
.sun, .moon {
opacity: 0;
}
.stars {
position: fixed;
top: 0;
height: 80vh;
width: 100%;
.star {
background-color: #FFEFC4;
border-radius: 100px;
display: none;
height: 15px;
width: 15px;
position: absolute;
z-index: 10;
animation: pulsate 2s linear infinite;
&:nth-child(1) {
top: 20%;
left: 5%;
transform: translate(-5%, -20%);
}
&:nth-child(2) {
display: none;
top: 67%;
left: 20%;
transform: translate(-20%, -67%);
}
&:nth-child(3) {
display: none;
top: 35%;
left: 37%;
transform: translate(-37%, -35%);
}
&:nth-child(4) {
display: none;
top: 75%;
left: 70%;
transform: translate(-70%, -75%);
}
&:nth-child(5) {
display: none;
top: 30%;
left: 90%;
transform: translate(-30%, -90%);
}
}
}
h1 {
display: inline-block;
font-family: "Inter", sans-serif;
font-size: 0;
font-weight: 400;
position: fixed;
top: 68%;
left: 50%;
transform: translate(-50%, -68%);
opacity: 0;
white-space: nowrap;
span {
font-size: 50px;
}
&.hello-world {
color: #000;
}
&.bye-world {
color: #fff;
}
}
.grass {
background-color: #065C19;
height: 20vh;
width: 100%;
position: fixed;
bottom: 0;
}
}
.fade-in {
animation: fadeIn 0.25s forwards;
}
.fade-out {
animation: fadeOut 0.25s forwards;
}
@keyframes fadeIn {
0% {
opacity: 0;
} 100% {
opacity: 1;
}
}
@keyframes fadeOut {
0% {
opacity: 1;
} 100% {
opacity: 0;
}
}
@keyframes pulsate {
0% {
opacity: 100%;
}
50% {
opacity: 25%;
scale: 0.9;
}
100% {
opacity: 100%
}
}
2. Bringing the Animation to Life with GSAP
Now that we have the structure in place, let’s animate it! We’ll use GSAP’s ScrollTrigger
and MotionPathPlugin
to animate the sun and moon based on scroll position.
gsap.registerPlugin(ScrollTrigger, MotionPathPlugin, DrawSVGPlugin);
We need to register the plugins we’re using: ScrollTrigger
for scroll-based animations, MotionPathPlugin
for moving elements along paths, and DrawSVGPlugin
to animate SVG paths.
3. Setting Up the Scroll Trigger and Timeline
The core of the animation happens in our timeline (tl2
). We set up ScrollTrigger
to pin the SVG element and control the animation based on scroll position.
var tl2 = gsap.timeline({
scrollTrigger: {
trigger: ".circle-svg",
scrub: 1, // Smooth scrolling effect
pin: true, // Pin the element during scroll
start: "center center", // Start when the SVG reaches the center of the viewport
end: "+=3000", // Animation length
}
});
-
trigger
: The SVG that controls when the animation starts. -
scrub
: Links animation progress to the scroll position. -
pin
: Keeps the SVG in place as the user scrolls. -
start
andend
: Define when the animation starts and how long it lasts.
4. Animating the Sun and Moon
Next, we move the sun along the path using the motionPath
property. This makes the sun follow the curve we set in the SVG path.
tl2.from(".circle-path", {drawSVG: 0}) // Draw the path as we scroll
.to(".sun", {
motionPath: {
path: ".circle-path", // The path to follow
align: ".circle-path", // Align the element along the path
alignOrigin: [0.5, 0.25], // Adjust alignment
start: 0,
end: 0.2, // Moves the sun a small distance initially
},
duration: 0.2
})
Here’s what’s happening:
- The path is drawn with
drawSVG
as the user scrolls. - The sun moves a small distance along the path to simulate sunrise.
We then continue the animation by moving the sun further along the path, changing the sky’s color, and gradually revealing stars.
.to(".sky", { backgroundColor: "#7A3BFF" }) // Change sky color to night
.to(".star:nth-child(3)", { display: "block" }, 2) // Show stars one by one
5. Handling the Moon and Text Animations
Once the sun sets, the moon rises following the same path, and the text changes based on scroll direction.
.to(".moon", {
motionPath: {
path: ".circle-path",
align: ".circle-path",
alignOrigin: [0.5, 0.25],
start: 0,
end: 0.2
},
duration: 0.2
})
.add(() => {
if (tl2.scrollTrigger.direction === -1) {
byeAnimation.reverse();
} else {
byeAnimation.play();
}
}, "<");
The moon animation is set up similarly to the sun. The timeline checks the scroll direction to determine which text message to display, playing or reversing the animation based on the scroll.
Final Touches
We tie everything together by animating additional stars, adding a grass element that rises, and fine-tuning timing and effects. It’s all about playing around with GSAP’s powerful timeline and animation controls
Wrapping Up
This project was a fun way to get familiar with GSAP’s capabilities. If you’re trying it out, start small and experiment with different properties and plugins. It’s amazing how much you can create with just a few lines of code!
Feel free to ask questions if you want to learn more about GSAP or how I set up the animations. For more industry insights and the latest updates from our agency, be sure to visit Toru Digital's Insights.
See demo here
Top comments (0)