YIZHUANG / react-multi-carousel

A lightweight production-ready Carousel that rocks supports multiple items and server-side rendering with no dependency. Bundle size 2kb.
MIT License
1.28k stars 288 forks source link

Swipe jitter / animation lag on mobile devices when swiping #207

Open wyqydsyq opened 3 years ago

wyqydsyq commented 3 years ago

When trying this library out on mobile devices, I found the swiping to be extremely choppy. The animations upon clicking prev/next arrows or dots works fine and looks smooth, just dragging looks slow and laggy.

To Reproduce Steps to reproduce the behavior:

  1. Visit a page using react-multi-carousel (e.g. the demo storybook) on a mobile Android or iOS device - tested w/ Google Pixel 2
  2. Try swiping to scroll the carousel
  3. Notice that the movement has a lot of jitter / is extremely choppy, like an animation at 3fps

Smartphone (please complete the following information):

This seems to be some issue specific to mobile devices - maybe they aren't using 3D acceleration for some reason? Swiping in a desktop-based Google Chrome with dev tools emulating a mobile viewport doesn't cause the issue and the animation appears smooth while swiping.

I'm going to guess there's some drag event handler firing too frequently causing the JS engine to lag or not often enough causing choppy updates at slow intervals. Maybe there's a missing requestAnimationFrame in some drag-related code?

As an example of a carousel swiping smoothly on mobile for comparison, https://xiaody.github.io/react-touch-carousel/docs/ works fine and smoothly on all devices I've tried.

FluorescentHallucinogen commented 3 years ago

I face this problem too.

@YIZHUANG @abhinavdalal Could you please take a look?

GaddMaster commented 3 years ago

I also have this issue ands it doesnt show on the demo. I tried copying demo porps exactly, its jittery & ugly feel. And this is the lesser problem.

amazingmaze commented 2 years ago

I had the same issue. For me, the error was caused by the page being able to vertically scroll whilst the user is scrolling horizontally. If I tried setting overflow:hidden on the page, the carousel worked just fine. Ended up using this post: https://github.com/akiran/react-slick/issues/1240#issuecomment-396484553 to prevent vertical scroll. Everything seems to be working fine right now.

shamsucmprimalcodes commented 2 years ago

I also have the same issue .

Sriraj1998 commented 1 year ago

Hi all ,

I know I'm a bit late for the person who created the issue @wyqydsyq , but anyways I kind of solved this issue , tested it on my mobile(i13) & the swiping has improved tremendously.

As @amazingmaze mentioned first we need to stop vertical scroll from happening when we are swiping the carousel. I made use of below code for that -

`let firstClientX, clientX;

const preventTouch = e => {
const minValue = 5; // threshold

clientX = e.touches[0].clientX - firstClientX;

// Vertical scrolling does not work when you start swiping horizontally.
if (Math.abs(clientX) > minValue) {
  e.preventDefault();
  e.returnValue = false;

  return false;
 }
 };

 const touchStart = e => {
  firstClientX = e.touches[0].clientX;
 };

//Component Fn starts here  

    const ProductsCarousel = () => {

        let containerRef = useRef();

        useEffect(() => {
          if (containerRef.current) {
            containerRef.current.addEventListener("touchstart", touchStart);
            containerRef.current.addEventListener("touchmove", preventTouch, {
              passive: false
            });
          }

          return () => {
            if (containerRef.current) {
              containerRef.current.removeEventListener("touchstart", touchStart);
              containerRef.current.removeEventListener("touchmove", preventTouch, {
                passive: false
              });
            }
          };
        });

        return (
            <div ref={containerRef}>
                <Carousel>
                //Your content
                </Carousel>
            </div>

            )

    }`

After this made few changes in the Carousel attributes - <Carousel customTransition="transform 1ms linear" minimumTouchDrag={10} transitionDuration={1} />`

So as you could see I reduced the transition time and changes the transition to linear rather than ease in out which was the default . Not sure if minimunTouchDrag made any difference , but too lazy to remove it and test again lol

Benkimeric commented 5 months ago

Here is a working solution which worked for me. Thanks to https://github.com/YIZHUANG/react-multi-carousel/issues/217

In your Carousel componenet you have to set the swipeable property to false:

Then in your global CSS file, override this CSS class : .react-multi-carousel-track { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: row; position: relative; transform-style: preserve-3d; -webkit-backface-visibility: hidden; backface-visibility: hidden; will-change: transform, transition; overflow-y: scroll !important; scrollbar-width: none; /* Firefox */ -ms-overflow-style: none; /* IE and Edge */ ::-webkit-scrollbar { display: none; /* Chrome, Safari, and Opera */ } }