React-native动画:尝试组合多个动画;出错

时间:2019-06-08 23:52:58

标签: javascript react-native animation

我正在尝试制作动画,从左上角的彩色正方形开始。单击它应将正方形移动到屏幕中心,同时将其缩放到其大小的两倍。然后,它应该翻转并显示背面。当我尝试在模拟器上加载应用程序时,出现此错误:

enter image description here

这是代码:

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

export default class App extends Component {
    state = {
        animation: new Animated.ValueXY(),
        scaleAnimation: new Animated.Value(1),
        rotateAnimation: new Animated.Value(0)
    };

    startAnimation = () => {
        const {width, height} = Dimensions.get("window");
        Animated.parallel([
            Animated.timing(this.state.animation.y, {
                toValue: (height / 2) - (this._height / 2),
                duration: 500,
                useNativeDriver: true
            }),
            Animated.timing(this.state.animation.x, {
                toValue: (width / 2) - (this._width / 2),
                duration: 500,
                useNativeDriver: true
            }),
            Animated.timing(this.state.scaleAnimation, {
                toValue: 2,
                duration: 500,
                useNativeDriver: true
            })
        ]).start(() => {
            Animated.timing(this.state.rotateAnimation, {
                toValue: 180,
                duration: 500,
                useNativeDriver: true
            }).start();
        })
    }

    saveDimensions = (e) => {
        this._width = e.nativeEvent.layout.width;
        this._height = e.nativeEvent.layout.height;
    }

    render() {
        const animatedStyles = {
            transform: [
                {
                    translateX: this.state.animation.x
                },
                {
                    translateY: this.state.animation.y
                },
                {
                    scale: this.state.scaleAnimation
                }
            ]
        }

        const frontInterpolate = this.state.rotateAnimation.interpolate({
            inputRange: [0, 180],
            outputRange: ['0deg', '180deg']
        })

        const backInterpolate = this.state.rotateAnimation.interpolate({
            inputRange: [0, 180],
            outputRange: ['180deg', '360deg']
        })

        const frontAnimatedStyle = {
            transform: [
                {
                    rotateY: this.frontInterpolate
                }
            ]
        }

        const backAnimatedStyle = {
            transform: [
                {
                    rotateY: this.backInterpolate
                }
            ]
        }

        return (
            <View style={styles.container}>
                <TouchableWithoutFeedback
                    onPress={() => this.startAnimation()}
                    onLayout={() => this.saveDimensions()}
                >
                    <View>
                        <Animated.View
                            style={[styles.box, animatedStyles, frontAnimatedStyle]}
                        >
                            <Text>Front</Text>
                        </Animated.View>
                        <Animated.View
                            style={[backAnimatedStyle, styles.box, styles.boxBack]}
                        >
                            <Text>Back</Text>
                        </Animated.View>
                    </View>
                </TouchableWithoutFeedback>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        //alignItems: 'center',
        //justifyContent: 'center',
    },
    box: {
        width: 150,
        height: 150,
        backgroundColor: 'tomato',
        position: 'absolute',
        top: 0,
        left: 0,
    },
    boxBack: {
        backgroundColor: 'green',
    },
});

我什至不知道动画是否可以正常播放,因为即使没有出现此错误,动画也无法加载。

1 个答案:

答案 0 :(得分:1)

这里是小吃https://snack.expo.io/@ziyoshams/frisky-watermelon,然后尝试检查代码。您的错误来自onLayout,但做了很多修改。这是代码:

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

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

export default class App extends Component {
  state = {
    animation: new Animated.ValueXY(),
    scaleAnimation: new Animated.Value(1),
    box1RotateAnimation: new Animated.Value(0),
    box2RotateAnimation: new Animated.Value(0),
  };

  startAnimation = () => {
    Animated.parallel([
      Animated.timing(this.state.animation.y, {
        toValue: height / 2 - this._height / 2,
        duration: 500,
        useNativeDriver: true,
      }),
      Animated.timing(this.state.animation.x, {
        toValue: width / 2 - this._width / 2,
        duration: 500,
        useNativeDriver: true,
      }),
      Animated.timing(this.state.scaleAnimation, {
        toValue: 2,
        duration: 500,
        useNativeDriver: true,
      }),
    ]).start(() => {
      Animated.sequence([
        Animated.timing(this.state.box1RotateAnimation, {
          toValue: 180,
          duration: 500,
          useNativeDriver: true,
        }),
        Animated.timing(this.state.box2RotateAnimation, {
          toValue: 180,
          duration: 500,
          useNativeDriver: true,
        }),
      ]).start();
    });
  };

  saveDimensions = e => {
    this._width = e.nativeEvent.layout.width;
    this._height = e.nativeEvent.layout.height;
  };

  render() {
    const frontInterpolate = this.state.box1RotateAnimation.interpolate({
      inputRange: [0, 180],
      outputRange: ['0deg', '90deg'],
    });

    const backInterpolate = this.state.box2RotateAnimation.interpolate({
      inputRange: [0, 180],
      outputRange: ['90deg', '0deg'],
    });

    const parentAnimation = {
      transform: [
        {
          translateX: this.state.animation.x,
          translateY: this.state.animation.y,
          scale: this.state.scaleAnimation,
        },
      ],
    };

    const box1Animation = {
      transform: [
        {
          rotateY: frontInterpolate,
        },
      ],
    };

    const box2Animation = {
      transform: [
        {
          rotateY: backInterpolate,
        },
      ],
    };

    return (
      <View style={styles.container}>
        <TouchableWithoutFeedback
          onPress={this.startAnimation}
          onLayout={this.saveDimensions}>
          <Animated.View style={[styles.box, parentAnimation]}>
            <Animated.View style={[styles.box1, box1Animation]}>
              <Text>Front</Text>
            </Animated.View>
            <Animated.View style={[styles.box2, box2Animation]}>
              <Text>Back</Text>
            </Animated.View>
          </Animated.View>
        </TouchableWithoutFeedback>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  box: {
    width: 150,
    height: 150,
    position: 'absolute',
    top: 0,
    left: 0,
  },
  box1: {
    width: 150,
    height: 150,
    backgroundColor: 'tomato',
    alignItems: 'center',
    justifyContent: 'center',
    position: 'absolute',
    top: 0,
    left: 0,
  },
  box2: {
    width: 150,
    height: 150,
    backgroundColor: 'green',
    alignItems: 'center',
    justifyContent: 'center',
    position: 'absolute',
    top: 0,
    left: 0,
  },
});