import { Position } from '../state/trace' ; import { Options } from '../options' ; import { Env } from '../env/index' ; import { State } from '../state/index' ; import { Operations } from '../state/operations' ; import { Animation } from '../render/animation' ; export type Actions = { preheat ( originPosition , originTransform ) : void ; move ( position ) : void ; stop ( ) : void ; } ; function resetState ( state , operations ) { const { tracker } = state ; const { initStatus } = operations ; tracker . clear ( ) ; initStatus ( ) ; } export function Actions ( options , env , state , operations ) { const { initLayout , initStatus , render , scrollPixel , slideTo , getOffsetSteps } = operations ; const animation = Animation ( ) ; function preheat ( originPosition , originTransform ) { const { tracker } = state ; animation . stop ( ) ; tracker . clear ( ) ; tracker . push ( originPosition ) ; initLayout ( originTransform ) ; initStatus ( originTransform ) ; state . isStart = true ; render ( ) ; } function move ( position ) { const { tracker } = state ; const { touchRatio , touchAngle , isHorizontal } = options ; if ( ! state . isStart || state . isScrolling ) return ; tracker . push ( position ) ; const vector = tracker . vector ( ) ; const displacement = tracker . getOffset ( ) ; if ( ! displacement . x && ! displacement . y ) return ; if ( ( isHorizontal && ( vector . angle < touchAngle ) ) || ( ! isHorizontal && ( 90 - vector . angle ) < touchAngle ) || state . isTouching ) { const offset = vector [ isHorizontal ? 'x' : 'y' ] * touchRatio ; state . isTouching = true ; scrollPixel ( offset ) ; render ( ) ; } else { state . isScrolling = true ; tracker . clear ( ) ; } } function stop ( ) { const { index , tracker } = state ; const { measure } = env ; if ( ! state . isStart ) return ; state . isStart = false ; if ( ! options . freeMode ) { const duration = tracker . getDuration ( ) ; const trans = tracker . getOffset ( ) [ options . isHorizontal ? 'x' : 'y' ] ; const jump = Math . ceil ( Math . abs ( trans ) / measure . boxSize ) ; const longSwipeIndex = getOffsetSteps ( trans ) ; if ( duration > options . longSwipesMs ) { slideTo ( index + longSwipeIndex * ( trans > 0 ? - 1 : 1 ) ) ; } else { slideTo ( trans > 0 ? index - jump : index + jump ) ; } resetState ( state , operations ) ; } else { const vector = tracker . vector ( ) ; let velocity = vector [ options . isHorizontal ? 'velocityX' : 'velocityY' ] ; animation . run ( ( duration ) => { const offset = velocity * duration ; velocity *= 0.98 ; if ( Math . abs ( offset ) < 0.01 ) { animation . stop ( ) ; resetState ( state , operations ) ; } else { scrollPixel ( offset ) ; render ( 0 ) ; } } ) ; } } return { preheat , move , stop } ; }