react-native版文字跑马灯
首页 专栏 react-native 文章详情
0

react-native版文字跑马灯

xpin 发布于 今天 03:17

js部分

interface IProps {
  text: string,
  style?: object,
}
interface IState {
  transformX: any,
  viewWidth: number,
  textWidth: number,
}

const FlexItem = Flex.Item;
const Speed = 10000
export default class Notice extends React.PureComponent<IProps, IState> {
  state: IState = {
    transformX: new Animated.Value(0),
    viewWidth: 0,
    textWidth: 0,
  }
  constructor (props: IProps) {
    super(props)
  }
  onTextLayout = (event: any) => {
    const { width } = event.nativeEvent.layout;
    this.setState({
      textWidth: width
    })
  }
  onViewLayout = (event: any) => {
    const { width } = event.nativeEvent.layout;
    this.setState({
      viewWidth: width
    })
  }
  move () {
    const { viewWidth, textWidth, transformX } = this.state;
    if (textWidth > viewWidth) {
      let duration = Speed
      duration += ((textWidth - viewWidth) / viewWidth) * Speed;
      transformX.setValue(viewWidth)
      Animated.timing(transformX, {
        toValue: -textWidth,
        duration: duration,
        easing: Easing.linear,
        useNativeDriver: false
      }).start(({finished}) => {
        if (finished) {
          this.move()
        }
      })
    }
  }
  componentDidUpdate () {
    this.move()
  }
  renderContent(text: string) {
    const { transformX, textWidth } = this.state;
    return <Animated.View style={[styles.animatedView, { width: textWidth, transform: [{ translateX: transformX }] }]}>
      <Text numberOfLines={1}>
        {text}
      </Text>
    </Animated.View>
  }
  render() {
    const { text, style = {} } = this.props;
    return <View onLayout={this.onViewLayout} style={[styles.view, style]}>
      <Flex direction="row">
        <FlexItem style={{ flexDirection: 'row' }}>
          {this.renderContent(text)}
        </FlexItem>
      </Flex>
      <View style={styles.hide}>
        <Text onLayout={this.onTextLayout} numberOfLines={1} style={[styles.hide]}>
          {text}
        </Text>
      </View>
    </View>
  }
}

css部分

const styles = StyleSheet.create({
  view: {
    paddingVertical: 24,
    overflow: 'hidden'
  },
  normalView: {
    paddingLeft: 24,
  },
  animatedView: {
    flexDirection: 'row',
  },
  hide: {
    flexDirection: 'row',
    opacity: 0,
    zIndex: -1,
    position: 'absolute',
    top: 0,
  },
});
react-native animate
阅读 34 更新于 今天 03:26
收藏
分享
本作品系原创, 采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
avatar
xpin
16 声望
0 粉丝
关注作者
0 条评论
得票 时间
提交评论
avatar
xpin
16 声望
0 粉丝
关注作者
宣传栏
目录

js部分

interface IProps {
  text: string,
  style?: object,
}
interface IState {
  transformX: any,
  viewWidth: number,
  textWidth: number,
}

const FlexItem = Flex.Item;
const Speed = 10000
export default class Notice extends React.PureComponent<IProps, IState> {
  state: IState = {
    transformX: new Animated.Value(0),
    viewWidth: 0,
    textWidth: 0,
  }
  constructor (props: IProps) {
    super(props)
  }
  onTextLayout = (event: any) => {
    const { width } = event.nativeEvent.layout;
    this.setState({
      textWidth: width
    })
  }
  onViewLayout = (event: any) => {
    const { width } = event.nativeEvent.layout;
    this.setState({
      viewWidth: width
    })
  }
  move () {
    const { viewWidth, textWidth, transformX } = this.state;
    if (textWidth > viewWidth) {
      let duration = Speed
      duration += ((textWidth - viewWidth) / viewWidth) * Speed;
      transformX.setValue(viewWidth)
      Animated.timing(transformX, {
        toValue: -textWidth,
        duration: duration,
        easing: Easing.linear,
        useNativeDriver: false
      }).start(({finished}) => {
        if (finished) {
          this.move()
        }
      })
    }
  }
  componentDidUpdate () {
    this.move()
  }
  renderContent(text: string) {
    const { transformX, textWidth } = this.state;
    return <Animated.View style={[styles.animatedView, { width: textWidth, transform: [{ translateX: transformX }] }]}>
      <Text numberOfLines={1}>
        {text}
      </Text>
    </Animated.View>
  }
  render() {
    const { text, style = {} } = this.props;
    return <View onLayout={this.onViewLayout} style={[styles.view, style]}>
      <Flex direction="row">
        <FlexItem style={{ flexDirection: 'row' }}>
          {this.renderContent(text)}
        </FlexItem>
      </Flex>
      <View style={styles.hide}>
        <Text onLayout={this.onTextLayout} numberOfLines={1} style={[styles.hide]}>
          {text}
        </Text>
      </View>
    </View>
  }
}

css部分

const styles = StyleSheet.create({
  view: {
    paddingVertical: 24,
    overflow: 'hidden'
  },
  normalView: {
    paddingLeft: 24,
  },
  animatedView: {
    flexDirection: 'row',
  },
  hide: {
    flexDirection: 'row',
    opacity: 0,
    zIndex: -1,
    position: 'absolute',
    top: 0,
  },
});