Skip to content

Instantly share code, notes, and snippets.

@aneudy1702
Last active March 26, 2020 23:23
Show Gist options
  • Save aneudy1702/ba4094324ebcfbb26721cafc87026ecd to your computer and use it in GitHub Desktop.
Save aneudy1702/ba4094324ebcfbb26721cafc87026ecd to your computer and use it in GitHub Desktop.
React component to lock window scroll while users are horizontally swiping within the container. for example when swiping through a carousel.
import React, { useRef } from 'react';
import get from 'lodash.get';
import throttle from 'lodash.throttle';
const getTouchEndX = event => get(event, 'changedTouches[0].screenX') || 0;
const preventDefault = event => {
event.preventDefault();
event.returnValue = false;
return false;
};
const allowWindowScrolling = (shouldScroll = true) => {
const action = shouldScroll ? 'removeEventListener' : 'addEventListener';
window[action]('touchmove', preventDefault, { passive: false });
};
export const PreventVerticalScrollingWhileSwiping = React.memo(
({ children, ...props }) => {
const touchStartX = useRef(0);
const touchEndX = useRef(0);
const timeToResetScrolling = 200;
const resetId = useRef();
const onStart = throttle(event => {
touchStartX.current = getTouchEndX(event);
});
const onMove = throttle(event => {
touchEndX.current = getTouchEndX(event);
const swipeDistanceHorizontal = touchEndX.current - touchStartX.current;
const isSwiping = Math.abs(swipeDistanceHorizontal) > 5;
// Allow Window Scrolling if no Horizontal Swipe is in progress
allowWindowScrolling(!isSwiping);
if (isSwiping) {
// Re-enable Window scrolling after the configured period
clearTimeout(resetId.current);
resetId.current = setTimeout(allowWindowScrolling, timeToResetScrolling);
}
});
return (
<div onTouchStart={onStart} onTouchMove={onMove} {...props}>
{children}
</div>
);
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment