UNPKG

@uiw/react-native

Version:
109 lines 2.39 kB
import React, { useState } from 'react'; import { Animated, Easing, Text, View } from 'react-native'; function Marquee(props) { // const [texts, setTexts] = useState({}); const [left, _setLeft] = useState(new Animated.Value(0)); const [state, setState] = useState({ twidth: 0, width: 0 }); function tryStart(state) { if (state.twidth > state.width && state.width) { startMove(); } } const onLayout = e => { if (state.twidth) { return; } const states = { ...state, twidth: e.nativeEvent.layout.width }; setState(states); tryStart(states); }; const onLayoutContainer = e => { if (!state.width) { const states = { ...state, width: e.nativeEvent.layout.width }; setState(states); left.setValue(0); tryStart(states); } }; const startMove = () => { const { fps = 40, loop } = props; const SPPED = 1 / fps * 1000; // tslint:disable-next-line:no-this-assignment Animated.timing(left, { toValue: 1, duration: state.twidth * SPPED, easing: Easing.linear, delay: props.leading, isInteraction: false, useNativeDriver: true }).start(() => { if (loop) { moveToHeader(); } }); }; const moveToHeader = () => { Animated.timing(left, { toValue: 0, duration: 0, delay: props.trailing, isInteraction: false, useNativeDriver: true }).start(() => { startMove(); }); }; const { width, twidth } = state; const { style, text, maxWidth } = props; const textChildren = <Text onLayout={onLayout} numberOfLines={1} ellipsizeMode="tail" style={style}> {text} </Text>; return <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }} onLayout={onLayoutContainer}> <Animated.View // tslint:disable-next-line:jsx-no-multiline-js style={{ flexDirection: 'row', transform: [{ translateX: left.interpolate({ inputRange: [0, 1], outputRange: [0, -twidth + width] }) }], width: maxWidth }}> {textChildren} </Animated.View> </View>; } Marquee.defaultProps = { text: '', loop: false, leading: 500, trailing: 800, fps: 40, maxWidth: 1000 }; export default Marquee;