реагировать на нативную анимацию нескольких представлений в виде круга

Мне нужны 2 вида, которые одновременно трансформируются как круг без вращения. Первый вид начинается сверху, а второй вид снизу. Я уже спрашивал, как это сделать с одним видом. Я не запускаю его с двумя представлениями. Вопрос до

введите здесь описание изображения

//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,
    }
  });

person otto    schedule 21.12.2017    source источник
comment
Это действительно хороший вопрос об анимации нескольких объектов. Но у вас плохая тема, тут TypeError не при чем. Я думаю, именно поэтому получил отрицательный голос, измените свой вопрос, тогда он будет довольно хорошим.   -  person Val    schedule 21.12.2017


Ответы (2)


Чтобы сделать несколько анимаций одновременно, просто создайте из них несколько Animated.Value или interpolate несколько раз.

Движущаяся дорожка предназначена для вычисления translateX и translateY с помощью тригонометрической функции.

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,
      }
    });

Результат:

введите описание изображения здесь

person Val    schedule 21.12.2017
comment
спасибо, это работает очень хорошо :) Могу я спросить вас, как вы реализуете это маленькое видео в своем посте? - person otto; 21.12.2017
comment
Это GIF-изображение. Я использую GIPHY CAPTURE из магазина приложений для Mac. - person Val; 22.12.2017
comment
Возрождая этот вопрос, есть ли способ масштабировать размер элемента в верхней части основного круга и уменьшать другие на его основе? - person jinchuika; 17.08.2018
comment
можно ли продолжать анимацию без остановки? в настоящее время после завершения 1 раунда он останавливается на секунду и начинается снова. @Вал - person Neha Chauhan; 28.06.2019

Если вы ищете решение Butter smooth, похожее на вопрос реагировать на родную анимацию преобразования круга

Полный код


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',
},
});
person Aswin C    schedule 19.05.2020