react-native 走马灯效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z93701081/article/details/83826361
/**
 * @flow
 */
/* eslint react/no-did-mount-set-state: 0 */
import React, { Component } from 'react'
import {
  Text,
  View,
  Animated,
  Easing,
  StyleSheet,
  TouchableOpacity,
} from 'react-native'

const styles = StyleSheet.create({
  kbContainer: {
    // 必须要有一个背景或者一个border,否则本身高度将不起作用
    backgroundColor: 'transparent',
    overflow: 'hidden',
  },
  kb_text_c: {
    fontSize: 18,
    color: '#181818',
  },
})
type Props={
  scrollHeight: number,
  data: Array,
  textStyle: Object,
  scrollStyle: Object,
  kbContainer: Object,
  onChange: ()=>void,
  enableAnimation: boolean,
  duration:number,
  delay:number,
  onPress: ()=>void,
}

export default class ScrollVertical extends Component {
  static defaultProps = {
    enableAnimation: true,
  }

  constructor(props) {
    super(props)
    const translateValue = new Animated.ValueXY({ x: 0, y: 0 })
    // translateValue.addListener(({ x, y }) => {
    // })
    this.state = {
      translateValue,
      // 滚屏高度
      scrollHeight: this.props.scrollHeight || 32,
      // 滚屏内容
      kb_content: [],
      // Animated.View 滚动到的 y轴坐标
      kb_tempValue: 0,
      // 最大偏移量
      kb_contentOffsetY: 0,
      // 每一次滚动切换之前延迟的时间
      delay: this.props.delay || 500,
      // 每一次滚动切换的持续时间
      duration: this.props.duration || 500,
      enableAnimation: true,
    }
    this.createKbItem = this.createKbItem.bind(this)
  }
  state: {
    translateValue: any,
    scrollHeight: number,
    kb_content: Array,
    kb_tempValue: number,
    kb_contentOffsetY: number,
    delay: number,
    duration: number,
    enableAnimation: boolean
  }

  componentDidMount() {
    const content = this.props.data || []
    if (content.length !== 0) {
      const h = (content.length + 1) * this.state.scrollHeight
      this.setState({
        kb_content: content.concat(content[0]),
        kb_contentOffsetY: h,
      })

      // 开始动画
      // this._startAnimation()
      this.startAnimation()
    }
  }
  componentWillReceiveProps(nextProps) {
    this.setState({
      enableAnimation: nextProps.enableAnimation,
    }, () => {
      this.startAnimation()
    }
    )
  }

  componentWillUnmount() {
    if (this.animation) {
      clearTimeout(this.animation)
    }
    if (this.state.translateValue) {
      this.state.translateValue.removeAllListeners()
    }
  }
  overStep(name: string, num: number = 13) {
    if (name.length > num) {
      return `${name.substring(0, num)}...`
    }
    return name
  }
  createKbItem(kbItem, index) {
    return (
      <View
        key={index}
        style={[{
          justifyContent: 'center', height: this.state.scrollHeight }, this.props.scrollStyle]}
      >
        <TouchableOpacity
          onPress={() => this.props.onPress(kbItem.content)}
        >
          <Text style={[styles.kb_text_c, this.props.textStyle]}>
            {this.overStep(kbItem.title)}
          </Text>
        </TouchableOpacity>
      </View>
    )
  }
  startAnimation = () => {
    if (this.state.enableAnimation) {
      if (!this.animation) {
        this.animation = setTimeout(() => {
          this.animation = null
          this.startAnimationSeamless()
        }, this.state.delay)
      }
    }
  }

  startAnimationSeamless = () => {
    this.state.kb_tempValue -= this.state.scrollHeight
    if (this.props.onChange) {
      const index = Math.abs(this.state.kb_tempValue) / (this.state.scrollHeight)
      this.props.onChange(index < this.state.kb_content.length - 1 ? index : 0)
    }
    Animated.sequence([

      // Animated.delay(this.state.delay),
      Animated.timing(
        this.state.translateValue,
        {
          isInteraction: false,
          toValue: { x: 0, y: this.state.kb_tempValue },
          duration: this.state.duration, // 动画持续的时间(单位是毫秒),默认为500
          easing: Easing.linear,
        }
      ),
    ])
      .start(() => {
        // 无缝切换
        if (this.state.kb_tempValue - this.state.scrollHeight === -this.state.kb_contentOffsetY) {
          // 快速拉回到初始状态
          this.state.translateValue.setValue({ x: 0, y: 0 })
          this.state.kb_tempValue = 0
        }
        this.startAnimation()
      })
  }
  props: Props
  render() {
    return (
      <View
        style={[styles.kbContainer,
        { height: this.state.scrollHeight }, this.props.kbContainer]}
      >
        {
          this.state.kb_content.length !== 0 ?
            <Animated.View
              style={[
                { flexDirection: 'column' },
                { transform: [{ translateY: this.state.translateValue.y }],
                },
              ]}
            >
              {this.state.kb_content.map(this.createKbItem)}
            </Animated.View> : null
        }
      </View>
    )
  }
}


引入
import ScrollVertical from './ScrollVertical'


const dataArray = [
  {
    title: '保险全场五折',
    content: '保险全场五折,你买不了吃亏买不了上当嗷嗷嗷',
  },
  {
    title: '打到骨折',
    content: '骨折甩卖,全场骨折甩卖',
  },
]



    let arrayContent = [{ title: '', content: '' }]
    if (dataArray && dataArray.length > 0) {
      arrayContent = []
      for (const item of dataArray) {
        arrayContent.push({ title: item.title, content: item.content })
      }
    }


                  <ScrollVertical
                    onChange={(index => {
                      this.index = index
                    })}
                    onPress={(value: string) => {
                      this.setModalVisible(value)
                    }}
                    enableAnimation
                    data={arrayContent}
                    delay={2500}
                    duration={1000}
                    scrollHeight={34}
                    scrollStyle={{ alignItems: 'flex-start' }}
                    textStyle={{ fontSize: 14, color: '#000' }}
                  />


猜你喜欢

转载自blog.csdn.net/z93701081/article/details/83826361