4

I want 2 views which transform like a circle with no rotation at the same time. The first view starts at the top and the second view at the bottom. I already asked how to do it with one view. I dont get it run with two views. 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,
    }
  });
Val
  • 21,938
  • 10
  • 68
  • 86
otto
  • 1,815
  • 7
  • 37
  • 63
  • This is a really good question about animating multiple objects. But you got bad topic, there's nothing to do with TypeError. I think that's why got downvote, modify your question then it would be a pretty good one. – Val Dec 21 '17 at 11:17

2 Answers2

10

To make multiple animations at the same time, just create multiple Animated.Value, or interpolate from it multiple times.

The moving track is about calculate translateX and translateY with Trigonometric Function.

translateX is corresponding to Math.sin(), and translateY is corresponding to Math.cos().

Code for option two (interpolate from one Animated.Value multiple times):

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

Result:

enter image description here

Val
  • 21,938
  • 10
  • 68
  • 86
  • thank you it works very fine :) Can i ask you how you implement this little video in your post? – otto Dec 21 '17 at 17:46
  • 2
    It's an GIF image. I use *GIPHY CAPTURE* from Mac app store. – Val Dec 22 '17 at 05:30
  • Reviving this question, is there a way to scale the size of the element in the top of the main circle and shrink the other ones based on that? – jinchuika Aug 17 '18 at 13:12
  • is it possible to continues animating without stop? currently, once 1 round completed it's stopped for a sec and start again. @Val – Neha Chauhan Jun 28 '19 at 06:35
0

If you are looking for a Butter smooth solution similar to the question react native circle transform translate animation

Full code


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',
},
});
Aswin C
  • 1,152
  • 7
  • 12