import { EasingFunction , Easing , Animated , Platform } from 'react-native' ; function createKeyframeEasingFunction ( keyframes , easing ) { return ( t ) => { for ( let keyframeIndex = 1 ; keyframeIndex < keyframes . length ; keyframeIndex ++ ) { if ( t < keyframes [ keyframeIndex ] / 100 ) { const prev = keyframes [ keyframeIndex - 1 ] / 100 ; const current = ( keyframes [ keyframeIndex ] - keyframes [ keyframeIndex - 1 ] ) / 100 ; return prev + easing ( ( t - prev ) / current ) * current ; } } return t ; } ; } interface AnimationConfig { duration : number ; value : Animated . Value ; keyframes ? : number [ ] ; toValue ? : number ; easing ? : EasingFunction ; } function loop ( { duration , value , keyframes = [ 0 , 100 ] , easing = Easing . bezier ( 0.42 , 0.0 , 0.58 , 1.0 ) , toValue = 100 , } ) { const timing = Animated . timing ( value , { duration : duration , easing : createKeyframeEasingFunction ( keyframes , easing ) , toValue : toValue , useNativeDriver : Platform . OS !== 'web' } ) ; return Animated . loop ( timing ) ; } function stagger ( time , amount , animationConfig ) { const { duration , value , keyframes = [ 0 , 100 ] , easing = Easing . bezier ( 0.42 , 0.0 , 0.58 , 1.0 ) , toValue = 100 , } = animationConfig ; const easingFunction = createKeyframeEasingFunction ( keyframes , easing ) ; if ( Platform . OS === 'web' ) { const values = new Array ( amount ) . fill ( null ) . map ( ( _ ) => new Animated . Value ( 0 ) ) ; const animations = values . map ( ( value ) => loop ( { value , duration , easing , toValue , keyframes } ) ) ; const animation = Animated . stagger ( time , animations ) ; return { animation , values } ; } const timing = Animated . timing ( value , { duration : duration , easing : easingFunction , toValue : toValue , useNativeDriver : true } ) ; const animation = Animated . loop ( timing ) ; const frameDuration = 1000.0 / 60.0 ; const inputRange = [ ] ; const numFrames = Math . round ( animationConfig . duration / frameDuration ) ; for ( let frame = 0 ; frame < numFrames ; frame ++ ) { inputRange . push ( easingFunction ( frame / numFrames ) * 100 ) ; } const values = [ ] ; for ( let index = amount - 1 ; index >= 0 ; index -- ) { const delayedFrames = Math . round ( ( ( index * time ) / animationConfig . duration ) * numFrames ) ; const outputRange = inputRange . slice ( delayedFrames ) . concat ( inputRange . slice ( 0 , delayedFrames ) ) ; const value = index === 0 ? animationConfig . value : animationConfig . value . interpolate ( { inputRange , outputRange } ) ; values . push ( value ) ; } return { animation , values } ; } export { loop , stagger , AnimationConfig } ;