Search code examples
javascriptgsapscrolltrigger

Parallax effect within pinned GSAP container


I have a block which becomes pinned and scrolls horizontally.

Within this block, I have a vector which has a width of 3573px.

When a user scrolls horizontally, I want the vector to scroll also, alongside the images in my demo.

Have tried moving my vector under .horizontalScroller__scroll, so that it scrolls alongside the images, but that didn't work.

See demo:

$(function() {

  let images = gsap.utils.toArray(".horizontalScroller__item");

  gsap.to(images, {
    xPercent: -100 * (images.length - 1),
    ease: "none",
    scrollTrigger: {
      trigger: ".horizontalScroller",
      pin: true,
      scrub: 1,
      end: "+=3600", // size of svg bg
      //end: () => "+=" + document.querySelector(".horizontalScroller__images").offsetWidth
    }
  });

});
.spacer {
  height: 100vh;
  background: lightblue;
}

.horizontalScroller {
  padding: 100px 0 60px 0;
  background-color: #5D209F;
  height: 100vh;
  position: relative;
  overflow: hidden;
}
.horizontalScroller__intro {
  margin-bottom: 25px;
}
.horizontalScroller__scroll {
  height: 70%;
  position: relative;
  overflow: hidden;
}
.horizontalScroller__images {
  display: flex;
  align-items: center;
  position: relative;
  z-index: 1;
}
.horizontalScroller__item {
  width: 50vw;
  display: flex;
  justify-content: center;
  flex: 0 0 auto;
}
.horizontalScroller__image {
  -o-object-fit: fill;
  object-fit: fill;
  margin: 0 auto;
  width: 260px;
  height: 255px;
}
.horizontalScroller__pattern {
  position: absolute;
  top: -50%;
  width: 100%;
  height: 100%;
}
.horizontalScroller__pattern-inner {
  height: 100%;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/ScrollTrigger.min.js"></script>

<section class="spacer"></section>

<section class="horizontalScroller">

  <div class="container">
    <div class="row justify-content-center">
      <div class="col-12 col-md-8">
        <div class="horizontalScroller__intro text-center">
          <h2 class="horizontalScroller__header">Header</h2>
        </div>
      </div>
    </div>
  </div>

  <div class="horizontalScroller__scroll">
    <div class="horizontalScroller__images" id="horizontal-scroll">
      <div class="horizontalScroller__item">
        <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
      </div>
      <div class="horizontalScroller__item">
        <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
      </div>
      <div class="horizontalScroller__item">
        <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
      </div>
      <div class="horizontalScroller__item">
        <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
      </div>
    </div>

  </div>

  <div class="horizontalScroller__pattern">
    <div class="horizontalScroller__pattern-inner">
      <svg class="horizontalScroller__pattern-svg" xmlns="http://www.w3.org/2000/svg" width="3573.448" height="935.115" viewBox="0 0 3573.448 935.115">
        <g id="Journey_line" data-name="Journey line" transform="translate(58.751 66.918)">
          <path id="Path_111603" data-name="Path 111603" d="M-57.191,807.764c141.061,46.335,271.1-48.506,208.8-171.343-44.647-88.041-84.385,2.223-76.906,70.2,11.034,100.3,75.906,190.808,216.669,143.778C406.3,812,470.169,700.216,568.892,676.505c94.985-22.813,137.722,77.422,240.409,77.422,189.877,0,202.929-186.737,384.8-145.215,70.851,16.176,119.356,96.77,315.333,91.709,108.733-2.808,183.293-179.6,324.1-222.009,136.412-41.091,145.842,55.306,290.03,55.078,221.015-.348,232.464-251.918,446.846-265.314,144.5-9.029,229.247,90.469,364.966-54.532,26.116-27.9,52.772-44.257,77.079-53.559,38.931-14.9,81.644-13.148,119.848,3.795,52.233,23.165,142.179,57.218,225.578-44.538C3456.26-.7,3510.921-63.64,3510.921-63.64" fill="none" stroke="rgba(249,247,250,0.3)" stroke-miterlimit="10" stroke-width="10" />
          <path class="pulse" id="Path_111604" data-name="Path 111604" d="M1922.219,474.558a33.6,33.6,0,1,1-33.6-33.6,33.6,33.6,0,0,1,33.6,33.6" fill="#5d209f" />
          <path class="pulse" id="Path_111605" data-name="Path 111605" d="M1908.09,474.558a19.475,19.475,0,1,1-19.476-19.476,19.476,19.476,0,0,1,19.476,19.476" fill="#f6eb61" />
          <path class="pulse" id="Path_111606" data-name="Path 111606" d="M1056.355,649.037c0-19.115-15.045-34.611-33.6-34.611s-33.6,15.5-33.6,34.611,15.045,34.611,33.6,34.611,33.6-15.5,33.6-34.611" fill="#5d209f" />
          <path class="pulse" id="Path_111607" data-name="Path 111607" d="M1042.226,649.037c0-11.078-8.719-20.059-19.476-20.059s-19.475,8.981-19.475,20.059,8.719,20.059,19.475,20.059,19.476-8.981,19.476-20.059" fill="#f277c6" />
          <path class="pulse" id="Path_111610" data-name="Path 111610" d="M623.423,672.044c0-18.834-15.045-34.1-33.6-34.1s-33.6,15.268-33.6,34.1,15.045,34.1,33.6,34.1,33.6-15.268,33.6-34.1" fill="#5d209f" />
          <path class="pulse" id="Path_111611" data-name="Path 111611" d="M609.294,672.044a19.478,19.478,0,1,0-19.476,19.764,19.621,19.621,0,0,0,19.476-19.764" fill="#ff6d6a" />
          <path class="pulse" id="Path_111608" data-name="Path 111608" d="M2355.151,439.3a33.6,33.6,0,1,0-33.6,33.6,33.6,33.6,0,0,0,33.6-33.6" fill="#5d209f" />
          <path class="pulse" id="Path_111609" data-name="Path 111609" d="M2341.022,439.3a19.475,19.475,0,1,0-19.476,19.476,19.476,19.476,0,0,0,19.476-19.476" fill="#ff6d6a" />
        </g>
      </svg>

    </div>
  </div>

</section>

<section class="spacer"></section>


Solution

  • Where you have

    <div class="horizontalScroller__pattern">
    

    add horizontalScroller__SVG to it:

    <div class="horizontalScroller__pattern horizontalScroller__SVG">
    

    Add the following code:

    let svgBG = gsap.utils.toArray(".horizontalScroller__SVG");
    
    gsap.to(svgBG, {
     xPercent: -100,
     ease: "none",
     scrollTrigger: {
      trigger: ".horizontalScroller",
      pin: true,
      scrub: 1,
      end: "+=7200",
      //end: () => "+=" + document.querySelector(".horizontalScroller__images").offsetWidth
    }
    });
    

    You will need to fiddle with the +7200 number until you get the desire result.

    $(function() {
    
      let images = gsap.utils.toArray(".horizontalScroller__item");
    
      gsap.to(images, {
        xPercent: -100 * (images.length - 1),
        ease: "none",
        scrollTrigger: {
          trigger: ".horizontalScroller",
          pin: true,
          scrub: 1,
          end: "+=3600", // size of svg bg
          //end: () => "+=" + document.querySelector(".horizontalScroller__images").offsetWidth
        }
      });
      
      let svgBG = gsap.utils.toArray(".horizontalScroller__svg");
    
      gsap.to(svgBG, {
        xPercent: -100,
        ease: "none",
        scrollTrigger: {
          trigger: ".horizontalScroller",
          pin: true,
          scrub: 1,
          end: "+=7200",
          //end: () => "+=" + document.querySelector(".horizontalScroller__images").offsetWidth
        }
      });
    
    });
    .spacer {
      height: 100vh;
      background: lightblue;
    }
    
    .horizontalScroller {
      padding: 100px 0 60px 0;
      background-color: #5D209F;
      height: 100vh;
      position: relative;
      overflow: hidden;
    }
    .horizontalScroller__intro {
      margin-bottom: 25px;
    }
    .horizontalScroller__scroll {
      height: 70%;
      position: relative;
      overflow: hidden;
    }
    .horizontalScroller__image_item {
          width: 50vw;
          display: flex;
          justify-content: center;
          flex: 0 0 auto;
     }
    .horizontalScroller__images {
      display: flex;
      align-items: center;
      position: relative;
      z-index: 1;
    }
    .horizontalScroller__image {
      -o-object-fit: fill;
      object-fit: fill;
      margin: 0 auto;
      width: 260px;
      height: 255px;
    }
    .horizontalScroller__pattern {
      position: absolute;
      top: -50%;
      width: 100%;
      height: 100%;
    }
    .horizontalScroller__pattern-inner {
      height: 100%;
    }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/ScrollTrigger.min.js"></script>
    
    <section class="spacer"></section>
    
    <section class="horizontalScroller">
    
      <div class="container">
        <div class="row justify-content-center">
          <div class="col-12 col-md-8">
            <div class="horizontalScroller__intro text-center">
              <h2 class="horizontalScroller__header">Header</h2>
            </div>
          </div>
        </div>
      </div>
    
      <div class="horizontalScroller__scroll">
        <div class="horizontalScroller__images" id="horizontal-scroll">
          <div class="horizontalScroller__item horizontalScroller__image_item">
            <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
          </div>
          <div class="horizontalScroller__item horizontalScroller__image_item">
            <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
          </div>
          <div class="horizontalScroller__item horizontalScroller__image_item">
            <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
          </div>
          <div class="horizontalScroller__item horizontalScroller__image_item">
            <div class="horizontalScroller__image" style="background-image:url('https://picsum.photos/200/300');"></div>
          </div>
        </div>
    
      </div>
    
      <div class="horizontalScroller__svg horizontalScroller__pattern">
        <div class="horizontalScroller__pattern-inner">
          <svg class="horizontalScroller__pattern-svg" xmlns="http://www.w3.org/2000/svg" width="3573.448" height="935.115" viewBox="0 0 3573.448 935.115">
            <g id="Journey_line" data-name="Journey line" transform="translate(58.751 66.918)">
              <path id="Path_111603" data-name="Path 111603" d="M-57.191,807.764c141.061,46.335,271.1-48.506,208.8-171.343-44.647-88.041-84.385,2.223-76.906,70.2,11.034,100.3,75.906,190.808,216.669,143.778C406.3,812,470.169,700.216,568.892,676.505c94.985-22.813,137.722,77.422,240.409,77.422,189.877,0,202.929-186.737,384.8-145.215,70.851,16.176,119.356,96.77,315.333,91.709,108.733-2.808,183.293-179.6,324.1-222.009,136.412-41.091,145.842,55.306,290.03,55.078,221.015-.348,232.464-251.918,446.846-265.314,144.5-9.029,229.247,90.469,364.966-54.532,26.116-27.9,52.772-44.257,77.079-53.559,38.931-14.9,81.644-13.148,119.848,3.795,52.233,23.165,142.179,57.218,225.578-44.538C3456.26-.7,3510.921-63.64,3510.921-63.64" fill="none" stroke="rgba(249,247,250,0.3)" stroke-miterlimit="10" stroke-width="10" />
              <path class="pulse" id="Path_111604" data-name="Path 111604" d="M1922.219,474.558a33.6,33.6,0,1,1-33.6-33.6,33.6,33.6,0,0,1,33.6,33.6" fill="#5d209f" />
              <path class="pulse" id="Path_111605" data-name="Path 111605" d="M1908.09,474.558a19.475,19.475,0,1,1-19.476-19.476,19.476,19.476,0,0,1,19.476,19.476" fill="#f6eb61" />
              <path class="pulse" id="Path_111606" data-name="Path 111606" d="M1056.355,649.037c0-19.115-15.045-34.611-33.6-34.611s-33.6,15.5-33.6,34.611,15.045,34.611,33.6,34.611,33.6-15.5,33.6-34.611" fill="#5d209f" />
              <path class="pulse" id="Path_111607" data-name="Path 111607" d="M1042.226,649.037c0-11.078-8.719-20.059-19.476-20.059s-19.475,8.981-19.475,20.059,8.719,20.059,19.475,20.059,19.476-8.981,19.476-20.059" fill="#f277c6" />
              <path class="pulse" id="Path_111610" data-name="Path 111610" d="M623.423,672.044c0-18.834-15.045-34.1-33.6-34.1s-33.6,15.268-33.6,34.1,15.045,34.1,33.6,34.1,33.6-15.268,33.6-34.1" fill="#5d209f" />
              <path class="pulse" id="Path_111611" data-name="Path 111611" d="M609.294,672.044a19.478,19.478,0,1,0-19.476,19.764,19.621,19.621,0,0,0,19.476-19.764" fill="#ff6d6a" />
              <path class="pulse" id="Path_111608" data-name="Path 111608" d="M2355.151,439.3a33.6,33.6,0,1,0-33.6,33.6,33.6,33.6,0,0,0,33.6-33.6" fill="#5d209f" />
              <path class="pulse" id="Path_111609" data-name="Path 111609" d="M2341.022,439.3a19.475,19.475,0,1,0-19.476,19.476,19.476,19.476,0,0,0,19.476-19.476" fill="#ff6d6a" />
            </g>
          </svg>
    
        </div>
      </div>
    
    </section>
    
    <section class="spacer"></section>