From 87a60678baab256f37c244c8738a45717351c941 Mon Sep 17 00:00:00 2001 From: Vadim Date: Fri, 8 Oct 2021 19:31:36 +0300 Subject: [PATCH] Fix autoplay --- src/components/Carousel/Carousel.svelte | 43 ++++++----- .../{carousel2.js => createCarousel.js} | 71 ++++++++++++------- 2 files changed, 65 insertions(+), 49 deletions(-) rename src/components/Carousel/{carousel2.js => createCarousel.js} (82%) diff --git a/src/components/Carousel/Carousel.svelte b/src/components/Carousel/Carousel.svelte index efa235b..b4964ae 100644 --- a/src/components/Carousel/Carousel.svelte +++ b/src/components/Carousel/Carousel.svelte @@ -30,26 +30,26 @@ import { ProgressManager } from '../../utils/ProgressManager' import { wait } from '../../utils/interval' - import { carousel2 } from './carousel2' - - // TODO: apply normalize value before saving to reactive - // TODO: + import createCarousel from './createCarousel' + // used for lazy loading images, preloaded only current, adjacent and cloanable images + let loaded = [] let currentPageIndex let focused = false let progressValue let offset = 0 - let _duration = 0 + let durationMs = 0 let pagesCount = 1 - const [{ data, progressManager }, methods] = carousel2((key, value) => { + const [{ data, progressManager }, methods, service] = createCarousel((key, value) => { switcher({ 'currentPageIndex': () => currentPageIndex = value, 'progressValue': () => progressValue = value, 'focused': () => focused = value, 'offset': () => offset = value, - '_duration': () => _duration = value, + 'durationMs': () => durationMs = value, 'pagesCount': () => pagesCount = value, + 'loaded': () => loaded = value, })(key) }) @@ -78,13 +78,16 @@ * Page to start on */ export let initialPageIndex = 0 + $: { + data.initialPageIndexInit = initialPageIndex + } /** * Transition duration (ms) */ export let duration = 500 $: { - data.duration = duration + data.durationMsInit = duration } /** @@ -160,7 +163,7 @@ export async function goToPrev(options) { const animated = get(options, 'animated', true) - await methods.showPrevPage({ animated }) + await methods.showPrevPage({ animated }) } export async function goToNext(options) { @@ -187,17 +190,6 @@ methods.offsetPage({ animated: false }) }) - // used for lazy loading images, preloaded only current, adjacent and cloanable images - let loaded = [] - // $: loaded = getAdjacentIndexes({ - // infinite, - // pageIndex: currentPageIndex, - // pagesCount, - // particlesCount: particlesCountWithoutClones, - // particlesToShow: _particlesToShow, - // particlesToScroll, - // }).particleIndexes - function addClones() { const { clonesToAppend, @@ -244,7 +236,7 @@ // gestures function handleSwipeStart() { if (!swiping) return - data._duration = 0 + data.durationMs = 0 } async function handleSwipeThresholdReached(event) { if (!swiping) return @@ -272,6 +264,11 @@ function handleTapped(event) { methods.toggleFocused() } + + function showPrevPage() { + methods.showPrevPage() + console.log(service._getSubscribers()) + } @@ -307,7 +304,7 @@ on:swipeThresholdReached={handleSwipeThresholdReached} style=" transform: translateX({offset}px); - transition-duration: {_duration}ms; + transition-duration: {durationMs}ms; transition-timing-function: {timingFunction}; " bind:this={particlesContainer} diff --git a/src/components/Carousel/carousel2.js b/src/components/Carousel/createCarousel.js similarity index 82% rename from src/components/Carousel/carousel2.js rename to src/components/Carousel/createCarousel.js index 7e298a7..be75c37 100644 --- a/src/components/Carousel/carousel2.js +++ b/src/components/Carousel/createCarousel.js @@ -1,36 +1,34 @@ +import simplyReactive from 'simply-reactive' + import { NEXT, PREV } from '../../direction' import { - applyParticleSizes, getCurrentPageIndexByCurrentParticleIndex, getPartialPageSize, getPagesCountByParticlesCount, getParticleIndexByPageIndex, - createResizeObserver, } from '../../utils/page' -import { getClones, applyClones, getClonesCount } from '../../utils/clones' +import { getClonesCount } from '../../utils/clones' import { getAdjacentIndexes } from '../../utils/lazy' import { getValueInRange } from '../../utils/math' import { get, switcher } from '../../utils/object' import { ProgressManager } from '../../utils/ProgressManager' -import { wait } from '../../utils/interval' -import simplyReactive from 'simply-reactive' -// return only getters -export const carousel2 = (onChange) => { +function createCarousel(onChange) { const progressManager = new ProgressManager({ onProgressValueChange: (value) => { onChange('progressValue', 1 - value) }, }) - const [data, methods] = simplyReactive( + const [data, methods, service] = simplyReactive( { particlesCountWithoutClones: 0, particlesToShow: 1, // normalized particlesToShowInit: 1, // initial value particlesToScroll: 1, // normalized particlesToScrollInit: 1, // initial value - initialPageIndex: 1, + initialPageIndex: 1, // normalized + initialPageIndexInit: 1, // initial value particlesCount: 1, currentParticleIndex: 1, infinite: false, @@ -46,10 +44,11 @@ export const carousel2 = (onChange) => { autoplay: false, autoplayDirection: 'next', disabled: false, // Disable page change while animation is in progress - duration: 1000, - _duration: 1000, + durationMsInit: 1000, + durationMs: 1000, offset: 0, particleWidth: 0, + loaded: [], }, { setCurrentPageIndex: (data) => { @@ -100,10 +99,12 @@ export const carousel2 = (onChange) => { } }, initDuration: (data) => { - data._duration = data.duration + data.durationMs = data.durationMsInit }, - applyAutoplay: (data, { applyAutoplayIfNeeded }) => { - applyAutoplayIfNeeded(data.autoplay) + applyAutoplay: (data, { _applyAutoplayIfNeeded }) => { + // prevent _applyAutoplayIfNeeded to be called with watcher + // to prevent its data added to deps + data.autoplay && _applyAutoplayIfNeeded(data.autoplay) }, setParticlesToShow(data) { data.particlesToShow = getValueInRange( @@ -119,6 +120,23 @@ export const carousel2 = (onChange) => { data.particlesCountWithoutClones ) }, + setInitialPageIndex(data) { + data.initialPageIndex = getValueInRange( + 1, + data.initialPageIndexInit, + data.pagesCount + ) + }, + setLoaded(data) { + data.loaded = getAdjacentIndexes({ + infinite: data.infinite, + pageIndex: data.currentPageIndex, + pagesCount: data.pagesCount, + particlesCount: data.particlesCountWithoutClones, + particlesToShow: data.particlesToShow, + particlesToScroll: data.particlesToScroll, + }).particleIndexes + }, }, { _prev: (data) => { @@ -156,7 +174,7 @@ export const carousel2 = (onChange) => { toggleFocused: (data) => { data.focused = !data.focused }, - applyAutoplayIfNeeded: async ( + async _applyAutoplayIfNeeded( { infinite, autoplayDirection, @@ -165,7 +183,7 @@ export const carousel2 = (onChange) => { autoplay, }, { showNextPage, showPrevPage } - ) => { + ) { // prevent progress change if not infinite for first and last page if ( !infinite && @@ -180,8 +198,8 @@ export const carousel2 = (onChange) => { if (autoplay) { const onFinish = () => switcher({ - [NEXT]: showNextPage, - [PREV]: showPrevPage, + [NEXT]: async () => showNextPage(), + [PREV]: async () => showPrevPage(), })(autoplayDirection) await progressManager.start(onFinish) @@ -221,7 +239,7 @@ export const carousel2 = (onChange) => { changePage: async ( data, - { offsetPage, applyAutoplayIfNeeded, _jumpIfNeeded }, + { offsetPage, _applyAutoplayIfNeeded, _jumpIfNeeded }, updateStoreFn, options ) => { @@ -234,7 +252,7 @@ export const carousel2 = (onChange) => { data.disabled = false const jumped = await _jumpIfNeeded() - !jumped && applyAutoplayIfNeeded() // no need to wait it finishes + !jumped && _applyAutoplayIfNeeded() // no need to wait it finishes }, showNextPage: async ({ disabled }, { changePage, _next }, options) => { if (disabled) return @@ -266,21 +284,22 @@ export const carousel2 = (onChange) => { options ) }, - offsetPage: (data, _, options) => { + offsetPage(data, _, options) { const animated = get(options, 'animated', true) return new Promise((resolve) => { - // _duration is an offset animation time - data._duration = animated ? data.duration : 0 + // durationMs is an offset animation time + data.durationMs = animated ? data.durationMsInit : 0 data.offset = -data.currentParticleIndex * data.particleWidth setTimeout(() => { resolve() - }, data._duration) + }, data.durationMs) }) }, }, onChange ) - return [{ data, progressManager }, methods] - // return [{ ...data, progressManager }, methods] + return [{ data, progressManager }, methods, service] } + +export default createCarousel