import { State } from './index' ; import { Limitation } from '../env/limitation' ; import { EventHub , LIFE_CYCLES } from '../eventHub' ; import { Renderer } from '../render/index' ; import { Options } from '../options' ; import { Env } from '../env/index' ; export interface Operations { update ( ) : void ; render ( duration ? ) : void ; transform ( trans ) : void ; slideTo ( targetIndex , duration ? ) : void ; scrollPixel ( px ) : void ; initStatus ( startTransform ? ) : void ; initLayout ( originTransform ) : void ; getOffsetSteps ( offset ) : number ; } param velocity param transform param limitation export function isExceedingLimits ( velocity , transform , limitation ) { return velocity > 0 && transform > ( limitation . max ) || velocity < 0 && transform < ( limitation . min ) ; } param currentIndex param targetIndex param limitation param defaultWay export function getShortestWay ( currentIndex , targetIndex , limitation , defaultWay ) { const { maxIndex , minIndex } = limitation ; const shortcut = ( defaultWay > 0 ? 1 : - 1 ) * ( minIndex - maxIndex - 1 ) + targetIndex - currentIndex ; return Math . abs ( defaultWay ) > Math . abs ( shortcut ) ? shortcut : defaultWay ; } param transform param limitation export function getExcess ( transform , limitation ) { const exceedLeft = transform - limitation . max ; const exceedRight = transform - limitation . min ; return exceedLeft > 0 ? exceedLeft : exceedRight < 0 ? exceedRight : 0 ; } param env param state param options param renderer param eventHub constructor export function Operations ( env , state , options , renderer , eventHub ) { param offset function getOffsetSteps ( offset ) { const { measure } = env ; return Math . ceil ( Math . abs ( offset ) / measure . boxSize - options . longSwipesRatio ) ; } param duration param cb param force function render ( duration ? , cb ? , force ? ) { renderer . render ( state , duration , cb , force ) ; } param trans function transform ( trans ) { const { min , max } = env . limitation ; const transRange = max - min + ( options . loop ? env . measure . boxSize : 0 ) ; const len = transRange + 1 ; let progress ; state . transforms = trans ; if ( options . loop ) { progress = ( max - trans ) % len / transRange ; state . progress = progress < 0 ? 1 + progress : progress > 1 ? progress - 1 : progress ; } else { progress = ( max - trans ) / transRange ; state . progress = progress < 0 ? 0 : progress > 1 ? 1 : progress ; } eventHub . emit ( LIFE_CYCLES . SCROLL , { ... state } ) ; } param targetIndex param duration function slideTo ( targetIndex , duration ? ) { const { measure , limitation } = env ; const len = limitation . maxIndex - limitation . minIndex + 1 ; const computedIndex = options . loop ? ( targetIndex % len + len ) % len : targetIndex > limitation . maxIndex ? limitation . maxIndex : targetIndex < limitation . minIndex ? limitation . minIndex : targetIndex ; const newTransform = - computedIndex * measure . boxSize + limitation . base ; if ( getOffsetSteps ( newTransform - state . transforms ) !== 0 && options . loop ) { const excess = getExcess ( state . transforms , limitation ) ; const defaultWay = computedIndex - state . index ; const shortcut = getShortestWay ( state . index , computedIndex , limitation , defaultWay ) ; if ( shortcut !== defaultWay && ! excess ) { transform ( shortcut < 0 ? limitation . min - measure . boxSize : limitation . max + measure . boxSize ) ; } else if ( state . index === computedIndex ) { transform ( excess > 0 ? limitation . min - measure . boxSize + excess : limitation . max + measure . boxSize + excess ) ; } render ( 0 , undefined , true ) ; } eventHub . emit ( LIFE_CYCLES . BEFORE_SLIDE , state . index , state , computedIndex ) ; state . index = computedIndex ; transform ( newTransform ) ; render ( duration , ( ) => { eventHub . emit ( LIFE_CYCLES . AFTER_SLIDE , computedIndex , state ) ; } ) ; } param px function scrollPixel ( px ) { const { transforms } = state ; const { measure , limitation } = env ; const ratio = Number ( px . toExponential ( ) . split ( 'e' ) [ 1 ] ) ; const expand = ratio <= 0 ? Math . pow ( 10 , - ( ratio - 1 ) ) : 1 ; let newTransform = transforms ; if ( options . resistance && ! options . loop ) { if ( px > 0 && transforms >= limitation . max ) { px -= ( px * expand ) ** options . resistanceRatio / expand ; } else if ( px < 0 && transforms <= limitation . min ) { px += ( ( - px * expand ) ** options . resistanceRatio ) / expand ; } } newTransform += px ; if ( options . loop ) { const vector = state . tracker . vector ( ) ; const velocity = options . isHorizontal ? vector . velocityX : vector . velocityY ; const excess = getExcess ( transforms , limitation ) ; if ( excess && isExceedingLimits ( velocity , transforms , limitation ) ) { newTransform = excess > 0 ? limitation . min - measure . boxSize + excess : limitation . max + measure . boxSize + excess ; } } transform ( newTransform ) ; } function initStatus ( startTransform = 0 ) { state . startTransform = startTransform ; state . isStart = false ; state . isScrolling = false ; state . isTouching = false ; } function initLayout ( originTransform ) { transform ( originTransform ) ; } function update ( ) { slideTo ( state . index , 0 ) ; renderer . updateSize ( ) ; } return { update , render , transform , slideTo , scrollPixel , initStatus , initLayout , getOffsetSteps } ; }