Jump to content
Search Community

Smooth Page Scroll

OSUblake test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I've been getting a bunch of people asking me about how to do a smooth page scroll effect, so here it is. 

 

Scrolling is just a transform. If you scroll 100px down, the browser will translate the page -100px up. We can do that with GSAP.

TweenLite.set(contentToScroll, {
  y: -window.pageYOffset
});

 

So how do you prevent the browser from scrolling the content? Position your content in a fixed container, and set the height of the body equal to the height of your content. This will allow the page to scroll, but the fixed container won't move. Now animate the y position of your content based on the scroll position of the page.

 

 

See the Pen QqPqbN by osublake (@osublake) on CodePen

  • Like 13
  • Thanks 1
Link to comment
Share on other sites

Blake, using his great example of smooth scroll,

got into a situation when using it along with ScrollMagic / GSAP,

I'm trying to create a parallax system in BG image,

but when it starts animating bgImage, the image gets "jumped" created an example using jQuery NiceScroll for you to see more or less the difference.

I need it to be animated along with scrolling to create the Parallax effect:

 

See the Pen eGwvop by Noturnoo (@Noturnoo) on CodePen

 

 

See the Pen RLzgjP?editors=0100 by Noturnoo (@Noturnoo) on CodePen

 

Link to comment
Share on other sites

Yep. That's to be expected. ScrollMagic doesn't know about the animation, and is getting the scroll position like it normally does, but that's not correct. The value ScrollMagic is using is the end value, not the current value, so it's out of sync.

 

I have some other things I need to do, but I will make a demo later on showing you how to get the smooth parallax working with that code.

 

 

 

  • Like 2
Link to comment
Share on other sites

On 25/10/2017 at 9:21 AM, OSUblake said:

Yep. That's to be expected. ScrollMagic doesn't know about the animation, and is getting the scroll position like it normally does, but that's not correct. The value ScrollMagic is using is the end value, not the current value, so it's out of sync.

 

I have some other things I need to do, but I will make a demo later on showing you how to get the smooth parallax working with that code.

 

 

 

@OSUblake

Perfect, anxious.

Link to comment
Share on other sites

Well, here's the start of something. Put a data-depth attribute on your element like so. 0 will be no offset, 10 will be max offset.

<div data-depth="10"></div>

 

And then create a smooth scroll instance.

var scroller = new SmoothScroll({
  target: document.querySelector("#scroll-container"), // element container to scroll
  scrollEase: 0.1, // scroll speed
  maxOffset: 500
});

 

With maxOffset set to 500, an element with a depth of 10 will move 500px.

10 / 10 * 500 = 500

 

A depth of 5 will move 250px

5 / 10 * 500 = 250

 

And so on...

4 / 10 * 500 = 200

 

See the Pen GOJJyr by osublake (@osublake) on CodePen

 

  • Like 7
  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...

Hello Blake,

sorry for the delay, I've been working a lot these days.

First of all I want to thank you for having made some of your time available to create this,

it is very useful for me. And I'm sure I'll use it on many projects.
Just a question, is there a way for Parallax to start as soon as the element enters the viewport? For here he is cheering when he comes in half.
A solution similar to ScrollMagic's TriggerHook.

 

Cheers

Link to comment
Share on other sites

On 11/11/2017 at 10:00 AM, Noturnoo said:

Just a question, is there a way for Parallax to start as soon as the element enters the viewport? For here he is cheering when he comes in half.
A solution similar to ScrollMagic's TriggerHook.

 

I'm not familiar with ScrollMagic. Does the hook start an animation, like one that plays without scrolling?

 

  • Like 1
Link to comment
Share on other sites

ScrollMagic's TriggerHook system is used to indicate from how many percent what element is in the Viewport it will start the animation.
Example
TriggerHook: 0.8
(The element will start animating when it is 20% of the bottom of the viewport)
Since TriggerHook: 1 is equal to 100% of Viewport.
Did you get it?

  • Haha 1
Link to comment
Share on other sites

I use scrollmagic and tweenmax in my angular projects and I recently swapped over to a newer ES6 version of scrollmagic called Scroll Wizardry  its a drop in replacement so you can replace your calls from scrollmagic to scroll wizardry.   I am not sure how much difference the performance is but it seems to work great for me.   

 

https://github.com/homerjam/scrollwizardry

 

and if you use vue.js here is a wrapper for it, but if you use something like angular or plain JS you can just call it the standard way.

https://gist.github.com/zurie/f816c1d6569d28b2eafa7fea71b7ed95

 

  • Like 2
Link to comment
Share on other sites

  • 10 months later...
On 10/31/2017 at 2:37 AM, OSUblake said:

Blake, I don't mean to sound ignorant (it may be too late), but where is SmoothScroll defined?

 

 

And then create a smooth scroll instance.


var scroller = new SmoothScroll({
  target: document.querySelector("#scroll-container"), // element container to scroll
  scrollEase: 0.1, // scroll speed
  maxOffset: 500
});

 

-mark

***** NM Found It! ****

 

 

 
 

 

Edited by msymms
Anwered my own question
Link to comment
Share on other sites

I'm loading the JavaScript from another pen.

https://codepen.io/osublake/pen/e72106811a34efcccff91a03568cc790.js

 

 

Feel free to use it, but I really can't offer support for it. I never got around to making it work correctly for mobile. The address bar causes problems when it moves in and out of view.

 

 

 

 

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Blake, so I have dug into the smoothScroll.js file.  I am trying to understand the logic and what exactly you are doing.  There are some behaviors I would like to modify and really just understand what is going on.  You have incorporated a parallax feel which I want to capitalize on as well.  Are you able to answer questions about the code?

 

I don't understand what is happening in this for-loop prior to setting the transform style.

 

for (let i = 0; i < _this.scrollItems.length; i++) {
                let item = _this.scrollItems[i];
                let distance = scrollOrigin - item.top;
                let offsetRatio = distance / _this.maxDistance;
                item.endOffset = Math.round(_this.maxOffset * item.depthRatio * offsetRatio);
                if (Math.abs(item.endOffset - item.currentOffset < _this.endThreshold)) {
                    item.currentOffset = item.endOffset;
                }
                else {
                    // item.currentOffset += (item.endOffset - item.currentOffset) * this.scrollEase;
                    item.currentOffset += (item.endOffset - item.currentOffset) * dt;
                }
                item.target.style.transform = "translate3d(0px,-" + item.currentOffset + "px,0px)";
            }

    

Can you help?

Edited by msymms
Added Code
Link to comment
Share on other sites

So I have gone through the bulk of Keith's videos.  Quite enlightening.  Things look a little more familiar.  I have been able to start the parallax scrolling at the bottom of the screen.  But I am still trying to figure out the logic.  For instance, what does this value (dt) represent?

let dt = 1 - Math.pow(1 - _this.scrollEase, deltaTime);

 

and 

 

what is the need for an endThreshold?

 

 this.endThreshold = 0.03;

 

Sorry if this is basic stuff, I am just getting back into this after a number of years away.

Link to comment
Share on other sites

Everything is based on linear interpolation (lerp) being used like an exponential ease. Explaining dt and deltaTime can be hard to explain, so I'm just going to link to this.

https://gamedev.stackexchange.com/a/149106/109260

 

I had one line of code commented out. Use one or the other. Frame dependent animations can slow down during high CPU usage.

 

if (Math.abs(item.endOffset - item.currentOffset < this.endThreshold)) {
  item.currentOffset = item.endOffset;
} else {
  
  // FRAME DEPENDENT
  // item.currentOffset += (item.endOffset - item.currentOffset) * this.scrollEase;
  
  // FRAME INDEPENDENT
  // item.currentOffset += (item.endOffset - item.currentOffset) * dt;
}

 

 

That gamedev answer also mentioned Zeno, which is like a paradox. You can never arrive at a destination because the steps just get smaller and smaller. The threshold stops calculating stuff after a certain limit, i.e. changes you won't see because they are too small.

 

 

 

 

 

  • Like 2
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...