<h1 class="header-section">Scroll to see a timeline animation</h1>
<svg id="svg-stage" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 1200">
<path class="line01 line" d="M 10 200 600 200" ></path>
<path class="line02 line" d="M 10 400 600 400" ></path>
<path class="line03 line" d="M 10 600 600 600" ></path>
<path class="line04 line" d="M 10 800 600 800" ></path>
<path class="line05 line" d="M 10 1000 600 1000" ></path>
<text class="text01" x="30" y="190">2018</text>
<text class="text02" x="30" y="390">2019</text>
<text class="text03" x="30" y="590">2020</text>
<path class="theLine"
d="M -5,0
Q 450 230 300 450
T 130 750
Q 100 850 300 1000
T 150 1200"
fill="none" stroke-width="10px" />
<circle class="ball ball01" r="20" cx="50" cy="100"></circle>
<circle class="ball ball02" r="20" cx="278" cy="201"></circle>
<circle class="ball ball03" r="20" cx="327" cy="401"></circle>
<circle class="ball ball04" r="20" cx="203" cy="601"></circle>
</svg>
@font-face {
font-display: block;
font-family: Mori;
font-style: normal;
font-weight: 400;
src: url(https://assets.codepen.io/16327/PPMori-Regular.woff) format("woff");
}
body {
--light: #fffce1;
width: 100%;
height: 400vh;
background: #0e100f;
color: var(--light);
font-family: "Mori", sans-serif;
}
.header-section {
position: relative;
text-align: center;
margin: 100px auto 0;
}
#svg-stage {
max-width: 600px;
overflow: visible;
margin-top: 60vh;
}
.ball {
fill: var(--light);
visibility: hidden;
}
.line {
fill: none;
stroke: var(--light);
stroke-width: 2px;
}
text {
fill: var(--light);
font-size: 15px;
visibility: hidden;
}
.theLine {
stroke: var(--light);
}
console.clear();
gsap.registerPlugin(ScrollTrigger, DrawSVGPlugin, MotionPathPlugin);
gsap.defaults({ ease: "none" });
const pulses = gsap
.timeline({
defaults: {
duration: 0.05,
autoAlpha: 1,
scale: 2,
transformOrigin: "center",
ease: "elastic(2.5, 1)"
}
})
.to(".ball02, .text01", {}, 0.2)
.to(".ball03, .text02", {}, 0.33)
.to(".ball04, .text03", {}, 0.46);
const main = gsap
.timeline({
defaults: { duration: 1 },
scrollTrigger: {
trigger: "#svg-stage",
scrub: true,
start: "top center",
end: "bottom center"
}
})
.to(".ball01", { duration: 0.01, autoAlpha: 1 })
.from(".theLine", { drawSVG: 0 }, 0)
.to(
".ball01",
{
motionPath: {
path: ".theLine",
align: ".theLine",
alignOrigin: [0.5, 0.5]
}
},
0
)
.add(pulses, 0);
// 💚 This just adds the GSAP link to this pen, don't copy this bit
import { GSAPInfoBar } from "https://codepen.io/GreenSock/pen/vYqpyLg.js";
new GSAPInfoBar({ link: "https://gsap.com/docs/v3/Plugins/ScrollTrigger/" });
// 💚 Happy tweening!
This Pen doesn't use any external CSS resources.