carouselVertical.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import React, { Component } from 'react'
  2. import { Text, View, Animated, Easing, StyleSheet } from 'react-native'
  3. export default class carouselVertical extends Component {
  4. static defaultProps = {
  5. enableAnimation: true,
  6. content: 'content',
  7. title: 'title',
  8. }
  9. constructor(props) {
  10. super(props)
  11. let translateValue = new Animated.ValueXY({ x: 0, y: 0 })
  12. translateValue.addListener(({ x, y }) => {})
  13. this.state = {
  14. translateValue: translateValue,
  15. scrollHeight: this.props.scrollHeight || 32,
  16. kb_content: [],
  17. kb_tempValue: 0,
  18. kb_contentOffsetY: 0,
  19. delay: this.props.delay || 500,
  20. duration: this.props.duration || 500,
  21. enableAnimation: true,
  22. }
  23. }
  24. render() {
  25. return (
  26. <View
  27. style={[
  28. styles.kbContainer,
  29. { height: this.state.scrollHeight },
  30. this.props.kbContainer,
  31. ]}
  32. >
  33. {this.state.kb_content.length !== 0 ? (
  34. <Animated.View
  35. style={[
  36. {
  37. flexDirection: 'column',
  38. },
  39. {
  40. transform: [{ translateY: this.state.translateValue.y }],
  41. },
  42. ]}
  43. >
  44. {this.state.kb_content.map(this._createKbItem.bind(this))}
  45. </Animated.View>
  46. ) : null}
  47. </View>
  48. )
  49. }
  50. componentWillReceiveProps(nextProps) {
  51. this.setState(
  52. {
  53. enableAnimation: nextProps.enableAnimation ? true : false,
  54. },
  55. () => {
  56. this.startAnimation()
  57. }
  58. )
  59. }
  60. componentDidMount() {
  61. let content = this.props.data || []
  62. if (content.length !== 0) {
  63. let h = (content.length + 1) * this.state.scrollHeight
  64. this.setState({
  65. kb_content: content.concat(content[0]),
  66. kb_contentOffsetY: h,
  67. })
  68. this.startAnimation()
  69. }
  70. }
  71. _createKbItem(kbItem, index) {
  72. return (
  73. <View
  74. key={index}
  75. style={[
  76. {
  77. height: this.state.scrollHeight,
  78. justifyContent: 'center',
  79. },
  80. this.props.scrollStyle,
  81. ]}
  82. >
  83. <Text numberOfLines={1} style={this.props.textStyle}>
  84. <Text style={this.props.titleStyle}>
  85. {kbItem[this.props.title] || null}
  86. </Text>{' '}
  87. {kbItem[this.props.content]}
  88. </Text>
  89. </View>
  90. )
  91. }
  92. startAnimation = () => {
  93. if (this.state.enableAnimation) {
  94. if (!this.animation) {
  95. this.animation = setTimeout(() => {
  96. this.animation = null
  97. this._startAnimation()
  98. }, this.state.delay)
  99. }
  100. }
  101. }
  102. componentWillUnmount() {
  103. if (this.animation) {
  104. clearTimeout(this.animation)
  105. }
  106. if (this.state.translateValue) {
  107. this.state.translateValue.removeAllListeners()
  108. }
  109. }
  110. _startAnimation = () => {
  111. this.state.kb_tempValue -= this.state.scrollHeight
  112. if (this.props.onChange) {
  113. let index = Math.abs(this.state.kb_tempValue) / this.state.scrollHeight
  114. this.props.onChange(index < this.state.kb_content.length - 1 ? index : 0)
  115. }
  116. Animated.sequence([
  117. Animated.timing(this.state.translateValue, {
  118. isInteraction: false,
  119. toValue: { x: 0, y: this.state.kb_tempValue },
  120. duration: this.state.duration,
  121. easing: Easing.linear,
  122. }),
  123. ]).start(() => {
  124. if (
  125. this.state.kb_tempValue - this.state.scrollHeight ===
  126. -this.state.kb_contentOffsetY
  127. ) {
  128. this.state.translateValue.setValue({ x: 0, y: 0 })
  129. this.state.kb_tempValue = 0
  130. }
  131. this.startAnimation()
  132. })
  133. }
  134. }
  135. const styles = StyleSheet.create({
  136. kbContainer: {
  137. backgroundColor: 'transparent',
  138. overflow: 'hidden',
  139. },
  140. })