Scrollytelling with GSAP MotionPath and ScrollTrigger

Let's use greensock's GSAP MotionPath and ScrollTrigger to do some scrollytelling! This tutorial/cloneable highlights a trek up Mount Shasta I did many years ago. The lower-thirds titles were done with Webflow IX2 - who says GSAP and IX2 can't get along?

Watch the Tutorial on YouTubeGet the Project Cloneable

Inside <head> tag

<script defer src=""></script>
<script defer src=""></script>
<script defer src=""></script>

Inside </body> tag

function init() {
  gsap.registerPlugin(MotionPathPlugin, ScrollTrigger);

  // animate .circle along #mountain-path"#circle", {
    motionPath: {
      path: "#mountain-path",
      align: "#mountain-path", // magically align .circle to #mountain-path
      alignOrigin: [0.5, 0.5], // align to .circle center
      autoRotate: true // n/a for a circle
    scrollTrigger: {
      trigger: ".track",
      start: "top top", // when top of .track is at top of viewport
      end: "bottom bottom", // when bottom of .track is at bottom of viewport
      scrub: 1 // connect it to scroll.
    ease: "none"

  // move .image-wrap so that it follows .circle.
  // use ticker.add for each animation frame
  // use a animation set .image-wrap position based on .circle's coordinates
  gsap.ticker.add(() =>".image-wrap", {
      duration: 0.5,
      x: -gsap.getProperty(".circle", "x"),
      y: -gsap.getProperty(".circle", "y")

  //center the wrapper using left and top on inital load and any resize
  window.onload = window.onresize = () => {
    gsap.set(".image-wrap", {
      left: window.innerWidth / 2,
      top: window.innerHeight / 2

// run when DOM and scripts have loaded.
document.addEventListener("DOMContentLoaded", init);