Fix autoplay

This commit is contained in:
Vadim
2021-10-08 19:31:36 +03:00
parent 7652208ea9
commit 87a60678ba
2 changed files with 65 additions and 49 deletions

View File

@@ -30,26 +30,26 @@
import { ProgressManager } from '../../utils/ProgressManager' import { ProgressManager } from '../../utils/ProgressManager'
import { wait } from '../../utils/interval' import { wait } from '../../utils/interval'
import { carousel2 } from './carousel2' import createCarousel from './createCarousel'
// TODO: apply normalize value before saving to reactive
// TODO:
// used for lazy loading images, preloaded only current, adjacent and cloanable images
let loaded = []
let currentPageIndex let currentPageIndex
let focused = false let focused = false
let progressValue let progressValue
let offset = 0 let offset = 0
let _duration = 0 let durationMs = 0
let pagesCount = 1 let pagesCount = 1
const [{ data, progressManager }, methods] = carousel2((key, value) => { const [{ data, progressManager }, methods, service] = createCarousel((key, value) => {
switcher({ switcher({
'currentPageIndex': () => currentPageIndex = value, 'currentPageIndex': () => currentPageIndex = value,
'progressValue': () => progressValue = value, 'progressValue': () => progressValue = value,
'focused': () => focused = value, 'focused': () => focused = value,
'offset': () => offset = value, 'offset': () => offset = value,
'_duration': () => _duration = value, 'durationMs': () => durationMs = value,
'pagesCount': () => pagesCount = value, 'pagesCount': () => pagesCount = value,
'loaded': () => loaded = value,
})(key) })(key)
}) })
@@ -78,13 +78,16 @@
* Page to start on * Page to start on
*/ */
export let initialPageIndex = 0 export let initialPageIndex = 0
$: {
data.initialPageIndexInit = initialPageIndex
}
/** /**
* Transition duration (ms) * Transition duration (ms)
*/ */
export let duration = 500 export let duration = 500
$: { $: {
data.duration = duration data.durationMsInit = duration
} }
/** /**
@@ -160,7 +163,7 @@
export async function goToPrev(options) { export async function goToPrev(options) {
const animated = get(options, 'animated', true) const animated = get(options, 'animated', true)
await methods.showPrevPage({ animated }) await methods.showPrevPage({ animated })
} }
export async function goToNext(options) { export async function goToNext(options) {
@@ -187,17 +190,6 @@
methods.offsetPage({ animated: false }) 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() { function addClones() {
const { const {
clonesToAppend, clonesToAppend,
@@ -244,7 +236,7 @@
// gestures // gestures
function handleSwipeStart() { function handleSwipeStart() {
if (!swiping) return if (!swiping) return
data._duration = 0 data.durationMs = 0
} }
async function handleSwipeThresholdReached(event) { async function handleSwipeThresholdReached(event) {
if (!swiping) return if (!swiping) return
@@ -272,6 +264,11 @@
function handleTapped(event) { function handleTapped(event) {
methods.toggleFocused() methods.toggleFocused()
} }
function showPrevPage() {
methods.showPrevPage()
console.log(service._getSubscribers())
}
</script> </script>
<div class="sc-carousel__carousel-container"> <div class="sc-carousel__carousel-container">
@@ -282,7 +279,7 @@
<Arrow <Arrow
direction="prev" direction="prev"
disabled={!infinite && currentPageIndex === 0} disabled={!infinite && currentPageIndex === 0}
on:click={methods.showPrevPage} on:click={showPrevPage}
/> />
</div> </div>
</slot> </slot>
@@ -307,7 +304,7 @@
on:swipeThresholdReached={handleSwipeThresholdReached} on:swipeThresholdReached={handleSwipeThresholdReached}
style=" style="
transform: translateX({offset}px); transform: translateX({offset}px);
transition-duration: {_duration}ms; transition-duration: {durationMs}ms;
transition-timing-function: {timingFunction}; transition-timing-function: {timingFunction};
" "
bind:this={particlesContainer} bind:this={particlesContainer}

View File

@@ -1,36 +1,34 @@
import simplyReactive from 'simply-reactive'
import { NEXT, PREV } from '../../direction' import { NEXT, PREV } from '../../direction'
import { import {
applyParticleSizes,
getCurrentPageIndexByCurrentParticleIndex, getCurrentPageIndexByCurrentParticleIndex,
getPartialPageSize, getPartialPageSize,
getPagesCountByParticlesCount, getPagesCountByParticlesCount,
getParticleIndexByPageIndex, getParticleIndexByPageIndex,
createResizeObserver,
} from '../../utils/page' } from '../../utils/page'
import { getClones, applyClones, getClonesCount } from '../../utils/clones' import { getClonesCount } from '../../utils/clones'
import { getAdjacentIndexes } from '../../utils/lazy' import { getAdjacentIndexes } from '../../utils/lazy'
import { getValueInRange } from '../../utils/math' import { getValueInRange } from '../../utils/math'
import { get, switcher } from '../../utils/object' import { get, switcher } from '../../utils/object'
import { ProgressManager } from '../../utils/ProgressManager' import { ProgressManager } from '../../utils/ProgressManager'
import { wait } from '../../utils/interval'
import simplyReactive from 'simply-reactive'
// return only getters function createCarousel(onChange) {
export const carousel2 = (onChange) => {
const progressManager = new ProgressManager({ const progressManager = new ProgressManager({
onProgressValueChange: (value) => { onProgressValueChange: (value) => {
onChange('progressValue', 1 - value) onChange('progressValue', 1 - value)
}, },
}) })
const [data, methods] = simplyReactive( const [data, methods, service] = simplyReactive(
{ {
particlesCountWithoutClones: 0, particlesCountWithoutClones: 0,
particlesToShow: 1, // normalized particlesToShow: 1, // normalized
particlesToShowInit: 1, // initial value particlesToShowInit: 1, // initial value
particlesToScroll: 1, // normalized particlesToScroll: 1, // normalized
particlesToScrollInit: 1, // initial value particlesToScrollInit: 1, // initial value
initialPageIndex: 1, initialPageIndex: 1, // normalized
initialPageIndexInit: 1, // initial value
particlesCount: 1, particlesCount: 1,
currentParticleIndex: 1, currentParticleIndex: 1,
infinite: false, infinite: false,
@@ -46,10 +44,11 @@ export const carousel2 = (onChange) => {
autoplay: false, autoplay: false,
autoplayDirection: 'next', autoplayDirection: 'next',
disabled: false, // Disable page change while animation is in progress disabled: false, // Disable page change while animation is in progress
duration: 1000, durationMsInit: 1000,
_duration: 1000, durationMs: 1000,
offset: 0, offset: 0,
particleWidth: 0, particleWidth: 0,
loaded: [],
}, },
{ {
setCurrentPageIndex: (data) => { setCurrentPageIndex: (data) => {
@@ -100,10 +99,12 @@ export const carousel2 = (onChange) => {
} }
}, },
initDuration: (data) => { initDuration: (data) => {
data._duration = data.duration data.durationMs = data.durationMsInit
}, },
applyAutoplay: (data, { applyAutoplayIfNeeded }) => { applyAutoplay: (data, { _applyAutoplayIfNeeded }) => {
applyAutoplayIfNeeded(data.autoplay) // prevent _applyAutoplayIfNeeded to be called with watcher
// to prevent its data added to deps
data.autoplay && _applyAutoplayIfNeeded(data.autoplay)
}, },
setParticlesToShow(data) { setParticlesToShow(data) {
data.particlesToShow = getValueInRange( data.particlesToShow = getValueInRange(
@@ -119,6 +120,23 @@ export const carousel2 = (onChange) => {
data.particlesCountWithoutClones 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) => { _prev: (data) => {
@@ -156,7 +174,7 @@ export const carousel2 = (onChange) => {
toggleFocused: (data) => { toggleFocused: (data) => {
data.focused = !data.focused data.focused = !data.focused
}, },
applyAutoplayIfNeeded: async ( async _applyAutoplayIfNeeded(
{ {
infinite, infinite,
autoplayDirection, autoplayDirection,
@@ -165,7 +183,7 @@ export const carousel2 = (onChange) => {
autoplay, autoplay,
}, },
{ showNextPage, showPrevPage } { showNextPage, showPrevPage }
) => { ) {
// prevent progress change if not infinite for first and last page // prevent progress change if not infinite for first and last page
if ( if (
!infinite && !infinite &&
@@ -180,8 +198,8 @@ export const carousel2 = (onChange) => {
if (autoplay) { if (autoplay) {
const onFinish = () => const onFinish = () =>
switcher({ switcher({
[NEXT]: showNextPage, [NEXT]: async () => showNextPage(),
[PREV]: showPrevPage, [PREV]: async () => showPrevPage(),
})(autoplayDirection) })(autoplayDirection)
await progressManager.start(onFinish) await progressManager.start(onFinish)
@@ -221,7 +239,7 @@ export const carousel2 = (onChange) => {
changePage: async ( changePage: async (
data, data,
{ offsetPage, applyAutoplayIfNeeded, _jumpIfNeeded }, { offsetPage, _applyAutoplayIfNeeded, _jumpIfNeeded },
updateStoreFn, updateStoreFn,
options options
) => { ) => {
@@ -234,7 +252,7 @@ export const carousel2 = (onChange) => {
data.disabled = false data.disabled = false
const jumped = await _jumpIfNeeded() 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) => { showNextPage: async ({ disabled }, { changePage, _next }, options) => {
if (disabled) return if (disabled) return
@@ -266,21 +284,22 @@ export const carousel2 = (onChange) => {
options options
) )
}, },
offsetPage: (data, _, options) => { offsetPage(data, _, options) {
const animated = get(options, 'animated', true) const animated = get(options, 'animated', true)
return new Promise((resolve) => { return new Promise((resolve) => {
// _duration is an offset animation time // durationMs is an offset animation time
data._duration = animated ? data.duration : 0 data.durationMs = animated ? data.durationMsInit : 0
data.offset = -data.currentParticleIndex * data.particleWidth data.offset = -data.currentParticleIndex * data.particleWidth
setTimeout(() => { setTimeout(() => {
resolve() resolve()
}, data._duration) }, data.durationMs)
}) })
}, },
}, },
onChange onChange
) )
return [{ data, progressManager }, methods] return [{ data, progressManager }, methods, service]
// return [{ ...data, progressManager }, methods]
} }
export default createCarousel