Jump to content
GreenSock

mikel

CustomScrollBar: Scrolltrigger, Draggable

Recommended Posts

Hey,

 

 

Based on the case below, I tried to build a custom scroll bar for a scrollable element with fixed sizes. It works ...


But if you change the window size, if the scroll progress is not equal to 0 or 1, then the drag function is disturbed.

 

See the Pen c889651f79b9848c71f4a918e94471a8?editors=0010 by mikeK (@mikeK) on CodePen

 

What am I doing wrong?

Mikel

See the Pen 896549f0a83297debd9111fe9b205a97?editors=1010 by GreenSock (@GreenSock) on CodePen

Link to comment
Share on other sites

Hey mikel. Even with your current sizing the scroll distance and drag distance don't match up. Try scrolling to the end then dragging - it jumps because the bounds are different.

 

I was able to convert the original pen you linked to your format like so. You should be able to compare your code with this code to see any differences:

const handler = document.querySelector("#handler");
const scroller = document.querySelector("#scroller");
let barLength, maxScroll, trigger, draggable;

// this ScrollTrigger will use the window/<body> by default, calling onRefresh when the page resizes, and onUpdate whenever any scroll happens. 
trigger = ScrollTrigger.create({
  scroller: scroller,
  onRefresh: onResize,
  onUpdate: updateHandler
});

draggable = Draggable.create(handler, {
  type: "y",
  bounds: ".bar",
  onDrag: function() {
    trigger.scroll(this.y / barLength * maxScroll); // when dragging, scroll the page to the corresponding ratio
  }
})[0];

function onResize() {
  if (trigger) {
    maxScroll = ScrollTrigger.maxScroll(scroller); // record the maximum scroll value for the page
    barLength = document.querySelector(".bar").offsetHeight - handler.offsetHeight; 
    updateHandler();
  }
}

function updateHandler() {
  // move the handler to the corresponding ratio according to the page's scroll position.
  gsap.set(handler, {y: barLength * trigger.scroll() / maxScroll});
}

 

  • Like 2
Link to comment
Share on other sites

 

Hey Zach,

 

Thank you for your help.

 

It doesn't work for me - see video.

What I don't understand: The scroller element, maxScroll and also the bar element have fixed sizes.

Why do you need an onRefresh when the page resizes?

 

Mikel

 

Link to comment
Share on other sites

48 minutes ago, mikel said:

It doesn't work for me

Weird. What OS and browser are you using?

 

49 minutes ago, mikel said:

Why do you need an onRefresh when the page resizes?

You can remove the onRefresh listener if this is always going to be the same size. I just included it as part of converting the old demo. If you do remove it, make sure to get the values that you need on load.

Link to comment
Share on other sites

The problem is that you don't have a start or end on the ScrollTrigger, nor do you have a trigger, so it's defaulting to using the <body> as the trigger and a start of "top top". You're translating the nested element such that it goes beyond the top of the <body>, effectively making the <body> grow upwards beyond the viewport. So when you resize and it does a refresh to recalculate where the start/end positions are, it's setting them such that the ScrollTrigger won't get triggered until further down. You'll see that the onUpdate isn't firing. 

 

Solution: 

Just add start: 0, end: "max" to your ScrollTrigger. 

 

I'll also update ScrollTrigger for the next release so that when there's no trigger or "start" defined at all, it'll just default to start: 0 (numeric, absolute). That change is made in the latest beta: https://assets.codepen.io/16327/ScrollTrigger.min.js

  • Like 3
Link to comment
Share on other sites

Hey Jack,

Hey Zach,

 

Great - runs perfectly. Thank you JACK.

 

See the Pen RwGLYxE?editors=1010 by mikeK (@mikeK) on CodePen

 

See the Pen RwGLOmm?editors=0100 by mikeK (@mikeK) on CodePen


I often get irritated by defaults. And I couldn't believe that the default for trigger is the <body> (no reference in the DOCs).

Even if it was explicitly stated in the example.
For my level, this maxim is better: What you code is what you get! And if I forget required properties, I get a warning.
Sure, I see the convenience of defaults. However, they don't always make sense for individual designs.

And there is the possibility to set general defaults yourself if you need hundreds of similar animations.

 

The defaults for today: Silent Night! Holy Night!

Mikel

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.
×