lukaszflorczak / vue-agile

🎠 A carousel component for Vue.js
https://lukaszflorczak.github.io/vue-agile/
MIT License
1.49k stars 167 forks source link

Pause autoplay for some time when manual sliding #164

Open cimpok opened 4 years ago

cimpok commented 4 years ago

Hi, its me again, Thank you for solving so quickly my issue last time, this time a feature request to refine the user experience further.

The problem: With autoplay on, the user can manually swipe the slides, that's fine. But it could be annoying when the user has just swiped onto a selected slide (with the intention to watch it for some time) and the autoplay kicks in any time (it can be any random time between zero and autoplaySpeed) just to swipe away the slide the user has just selected to view)

My proposal:

  1. reset the autoplay timer each time a manual slide happens, so at least the autoplaySpeed's time allowed after a manual slide
  2. I would consider allowing more time before the autoplay kicks in again, introduce a new setting: pauseAfterSwipe (in msec value, can differ from autoplaySpeed)
  3. throw us an event when manual swipe happens so we can handle it in code
SayHeyD commented 4 years ago

So I just had to do something similar not with manual sliding. In my case the timing should also stay the same but when a user changes a page (no SPA).

I don't know if this is the 'best' solution bur here's my component:

<template>
    <agile  id="slideShow"
            ref="slideshow"
            :autoplay="isPlaying"
            :autoplaySpeed="5000"
            :dots="false"
            :nav-buttons="false"
            :initial-slide="slideToShow"
            @after-change="setCurrentSlide"
            >
        <div class="w-full">
            <img ... class="w-full h-full object-cover">
        </div>

        ...

    </agile>
</template>

<script>
    export default {
        name: "Background",
        data() {
            return {
                slideToShow: parseInt(localStorage.getItem('slide')) || 0,
                isPlaying: true,
            }
        },
        mounted() {
            this.firstSlideChange();
            this.setCurrentSlide();
        },
        methods: {
            firstSlideChange() {
                let differenceInMilliSeconds = new Date().getTime() - Date.parse(localStorage.getItem('lastSlideChange'));
                if (differenceInMilliSeconds < 5000) {
                    this.isPlaying = false;
                    setTimeout(() => {
                        this.$refs.slideshow.goToNext();
                        this.isPlaying = true;
                    }, 5000 - differenceInMilliSeconds)
                }
            },
            setCurrentSlide() {
                localStorage.setItem('currentSlide', this.$refs.slideshow.getCurrentSlide());
                localStorage.setItem('lastSlideChange', new Date().toISOString());
            }
        }
    }
</script>

Basically I bound autoplay to isPlaying. I also set the @after-change event to fire firstSlideChange() which compares the time between the last change and the current time in milliseconds.

Hopefully I could help you.

cimpok commented 4 years ago

Hi, thanks for sharing your code.

In your case you have the 'mounted' event that triggers your methods when the user reloads a page. This is a clear trigger for you, but I am stuck with my problem because a manual swipe does not differ from an autoplayed slide-change event. Both emit the same @after-change event.

I could perhaps make out the difference by comparing the elapsed time between the @after-change events not matching the autoplaySpeed value, but it would be an overkill for such a small functionality I think. Lukasz could perhaps make this for us easily with just a couple of lines in the component.