nolimits4web / swiper

Most modern mobile touch slider with hardware accelerated transitions
https://swiperjs.com
MIT License
39.97k stars 9.75k forks source link

Issue with Double Swipe Trigger on Safari Using Trackpad or Mousewheel #6942

Closed therealtgd closed 1 year ago

therealtgd commented 1 year ago

Check that this is really a bug

Reproduction link

https://codesandbox.io/p/sandbox/swiper-react-slides-per-view-forked-9mrfck?file=%2Fsrc%2FApp.jsx%3A1%2C1

Bug description

I've encountered an issue with the Swiper library when using Safari and performing a two-finger swipe gesture on a trackpad or using the mousewheel scroll. The problem is that occasionally, the carousel swipes two times instead of the expected single swipe action. This issue is isolated to Safari, as the library works as intended on other browsers.

Expected Behavior

The carousel should respond with a single swipe action, transitioning to the next or previous slide accordingly.

Actual Behavior

Upon performing the two-finger swipe gesture or mousewheel scroll, the carousel swipes twice, causing an unintended and jumpy transition between slides.

Swiper version

10.1.0

Platform/Target and Browser Versions

macOS Safari 16.5.1

Validations

Would you like to open a PR for this bug?

nolimits4web commented 1 year ago

It is a known issue and already opened here, for now you can use cssMode to have perfect scrolling with trackpad

therealtgd commented 1 year ago

Thanks for the fix and a quick reply! 🚀 Quick question: any chance of adding that fix to the docs if it isn't already there? Would be a huge help for others who might run into it.

therealtgd commented 1 year ago

@nolimits4web With cssMode enabled the mouse click and drag no longer works. Is there a way to make it work? Here is my code:

"use client";

import { useRef } from "react";

import { Swiper, SwiperSlide } from "swiper/react";
import { Mousewheel } from "swiper/modules";

import "swiper/css";

<Swiper
  modules={[Mousewheel]}
  spaceBetween={40}
  slidesPerView="auto"
  mousewheel={{ forceToAxis: true }}
  ref={swiperElRef}
>
  {companyList.map((company) => (
    <SwiperSlide key={company.id} style={{ width: "420px" }}>
    ...
    </SwiperSlide>
  ))}
</Swiper>
LeoSeyers commented 9 months ago

It is a known issue and already opened here, for now you can use cssMode to have perfect scrolling with trackpad

I tried cssMode that but mousewheel mode and grab do not work anymore. I'd rather have2 slides jumping than loosing those controls (full bleed slider).

Also, this is not restricted to Safari. I have this issue while using trackpage Chrome on updated Apple M1.

jpask1392 commented 3 months ago

If this helps anyone here!

If the user does a big swipe, you can temporarily disable the mousewheel to prevent it jumping again. Then wait to re-enable. It's not perfect because if someone does large swipes in quick succession, they'll trigger a page change because the mousewheel event is removed. Works for what I need buuuut you can decide if you're ok with that trade off!

useEffect(() => {
  if (!swiperRef.current) return;
  const swiperParams: SwiperOptions = {
    slidesPerView: 'auto',
    keyboard: true,
    loop: true,
    mousewheel: {
      forceToAxis: true,
      thresholdDelta: 35,
    },
    on: {
      scroll: (swiper, e) => {
        const deltaX = Math.abs(e.deltaX); // left or right
        const threshold = 50; // Adjust the threshold as needed

        clearTimeout(scrollTimeout.current);
        scrollTimeout.current = setTimeout(() => {
          if (deltaX > threshold) swiper.mousewheel?.enable();
        }, 1000);

        if (deltaX > threshold) {
          swiper.mousewheel?.disable(); // stops the initial scroll
        }
      }
    },
  };

  Object.assign(swiperRef.current, swiperParams);
  swiperRef.current?.initialize();
}, []);