Реактивная анимация: попытка объединить несколько анимаций; получать ошибку - PullRequest
0 голосов
/ 09 июня 2019

Я пытаюсь сделать анимацию, где я начинаю с цветного квадрата в верхнем левом углу. Нажав на него, вы должны переместить квадрат в центр экрана, увеличив его в два раза. Затем он должен перевернуться и показать обратную сторону. Когда я пытаюсь загрузить приложение на эмуляторе, я получаю эту ошибку:

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 Ответ

1 голос
/ 09 июня 2019

Вот закуска 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,
  },
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...