import React from 'react' ; import { Animated , Easing , LayoutChangeEvent , StyleProp , Text , TextStyle , View } from 'react-native' ; export interface MarqueeProps { text ? : React . ReactNode ; loop ? : boolean ; leading ? : number ; trailing ? : number ; className ? : string ; fps ? : number ; style ? : StyleProp < TextStyle > ; maxWidth ? : number ; } class Marquee extends React . PureComponent < MarqueeProps , any > { static defaultProps = { text : '' , loop : false , leading : 500 , trailing : 800 , fps : 40 , maxWidth : 1000 , } ; texts : any ; left : any ; constructor ( props ) { super ( props ) ; this . texts = { } ; this . left = new Animated . Value ( 0 ) ; this . state = { twidth : 0 , width : 0 , } ; } onLayout = ( e ) => { if ( this . state . twidth ) { return ; } this . setState ( { twidth : e . nativeEvent . layout . width , } , ( ) => { this . tryStart ( ) ; } ) ; } ; tryStart ( ) { if ( this . state . twidth > this . state . width && this . state . width ) { this . startMove ( ) ; } } onLayoutContainer = ( e ) => { if ( ! this . state . width ) { this . setState ( { width : e . nativeEvent . layout . width , } , ( ) => { this . left . setValue ( 0 ) ; this . tryStart ( ) ; } ) ; } } ; startMove = ( ) => { const { fps = 40 , loop } = this . props ; const SPPED = ( 1 / fps ) * 1000 ; const { props } = this ; Animated . timing ( this . left , { toValue : 1 , duration : this . state . twidth * SPPED , easing : Easing . linear , delay : props . leading , isInteraction : false , useNativeDriver : true , } ) . start ( ( ) => { if ( loop ) { this . moveToHeader ( ) ; } } ) ; } ; moveToHeader = ( ) => { Animated . timing ( this . left , { toValue : 0 , duration : 0 , delay : this . props . trailing , isInteraction : false , useNativeDriver : true , } ) . start ( ( ) => { this . startMove ( ) ; } ) ; } ; render ( ) { const { width , twidth } = this . state ; const { style , text , maxWidth } = this . props ; const textChildren = ( < Text onLayout = { this . onLayout } numberOfLines = { 1 } ellipsizeMode = "tail" style = { style } > { text } < /Text>); return ( < View style = { { flex : 1 , flexDirection : 'row' , alignItems : 'center' } } onLayout = { this . onLayoutContainer } > < Animated . View style = { { flexDirection : 'row' , transform : [ { translateX : this . left . interpolate ( { inputRange : [ 0 , 1 ] , outputRange : [ 0 , - twidth + width ] , } ) , } , ] , width : maxWidth , } } > { textChildren } < /Animated.View> < /View>); } } export default Marquee ;