react-native-web icon indicating copy to clipboard operation
react-native-web copied to clipboard

ScrollView: momentum scroll events

Open necolas opened this issue 6 years ago • 9 comments

Look into supporting momentum scroll events.

necolas avatar Jul 07 '18 02:07 necolas

I guess that to add support for the scroll momentum callbacks there needs to be a way to detect if the scroll is done with momentum.

You could always check for the scroll speed, but that is not really the same thing as you call do a scroll movement fast without it having momentum.

Is anyone aware of any existing Javascript implementations where such gesture would be detected?

kristerkari avatar Dec 17 '18 10:12 kristerkari

My initial thought is that if a scroll is initiated by a touch, and scroll events are still firing while there is no active touch, we're in a "momentum" phase of the scroll. I don't think momentum events can exist for mouse/wheel-triggered scrolls. And the drag start event would fire when touch-scrolling starts, and drag end would fire when touch-scrolling ends. But would have to check when the events fire for native to confirm.

necolas avatar Dec 17 '18 20:12 necolas

I don't think momentum events can exist for mouse/wheel-triggered scrolls

At least on macos with a trackpad you can experience them in all browsers.


Might this help to finish touchable support as some issues with those might be related to some missing events (eg: for scroll responder?)

MoOx avatar Dec 31 '18 14:12 MoOx

https://css-tricks.com/snippets/css/momentum-scrolling-on-ios-overflow-elements/

RichardLindhout avatar Jun 19 '19 11:06 RichardLindhout

me too

zxymgl avatar Sep 25 '20 08:09 zxymgl

For anyone needing a temp workaround I made a hook...

// hooks.js

export const useWebOnScroll = ({ onScroll, onScrollEnd }) => {
  const lastScrollEvent = useRef(null);
  const scrollEndTimeout = useRef(null);

  const handleWebScroll = event => {
    onScroll(event);

    const timestamp = Date.now();

    if (scrollEndTimeout.current) {
      clearTimeout(scrollEndTimeout.current);
    }

    if (lastScrollEvent.current) {
      // Scroll ended
      scrollEndTimeout.current = setTimeout(() => {
        if (lastScrollEvent.current === timestamp) {
          lastScrollEvent.current = null;
          onScrollEnd && onScrollEnd(event);
        }
      }, 500);
    }

    lastScrollEvent.current = timestamp;
  };

  useEffect(() => {
    return () => {
      scrollEndTimeout.current && clearTimeout(scrollEndTimeout.current);
    };
  }, []);

  return handleWebScroll;
};

// Component.js


const Component = ({onScroll, onScrollEnd}) => {
    const handleWebScroll = useWebOnScroll({ onScroll, onScrollEnd })

    <ScrollView onScroll={Platform.select({ web: handleWebScroll, default: onScroll })} />
}

MorganTrudeau avatar Dec 01 '21 23:12 MorganTrudeau

Anyone know if this has been fixed or if there's another way of achieving this effect on RN web?

Ryanjso avatar Aug 08 '22 13:08 Ryanjso

Here's my solution: https://github.com/necolas/react-native-web/issues/2249#issuecomment-1736457705

nandorojo avatar Sep 27 '23 17:09 nandorojo