Jump to content
GreenSock

amitr95

How to remove delay in getting horizontal scroller to start?

Recommended Posts

I have a horizontal scroller block which takes a while to start moving. See the gif here (keep an eye on the right hand scroll bar):

 

In the gif, you can see when my section pins, and then from the scrollbar, you can see I'm scrolling down. After about 7 scrolls down, that's when my content starts to scroll horizontally.

 

Unsure what is causing this delay, but from a UX perspective, it's causing issues. Should ideally start scrolling horizontally as soon as the section pins.

 

I cannot create a codepen of my issue (as my pen exceeds the 1mb limit), but see here for a JSFiddle, code below also.

 

$(function() {

  let container = document.querySelector(".horizontalScroller__items");
  let elements = gsap.utils.toArray(document.querySelectorAll(".animate"));
  let intro = document.querySelector(".horizontalScroller__intro");
  let svg = document.querySelector(".horizontalScroller__items svg");
  let animDone = false;

  gsap.to(container, {
    ease: "none",
    scrollTrigger: {
      trigger: ".horizontalScroller",
      pin: ".horizontalScroller",
      anticipatePin: 1,
      // scrub: 0.2,
      invalidateOnRefresh: true,
      refreshPriority: 1,
      end: '+=445%', // this decides speed of shift (not how much it scrolls by)
      markers: true,
      onEnter: (self) => {
        moveAnimate();
      },
      onLeaveBack: (self) => {
        resetAnimate();
      },
      onUpdate: (self) => {
        let p = self.progress;

        if (p <= 0.25) {
          animDone = false;
        }

        if (p > 0.23) {
          console.log(p);
          moveAnimate();
          // this controls how much it scrolls
          // we do not want to shift the svg by 100% to left
          // want to shift it only by 100% - browser width
          let scrollPercent = (1 - window.innerWidth / svg.scrollWidth) * 100;
          let shift = ((p - 0.22) * scrollPercent) / 0.7;
          if($(window).width() < 768){
            shift = ((p - 0.22) * scrollPercent) / 0.79;
          }
          gsap.to(svg, {
            xPercent: -shift
          });

        }

      }
    }
  });

  function resetAnimate() {
    gsap.set(".animate", {
      y: 150,
      opacity: 0
    });
  }
  resetAnimate();
  
  function moveAnimate() {
    for (let e of elements) {
      if (ScrollTrigger.isInViewport(e, 0.2, true)){
        gsap.to(e, {
          y: 0,
          opacity: 1,
          duration: 1.5
        });
      }
    }
  }

  // refresh scrolltrigger once
  var toggleScroll = false;
  $(window).one("scroll", checkToggleScroll);

  function checkToggleScroll(){
    if ($('.horizontalScroller').isInViewport()) {
      ScrollTrigger.refresh();
      toggleScroll = true;
    }
    if(!toggleScroll){
      $(window).one("scroll", checkToggleScroll);
    }
  }

});
@media (max-width: 576px) {
  :root {
    scroll-behavior: unset !important;
  }
}

.spacer {
  background-color: black;
  height: 1000px;
}

.horizontalScroller {
  padding: 100px 0 60px 0;
  height: 100vh;
  position: relative;
  overflow: hidden;
  z-index: 1;
}
@media (min-width: 768px) {
  .horizontalScroller {
    padding: 140px 0 80px 0;
  }
}
@media (min-width: 1200px) {
  .horizontalScroller {
    padding: 114px 0 80px 0;
  }
}
.horizontalScroller__intro {
  margin-bottom: 90px;
}
.horizontalScroller__header {
  margin-bottom: 17px;
}
.horizontalScroller__scroll {
  position: absolute;
  overflow: hidden;
  top: 0;
}
.horizontalScroller__items {
  position: relative;
  height: 100vh;
  width: 100%;
}
.horizontalScroller__items svg {
  height: 100%;
  width: auto;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></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>

<div class="spacer"></div>

<section class="horizontalScroller">

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

  <div class="horizontalScroller__scroll"> 
    <div class="horizontalScroller__items">
      <!-- large svg code here, see jsfiddle -->
    </div>
  </div>

</section>

<div class="spacer"></div>

 

Link to comment
Share on other sites

Extremely difficult to debug something like this without a working piece of code. First thing you should try is markers: true on your scrollTrigger and then log something in the onEnter event to make sure it's triggering correctly. If it is, then it's likely a logic problem. To be honest, I'm not sure what your code structure is doing. It seems far more complex than necessary to achieve the results the gif you shared is showing.

  • Like 1
Link to comment
Share on other sites

That code/logic looks very strange to me. I suspect @SteveS is correct, that you're overcomplicating and over-engineering things. 

 

You've got an onUpdate that's handling things differently based on the progress (odd - it's probably much cleaner to just use two ScrollTriggers) and then if it's more than 25%, you're calling  moveAnimate() on EVERY update, over and over again which is creating a new tween each time and there's no overwrite set, so you're creating a ton of conflicting tweens that are all trying to control the same properties of the same elements. That's definitely a problem. The same goes for your xPercent tween in there - you're creating a new one over and over again. 

 

If you still need some help, I'd strongly recommend just simplifying things using a few colored <div> elements in CodePen and then post back here with your GSAP-specific question and we'd be happy to take a peek. 

Link to comment
Share on other sites

Hi @SteveS, @GreenSock,

 

Thanks for the above feedback.

 

I have simplified my JS to remove the animation - See JSFiddle here - Again, apologies, I cannot create a Codepen because it says my pen exceeds the 1MB limit, which is caused by the SVG (that is essential to my issue).

 

I've seen demo's which showcase how to scroll horizontally using multiple elements (for example, scroll every .panel element. However, I'm just trying to scroll horizontally on my single svg graphic.  This is where I'm struggling.

 

In my fiddle demo above, you can see the delay in making the scroll start.

 

JS:

$(function() {

  let container = document.querySelector(".horizontalScroller__items");
  let svg = document.querySelector(".horizontalScroller__items svg");

  gsap.to(container, {
    ease: "none",
    scrollTrigger: {
      trigger: ".horizontalScroller",
      pin: ".horizontalScroller",
      anticipatePin: 1,
      scrub: 0.2,
      invalidateOnRefresh: true,
      refreshPriority: 1,
      // end: '+=445%', // this decides speed of shift (not how much it scrolls by)
      end: () => "+=" + window.innerWidth,
      markers: true,
      onUpdate: (self) => {
        let p = self.progress;
        if (p > 0.23) {
          let scrollPercent = (1 - window.innerWidth / svg.scrollWidth) * 100;
          let shift = ((p - 0.22) * scrollPercent) / 0.7;
          if($(window).width() < 768){
            shift = ((p - 0.22) * scrollPercent) / 0.79;
          }
          gsap.to(svg, {
            xPercent: -shift
          });
        }
      }
    }
  });


  // refresh scrolltrigger once
  var toggleScroll = false;
  $(window).one("scroll", checkToggleScroll);

  function checkToggleScroll(){
    if ($('.horizontalScroller').isInViewport()) {
      ScrollTrigger.refresh();
      toggleScroll = true;
    }
    if(!toggleScroll){
      $(window).one("scroll", checkToggleScroll);
    }
  }

});

 

Link to comment
Share on other sites

If CodePen isn't working, try CodeSandbox.

I'm still not sure what the onUpdate is supposed to be doing that cannot be done with a tween itself

Link to comment
Share on other sites

I think I'm just as confused as @SteveS here - I don't understand what you're trying to do or why you're creating new tweens on every single update, but only after it hits a progress beyond 0.23. I'm totally lost. 

 

3 hours ago, amitr95 said:

Can you provide an example of this Tween approach? I don't see this in the GSAP demo?

Not sure what you mean here either. What Tween approach?

 

It's typically best to just simplify things as much as possible in a CodePen using a few colored <div> elements to illustrate your use case. Don't worry about using your "real" artwork especially if it's huge. The idea is to just get the movement correct and the overall concept, then you can apply it to your actual project. But again, I think we're all confused about what exactly your goal is so it's difficult for us to offer any advice or solution. 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×