swiper icon indicating copy to clipboard operation
swiper copied to clipboard

Autoplay and slidesPerView auto only autoslides a single slide

Open MagicLegend opened this issue 4 years ago • 9 comments

  • Swiper Version: 6.4.10
  • Platform/Target and Browser Versions: KDE Neon 5.20, Firefox 85.0 (64-bit) & Chrome Version 88.0.4324.96 (Official Build) (64-bit)

What You Did

Enabled autoplay in combination with slidesPerView={'auto'}.

Example: https://codesandbox.io/s/naughty-swanson-6dz2i

Expected Behavior

The slider will autoslide.

Actual Behavior

Now the slider will only move 1 slide, and then stop autosliding.

Disabling or changing the value of slidesPerView (anything but auto works) fixes the issue. Also, calling update(), resizing the window (which internally also forces an update if I'm not mistaken) or even switching to another tab and coming back will let the slider move 1 slide again.

MagicLegend avatar Feb 04 '21 08:02 MagicLegend

The plot thickens. I figured it had to do something with my hack to work around the changing sizes of the swiper-slide-current slide. Here I run swiper.update() 50ms after a slideChange event. So, I did a quick experiment using the JS based Swiper, where I could not replicate the bug. So I figured it was a React-related issue. I found #3977, where the author also uses autoplay with slidesPerView auto; so I took his code for a quick test as well:

JS based test: https://codesandbox.io/s/amazing-newton-kiejf?file=/index.html - All fine and working with the swiper.update() Second React test: https://codesandbox.io/s/strange-bash-g715w - Broken when adding the onSlideChange, but working with slidesPerView on auto

So I guess it's a little more complicated than I thought... So it seems to be react-specific, and having to do with the combination of autoplay, slidesPerView on auto and the swiper.update call on slideChange...

MagicLegend avatar Feb 04 '21 09:02 MagicLegend

Similar workaround for the slide width found here: #1861

It explains the jumpyness I had also experienced; but since my slide width change is not that big, I just took it for granted. Note that he also uses the swiper.update() after a slidechange (although he uses onSlideChangeEnd). Here autoplay also appears to work; which is consistent with my findings that it only breaks when using React.

MagicLegend avatar Feb 04 '21 10:02 MagicLegend

For anyone stumbling across this; I've created a workaround by manually implementing the basics of the autoplay feature: https://codesandbox.io/s/interesting-golick-pkki2

It takes the same event used in the source code of Swiper: https://github.com/nolimits4web/swiper/blob/e39d8e924048fd043377054e0a2d6d9496bf11aa/src/components/autoplay/autoplay.js#L167-L175

And uses the basic idea from this SO answer to pause and unpause: https://stackoverflow.com/a/21278007

I'm not saying it's the best solution, but it works for me.

I'd still like the original bug to be worked out though :)

MagicLegend avatar Feb 04 '21 12:02 MagicLegend

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Aug 04 '21 23:08 stale[bot]

@contributers any word on the bug? Or will we just let it go stale? :(

MagicLegend avatar Aug 05 '21 07:08 MagicLegend

Any update on this issue?

westonAnchore avatar Jan 14 '22 20:01 westonAnchore

hi. the same problem but is desided to write special code to handle it. this worke for me: slidesPerView={here,you must find your window width divided by width of your sliders} i wrote a hook to calculate width for me: :see the end of code for hook created to handle the size and then see slidesPerVeiw in swiper to understand usage"

import { useState, useEffect } from "react";
import React from "react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/scrollbar";
import "swiper/css/free-mode";
import SwiperCore, { Autoplay, FreeMode, Navigation, Scrollbar } from "swiper";
import { styled } from "@mui/material";
SwiperCore.use([Scrollbar, FreeMode, Autoplay, Navigation]);

//-----------style to swiper by: styled()
let Swip = styled(Swiper)(({ theme }) => ({
    padding: 17,
    
    width: "90%",
    "& .swiper-wrapper": { padding: 0 },
}));
export default function Brands() {
    const { width } = useWindowDimensions();
    return (
        <Swip
            autoplay={{
                delay: 3000,
                disableOnInteraction: false,
            }}
            navigation={true}
            spaceBetween={10}
            centeredSlides={true}
            loop={true}
            freeMode={true}
            slidesPerView={width>1700?1700/200:Math.floor(width/200)}
            scrollbar={{
                hide: false,
            }}
        >
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "lightgreen" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "lightblue" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "darkgreen" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "purple" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "pink" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "brown" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "yellow" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "red" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "black" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "green" }}
                />
            </SwiperSlide>
            <SwiperSlide>
                <div
                    style={{ width: 150, height: 100, backgroundColor: "blue" }}
                />
            </SwiperSlide>

        </Swip>
    );
}

function getWindowDimensions() {
    const { innerWidth: width, innerHeight: height } = window;
    return {
        width,
        height,
    };
}

function useWindowDimensions() {
    const [windowDimensions, setWindowDimensions] = useState(
        getWindowDimensions()
    );

    useEffect(() => {
        function handleResize() {
            setWindowDimensions(getWindowDimensions());
        }

        window.addEventListener("resize", handleResize);
        return () => window.removeEventListener("resize", handleResize);
    }, []);

    return windowDimensions;
}

hamidsaif70 avatar Jan 23 '22 13:01 hamidsaif70

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jul 31 '22 21:07 stale[bot]

@contributers any word on the bug? Or will we just let it go stale? :(

MagicLegend avatar Aug 01 '22 08:08 MagicLegend

Swiper v9 comes with fully reworked autoplay module. If you have similar issues in Swiper 9, open a new issue with a CodeSandbox showing the issue.

nolimits4web avatar Feb 01 '23 12:02 nolimits4web