如何使用动画图像进行React Native倒计时?

时间:2017-05-23 07:55:03

标签: javascript reactjs animation react-native react-animated

我正在尝试创建一个反应原生动画,其中一些图像像这样倒计时:

3 --> ease out down duration 1 second each case
2 --> ease out down
1 --> ease out down

我找到了一种方法可以做出反应动画,但结果并不能说服我,如果有更好的方法可以让我知道。

我想每次我遇到一个新的元素渲染开始倒计时我说要做出动画反应,让每个数字的迭代减少3,改变图像数量,这不是解决问题的自然方法我有。

目前还没有使用redux,可能以后我会添加它。 状态的属性:时间,当前开始时间尚未使用。

我需要的只是在我定义的动画中,我所展示的图像发生倒计时的效果。

我认为差不多到了那里,但肯定有更好的方法来面对这个问题,任何建议都很受欢迎,即使它是一个指导。我也尝试过react-native-animate-number但没有运气......

提前致谢

import React from 'react';
import util from '../utils.js';
import * as Animatable from 'react-native-animatable';
import {
  View,
  Dimensions,
  Image,
  StyleSheet
} from 'react-native';

const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;

const styles = StyleSheet.create({
  mainOption: {
  },
  container: {
    width: width,
    height: height,
    flex: 1,
    justifyContent: 'center',
    flexDirection: 'column',
    alignItems: 'center'
  }
});
const timeLapse = [
              <Image source={require('../images/1.png')} key={util.uniqueId()}/>,
              <Image source={require('../images/2.png')} key={util.uniqueId()}/>,
              <Image source={require('../images/3.png')} key={util.uniqueId()}/>
];

export default class StartingGameCountDown extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      time: props.time,
      currentTimeToBegin: props.currentTimeToBegin,
      imagePosition: 0
    };
  }
  componentWillReceiveProps(nextProps) {
    const nextImage = this.state.imagePosition + 1;
    this.setState({
      ...this.state,
      letters: nextProps.time,
      currentTimeToBegin: nextProps.currentTimeToBegin,
      imagePosition: nextImage
    });
  }
  render() {
    return (
      <View style={styles.container}>
        <Animatable.View
               ref='countDown'
               duration={1000}
               delay={0}
               iterationCount={3}
               animation="fadeOutDown"
               style={styles.mainOption}>
          {timeLapse[this.state.imagePosition]}
        </Animatable.View>
      </View>
    );
  }
}

1 个答案:

答案 0 :(得分:0)

好了看了一下我发现可能正在使用序列和时间的文档可能是一个选项:

import React from 'react';
import {
  Animated,
  Text,
  View,
  Dimensions,
  Image,
  Easing,
  StyleSheet
} from 'react-native';

const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;

let counter = 0;
const util = {
  uniqueId: () => {
    return counter++;
  }
};

const styles = StyleSheet.create({
  mainOption: {
  },
  container: {
    width: width,
    height: height,
    top: -100,
    flex: 1,
    justifyContent: 'center',
    flexDirection: 'column',
    alignItems: 'center'
  }
});
const timeLapse = [
  require('../images/1.png'),
  require('../images/2.png'),
  require('../images/3.png')
];

export default class StartingGameCountDown extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      time: props.time,
      countDown: new Animated.Value(0),
      currentTimeToBegin: props.currentTimeToBegin,
      quantity: 3,
      sizes: [],
      duration: props.duration,
      animatedValues: [new Animated.Value(0), new Animated.Value(0), new Animated.Value(0)]
    };
  }
  animations() {
    let result = [];
    state = this.state;
    for(let i = 0; i < state.quantity; i++) {
      //Start
      result.push(Animated.timing(
            state.countDown,
            {
              toValue: 0,
              duration: 0
            }
          )
      );
      let parallel = [];
      //Animate
      for(let j = 0; j < state.quantity; j++) {
        parallel.push(
          Animated.timing(
              state.animatedValues[j],
              {
                easing: Easing.bezier(.07,.42,.85,.5),
                toValue: i === j ? 1 : 0,
                duration: i === j ? state.duration : 0
              }
            )
        );
      }
      //Stop
      parallel.push(Animated.timing(
            state.countDown,
            {
              easing: Easing.bezier(.07,.42,.85,.5),
              toValue: 1,
              duration: state.duration
            }
          )
      );

      result = [...result, Animated.parallel(parallel)];
    }
    return result;
  }
  componentDidMount() {
    Animated.sequence(this.animations()).start();
  }
  shouldComponentUpdate(nextProps, nextState) {
    //I don't to run lifecycle in any case by mistake here
    return false;
  }
  createImagesAnimated() {
    let transitionY = this.state.countDown.interpolate({
      inputRange: [0, 1],
      outputRange: [0, this.props.transition.y]
    });
    let result = [];
    //What to be Animated
    for(let i = 0; i < this.state.quantity; i++) {
      let image = this.state.animatedValues[i].interpolate({
        inputRange: [0, 0.5, 1],
        outputRange: [0, 1, 0]
      });
      result.push(
          <Animated.Image
              key={util.uniqueId()}
              source={timeLapse[i]}
              style={{
                //How to animate it
                  position: 'absolute',
                  opacity: image,
                  transform: [{
                    translateY: transitionY
                  }]
              }}
          />
      );
    }
    return result;
  }
  render() {
    return (
      <View style={styles.container}>
        {this.createImagesAnimated()}
      </View>
    );
  }
}

这将是组件的实现:

    <CountDownComponent
      transition={{y:200}}
      duration={5000}
    />

这解决了我的问题,我希望在未来能够找到更好的解决方案。

这是回购: https://github.com/jotaoncode/CountDown