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

Hey Blake, I know its been a year since you posted this scrolling parallax example, I really like it and I've been trying to figure somethings out. Mainly, how to update the 'scroll-container' height when I remove one of the image-items dynamically. I'm using your example as a menu - and so when an image is clicked, all other images are set to display:none - but the parent container height remains the same - just as when all the images were there. How can I trigger the scroll-container height to update to fit the one remaining image-item?

 

Hope you can help - Thanks

Link to comment
Share on other sites

In current implementation, Blake just loops through all the target elements that have data-depth attribute. And there is no logic in place to check if element is visible or hidden. You can add a property to 'item' that you can use to skip the element from the loop, but you will also have to adjust the the count of items to change the loop because you are skipping item and rest of calculation depends on the index. Kind of tricky situation as you will just have to rewrite most of the parts of it because Blake doesn't plan to provide support for it.

  • Like 3
Link to comment
Share on other sites

Hey Sahil, thanks for the reply.

 

The effect im looking for is already built-in Blakes code - its an event that fires whenever the browser window is resized or scrolled. Im basically trying to trigger that same event when I click on something. The scenario is, I have a 4 images - I click on one and the rest set to display:none. When only 1 image remains, the .scroll-container height does not update. However, when I manually resize the browser window, the scroll-container height updates and then so does the scroll position

 

below are the event functions Blake defines  

 

this._onResize = function (event) {
_this.resizeRequest++;
if (!_this.requestId) {
_this.lastTime = performance.now();
_this.requestId = requestAnimationFrame(_this._update);
}
};
this._onScroll = function (event) {
_this.scrollRequest++;
if (!_this.requestId) {
_this.lastTime = performance.now();
_this.requestId = requestAnimationFrame(_this._update);
}
};
Link to comment
Share on other sites

forgot to add this piece to...

 

this._update = function (currentTime) {
if (currentTime === void 0) { currentTime = performance.now(); }
var elapsedMS = currentTime - _this.lastTime;
if (elapsedMS > _this.maxElapsedMS) {
elapsedMS = _this.maxElapsedMS;
}
var deltaTime = elapsedMS * _this.targetFPMS;
var dt = 1 - Math.pow(1 - _this.scrollEase, deltaTime);
var resized = _this.resizeRequest > 0;
var scrollY = window.pageYOffset;
if (resized) {
var height = _this.target.clientHeight;
document.body.style.height = height + "px";
_this.scrollHeight = height;
_this.viewHeight = window.innerHeight;
_this.halfViewHeight = _this.viewHeight / 2;
_this.maxDistance = _this.viewHeight * 2;
_this.resizeRequest = 0;
}
Link to comment
Share on other sites

I'm not really sure what you're trying to do, but trying to remove all the images but one without a jump doesn't seem possible without another container that is fixed. The image that you want to isolate, you could clone and append it the same screen location in the another fixed container.

  • Like 2
Link to comment
Share on other sites

Thanks for the suggestion, I haven't considered that idea. I think in that case tho, a jump would still take place to some extent.

What I had in mind is: the image-item after being clicked - could then tween to the center of the screen during the forced reset.  because the doc height reset happens so quickly - I could, as part of the click event, tell the window.scrollTo(0, 0) and possibly avoid the jump.

 

really im just trying to mimic (in a very hackish way) what this portfolio site does on its project menu page http://alexandrerochet.com/ check out the page right after the intro - then click on a project to see the effect. its pretty slick I think.

Link to comment
Share on other sites

  • 1 month later...

Hello Everyone,

 

I've implemented Blake's smooth scrolling solution and am in love with it. With that in mind, I'm bashing my head the past 24 hrs on trying to get this to work in mobile. Blake's already addressed what the issue is, 

Quote

The address bar causes problems when it moves in and out of view.

 

Has anyone found a workaround or even better, come up with a working solution for mobile?

Any suggestions, direction, help on any level would be greatly appreciated.

Link to comment
Share on other sites

Although I don't use blakes implementation in this post (I use scrollmagic which is a scrolling system made for TweenMax and has parallax , pining, easing, and a ton of other advanced features) 

 

I have parallax / fading / scroll based animations on my personal site and it works great on mobile.  check it out at zadesigns.com

 

I use a combination of iNOBounce and ViewportUnitBuggyFill  to get it to work.

 

the only downside is that you are stuck with the address bar and the tab bar...  but blame Apple for that. 

 

good luck

  • Like 1
Link to comment
Share on other sites

Nice man, site looks impressive!

 

My site just requires two things -- smooth scroll + fading elements on scroll.

For this I'm using Blake's implementation + Intersection Observer API.

 

What I really like about Blake's implementation is it's purely JS, and JS that I can see/tinker with easily.

I haven't tested my app on iOS but see this on chrome + android.

To visually see what's happening, 

 

Found this video on a thread btw.

The only workaround (if you can call it that) I can think of to address all devices, is to remove the smooth scroll functionality for mobile. Having trouble with this too.

 

Tried going the JS + GSAP way,

     if (window.innerWidth <= 800 && window.innerHeight <= 730) {
		// remove and update classes
       TweenMax.set(this.el, { className: -=main});
       TweenMax.set(this.el, { className: +=main-mobile});
     };

 

Tried swapping css files dependent on viewport but having issues in a SSR Next.js environment.

 

But still no luck. 

 

Seems like ViewportUnitBuggyFill is meant for legacy browsers on android where vh,vw units are not recognized. This is a concern too, but not quite there yet. I'm still working on getting this to work on modern browsers lol.

 

As you can see, right now I'm leaning heavily on this forum lol.

Link to comment
Share on other sites

The mobile issue can be solved by using a fixed body size, and making another element scrollable. For an example, go to stackblitz and start an ionic app. The only downside to that approach is that the navigation bars will not shrink or move out of view. 

 

And here's one way to listen for media query changes instead of resize events.

 

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

 

 

  • Like 3
Link to comment
Share on other sites

Hey Blake,

 

Great to hear from you!

Could you elaborate using your smooth scroll implementation? Or if you could elaborate a little more on the fixed body size approach..

I just tried the following..

 

body {
  // BEFORE
  // overflow-x: hidden !important;
  // overflow-y: scroll !important;
  background: #148991;
  height: 310rem !important;
}

a { cursor: pointer; text-decoration: none !important; }

#main {
  // AFTER
  overflow-x: hidden !important;
  overflow-y: scroll !important;

  background: linear-gradient(to right top, #148991, #011219, #022531, #074757) !important;
  overflow: hidden !important;
  position: fixed;
  width: 100vw;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  justify-content: center;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

 

Am I going in the right direction here? At this point the address bar still causes teh issue

Link to comment
Share on other sites

Interestingly, keeping your original implementation and simply adjusting the scroll speed seemed to have done the trick. At least in Chrome / Android.

The resize event is still firing but given the new range of values maybe the jump is too small to notice.

 

    let scroller;

    if (window.innerWidth <= 800 && window.innerHeight <= 730) {
      scroller = {
        target: document.querySelector("#playground-subcontainer"),
        ease: .5, // <-- scroll speed on mobile
        endY: 0,
        y: 0,
        resizeRequest: 1,
        scrollRequest: 0,
      };
    }
    else {
      scroller = {
        target: document.querySelector("#playground-subcontainer"),
        ease: .05,  // <--scroll speed on !mobile
        endY: 0,
        y: 0,
        resizeRequest: 1,
        scrollRequest: 0,
      };
    }

 

Link to comment
Share on other sites

Here's a quickie version that should prevent the navigation bars from moving/resizing. It still has issues, like you can't interact with anything because pointer events are blocked. It could probably be done better using custom elements, but React doesn't play nice with custom elements.

 

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

 

 

  • Like 3
Link to comment
Share on other sites

  • 1 month later...

Hello guys!

 

Blake this is amazing, thanks so much for sharing it with the community.

I have a quick question...

 

I'm using the exact same code you've shared for the page smooth scroll and scroll magic for triggers. I was wondering why the "start" and "end" triggers move so much up and down as if they're glitchy and if there is a way to fix that?

example.gif

Link to comment
Share on other sites

  • 3 months later...
  • 1 month later...
  • OSUblake locked this topic
  • 1 year later...
Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

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