将多个视图的原生动画作为一个圆圈进行反应

时间:2017-12-21 10:36:50

标签: javascript reactjs react-native react-animated

我想要2个视图,它们像圆圈一样变换,同时没有旋转。第一个视图从顶部开始,第二个视图从底部开始。我已经问过如何用一个视图做到这一点。我不认为它运行两个视图。 Question Before

enter image description here

//import liraries
import React, { Component } from 'react';
import { View, Text, StyleSheet, Animated, Button, TouchableOpacity } from 'react-native';

// create a component
export default class App extends Component {
  constructor() {
      super()
      this.animated = new Animated.Value(0);
      this.animated2 = new Animated.Value(0);

      var range = 1, snapshot = 50, radius = 100;
      /// translateX
      var inputRange = []
      var outputRange = [] 
      var outputRange2 = []
      for (var i=0; i<=snapshot; ++i) {
          var value = i/snapshot;
          var move = Math.sin(value * Math.PI * 2) * radius;
          inputRange.push(value);
          outputRange.push(move);
          outputRange2.push(-move);
      }
      translateX = this.animated.interpolate({ inputRange, outputRange });
      translateX2 = this.animated2.interpolate({inputRange, outputRange2})

      /// translateY
      var inputRange = [] 
      var outputRange = []
      var outputRange2 = []
      for (var i=0; i<=snapshot; ++i) {
          var value = i/snapshot;
          var move = -Math.cos(value * Math.PI * 2) * radius;
          inputRange.push(value);
          outputRange.push(move);
          outputRange2.push(-move);
      }
      translateY = this.animated.interpolate({ inputRange, outputRange });
      translateY2 = this.animated2.interpolate({inputRange, outputRange2})

  }

    animate() {
      this.animated.setValue(0)
      Animated.timing(this.animated, {
        toValue: 1,
        duration: 10000,
      }).start();
      this.animated2.setValue(0)
      Animated.timing(this.animated2, {
        toValue: 1,
        duration: 10000,
      }).start();
    }


    render() {
      //const transform = [{ translateY: this.translateY }, {translateX: this.translateX}];
      return (
        <View style={styles.container}>
          <Animated.View style={
            [{ transform: [{ translateY: translateY }, {translateX: translateX}] }]}>
            <TouchableOpacity style={styles.btn}>
              <Text>hallo</Text>
            </TouchableOpacity>
          </Animated.View>
          <Animated.View style={
            [{ transform: [{ translateY: translateY2 }, {translateX: translateX2}] }]}>
            <TouchableOpacity style={styles.btn}>
              <Text>hallo</Text>
            </TouchableOpacity>
          </Animated.View>
          <Button title="Test" onPress={() => { 
            this.animate() 
            }} />
        </View>
      );
    }
  }

  // define your styles
  const styles = StyleSheet.create({
    container: {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor: '#2c3e50',
    },
    btn2: {
      justifyContent: 'center',      
      alignItems: 'flex-end',
      alignSelf: 'flex-end'
    },
    btn: {
      backgroundColor: 'red',
      justifyContent: 'center',
      alignItems: 'center',
      width: 50,
    }
  });

2 个答案:

答案 0 :(得分:6)

要同时制作多个动画,只需多次创建多个Animated.Valueinterpolate

移动轨道是关于使用三角函数计算translateXtranslateY

translateX对应Math.sin()translateY对应Math.cos()

选项二的代码(多次插入一个Animated.Value):

export class App extends Component {
    constructor() {
        super()
        this.animated = new Animated.Value(0);

        var range = 1, snapshot = 50, radius = 100;

        /// translateX
        var inputRange = [], outputRange = [];
        for (var i=0; i<=snapshot; ++i) {
            var value = i/snapshot;
            var move = Math.sin(value * Math.PI * 2) * radius;
            inputRange.push(value);
            outputRange.push(move);
        }
        this.translateX = this.animated.interpolate({ inputRange, outputRange });

        /// translateY
        var inputRange = [], outputRange = [];
        for (var i=0; i<=snapshot; ++i) {
            var value = i/snapshot;
            var move = -Math.cos(value * Math.PI * 2) * radius;
            inputRange.push(value);
            outputRange.push(move);
        }
        this.translateY = this.animated.interpolate({ inputRange, outputRange });

        /// translateX2
        var inputRange = [], outputRange = [];
        for (var i=0; i<=snapshot; ++i) {
            var value = i/snapshot;
            var move = Math.sin((value + 1/2) * Math.PI * 2) * radius;
            inputRange.push(value);
            outputRange.push(move);
        }
        this.translateX2 = this.animated.interpolate({ inputRange, outputRange });

        /// translateY2
        var inputRange = [], outputRange = [];
        for (var i=0; i<=snapshot; ++i) {
            var value = i/snapshot;
            var move = -Math.cos((value + 1/2) * Math.PI * 2) * radius;
            inputRange.push(value);
            outputRange.push(move);
        }
        this.translateY2 = this.animated.interpolate({ inputRange, outputRange });

    }

      animate() {
        this.animated.setValue(0)
        Animated.loop(
            Animated.timing(this.animated, {
                toValue: 1,
                duration: 1000,
              })
        ).start();
      }


      render() {
        const transform = [{ translateY: this.translateY }, {translateX: this.translateX}];
        const transform2 = [{ translateY: this.translateY2 }, {translateX: this.translateX2}];
        return (
          <View style={styles.container}>
            <Animated.View style={[{ transform }]}>
              <TouchableOpacity style={styles.btn}>
                <Text>hallo</Text>
              </TouchableOpacity>
            </Animated.View>

            <Animated.View style={[{ transform: transform2 }]}>
              <TouchableOpacity style={styles.btn}>
                <Text>hallo</Text>
              </TouchableOpacity>
            </Animated.View>

            <Button title="Test" onPress={() => { 
              this.animate() 
              }} />
          </View>
        );
      }
    }

    // define your styles
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#2c3e50',
      },
      btn: {
        backgroundColor: 'red',
        justifyContent: 'center',
        alignItems: 'center',
        width: 50,
      }
    });

<强>结果:

enter image description here

答案 1 :(得分:0)

如果您正在寻找类似于问题react native circle transform translate animation

黄油平滑 解决方案

完整代码


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

export default class Circle extends Component {
constructor() {
    super();
    this.animated = new Animated.Value(0);
    var inputRange = [0, 1];
    var outputRange = ['0deg', '360deg'];
    this.rotate = this.animated.interpolate({inputRange, outputRange});
    outputRange = ['0deg', '-360deg'];
    this.rotateOpposit = this.animated.interpolate({inputRange, outputRange});
}

componentDidMount() {
    this.animate();
}

animate() {
    Animated.loop(
    Animated.timing(this.animated, {
        toValue: 1,
        duration: 4000,
        useNativeDriver: true,
        easing: Easing.linear,
    }),
    ).start();
}
render() {
    const transform = [{rotate: this.rotate}];
    const transform1 = [{rotate: this.rotateOpposit}];
    return (
    <View style={styles.container}>
        <Animated.View style={[styles.item, {transform}]}>
        <Animated.View style={[styles.topItem, {transform: transform1}]}>
            <Text style={styles.text}>Test</Text>
        </Animated.View>
        <Animated.View style={[styles.bottomItem, {transform: transform1}]}>
            <Text style={styles.text}>Test</Text>
        </Animated.View>
        </Animated.View>
    </View>
    );
}
}
const styles = StyleSheet.create({
container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
},
item: {
    position: 'absolute',

    width: 100,
    height: 200, //this is the diameter here
},
topItem: {
    width: '100%',
    height: 20,
    backgroundColor: 'red',
    position: 'absolute',
    alignItems: 'center',
    justifyContent: 'center',
},
bottomItem: {
    width: '100%',
    height: 20,
    backgroundColor: 'red',
    position: 'absolute',
    bottom: 0,
    alignItems: 'center',
    justifyContent: 'center',
},
text: {
    color: '#fff',
},
});