darkroomengineering / lenis

How smooth scroll should be
https://lenis.darkroom.engineering
MIT License
9.03k stars 385 forks source link

Can't see scroll bar and can't scroll on mobile #160

Closed gercordero closed 1 year ago

gercordero commented 1 year ago

Describe the bug I am currently using React-Three-Next starter which has a Scroll component that uses Lenis in a very similar way to React Lenis.

When I use the Scroll component to wrap my pages they look fine and I can scroll them with the mouse wheel and trackpad without problems but the scroll bar is not visible and on touch devices I can't scroll unless I set the smoothTouch option to true. In addition to that when I try to integrate the gsap ScrollTrigger plugin the scroller-start and scroller-end are both at the top of the page.

Here you can see the issue:

https://user-images.githubusercontent.com/13878860/231392679-32899a1a-cd06-4b4c-bb9b-6a83fa1ea14c.mov

I am also sharing part of my implementation in case it helps:

// Scroll.tsx
const state = {
  top: 0,
  progress: 0,
}

export default function Scroll({ children }) {
  gsap.registerPlugin(ScrollTrigger);

  const content = useRef(null)
  const wrapper = useRef(null)

  useEffect(() => {
    const lenis = new Lenis({
      wrapper: wrapper.current,
      content: content.current,
      duration: 1.2,
      easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), // https://www.desmos.com/calculator/brs54l4xou
      direction: 'vertical',
      gestureDirection: 'vertical',
      smooth: true,
      smoothTouch: false,
      touchMultiplier: 2,
      infinite: false,
    })

    lenis.on('scroll', ({ scroll, progress }) => {
      state.top = scroll
      state.progress = progress

      ScrollTrigger.update();
    })

    gsap.ticker.add((time) => {
      lenis.raf(time * 1000);
    });

    const effectSub = addEffect((time) => lenis.raf(time))
    return () => {
      effectSub()
      lenis.destroy()
    }
  }, [])

  return (
    <div
      ref={wrapper}
      style={{
        position: 'absolute',
        overflow: 'hidden',
        width: '100%',
        height: '100%',
        top: 0,
      }}>
      <div
        ref={content}
        style={{
          position: 'relative',
          minHeight: '200vh',
        }}>
        {children}
      </div>
    </div>
  )
}
// _app.tsx
<Layout ref={ref}>
        <Scroll>
          <Component {...pageProps} />
        </Scroll>
        {/* The canvas can either be in front of the dom or behind. If it is in front it can overlay contents.
         * Setting the event source to a shared parent allows both the dom and the canvas to receive events.
         * Since the event source is now shared, the canvas would block events, we prevent that with pointerEvents: none. */}
        {Component?.canvas && (
          <Scene className="pointer-events-none" eventSource={ref} eventPrefix="client">
            {Component.canvas(pageProps)}
          </Scene>
        )}
</Layout>
clementroche commented 1 year ago

First of all i don't think you need a scroll wrapper, why don't you use page scroll ? Anyway, just remove overflow hidden on your wrapper. If you're using React, i advise you to take a look at react-lenis.

About ScrollTrigger, you need to use your wrapper element as scroller