最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Circling motion animation in React Native - Stack Overflow

programmeradmin2浏览0评论

I need to create an animation with an image that will circle around another image. I have already tried to use suggestions from a similar question like Animate a Circle around another circle , but unfortunately it didn't help. I tried looking into 3rd party modules that would offer the desirable functionality, but haven't found something that would fit my need.

I found a helpful article to understand the circular motion in JavaScript, however I have a hard time to replicate it in React Native animation. I believe I simply have a hard time understanding a proper usage of Animated API and transform style properties when it es to animating circular movement.


<View style={animationContainer}>
    <Image
      source={require('./images/image.png')}
      style={image}
    />
    <Animated.Image
      source={require('./images/icon.png')}
      style={circlingIcon}
    />
</View>

I need to create an animation with an image that will circle around another image. I have already tried to use suggestions from a similar question like Animate a Circle around another circle , but unfortunately it didn't help. I tried looking into 3rd party modules that would offer the desirable functionality, but haven't found something that would fit my need.

I found a helpful article to understand the circular motion in JavaScript, however I have a hard time to replicate it in React Native animation. I believe I simply have a hard time understanding a proper usage of Animated API and transform style properties when it es to animating circular movement.


<View style={animationContainer}>
    <Image
      source={require('./images/image.png')}
      style={image}
    />
    <Animated.Image
      source={require('./images/icon.png')}
      style={circlingIcon}
    />
</View>
Share Improve this question asked Feb 4, 2020 at 2:34 Evgenii KlepilinEvgenii Klepilin 6952 gold badges8 silver badges21 bronze badges 6
  • 1 This is what you are looking for – CampbellMG Commented Feb 4, 2020 at 4:56
  • @CampbellMG I have seen that one, and it looked like an OK solution, but not the best. But I appreciate pointing that example out – Evgenii Klepilin Commented Feb 4, 2020 at 7:59
  • What part of this solution doesn't work for you? – CampbellMG Commented Feb 4, 2020 at 8:00
  • What I don't like about this solution is that it is possible to approximate it down to the circular movement, but not to provide exact functional correlation. There is a variable snapshot which defines how many frames would you want to have in your animation. What I was hoping finding would be the proper interpolation of a value that would result in a continuous graph/movement – Evgenii Klepilin Commented Feb 4, 2020 at 8:03
  • 1 The problem you are going to run into trying to create circular movement with the Animated API is that you only have access to basic mathematical functions (add, divide, modulo etc.). That is why this solution samples values along a circular path rather than an exact figure. You could try a library like this that includes a few more plex functions like sin using a Taylor Series. – CampbellMG Commented Feb 4, 2020 at 8:14
 |  Show 1 more ment

2 Answers 2

Reset to default 2

I have posted a similar butter smooth solution for 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});
    }

    ponentDidMount() {
        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>
          </View>
        );
    }
 }
 const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    item: {
        position: 'absolute',
        width: 100,
        height: 200, // this is the diameter of circle
    },
    topItem: {
        width: '100%',
        height: 20,
        backgroundColor: 'red',
        position: 'absolute',
        alignItems: 'center',
        justifyContent: 'center',
    },
    text: {
        color: '#fff',
    },
 });

I hope it will help you..

I have taken a solution from a question react native circle transform translate animation and refactored it a little by separating interpolation of coordinates over Y and X in two different functions.

interface InterpolatedMotion {
  translateX: Animated.Value;
  translateY: Animated.Value;
}

interface AnimatedIcon extends InterpolatedMotion {
  animated: Animated.Value;
}

interface State {
  icon: AnimatedIcon;
}

const defaultAnimatedIcon = (animatedValue: number): AnimatedIcon => ({
  animated: new Animated.Value(animatedValue),
  translateX: new Animated.Value(0),
  translateY: new Animated.Value(0),
});

export class Animation extends PureComponent<Props, State> {
  state = {
    icon: defaultAnimatedIcon(0),
  }

  constructor(props) {
    super(props);
    let { icon } = this.state;

    icon.animated.setValue(0);

    const snapshot = 50;
    const radius = 200;

    const inOutX = this.interpolateCircularMotionOverX(snapshot, radius);

    icon.translateX = coins.animated.interpolate(inOutX);

    const inOutY = this.interpolateCircularMotionOverY(snapshot, radius);

    icon.translateY = coins.animated.interpolate(inOutY);
  }

  ponentWillMount(): void {
    this.startAnimation();
  }

  startAnimation = (): void => {
    let { icon } = this.state;

    icon.animated.setValue(0);

    let animations = [
      Animated.timing(
        icon.animated,
        {
          toValue: 1,
          duration: 8000,
          easing: Easing.linear,
        },
      ),
    ];

    Animated.loop(
      Animated.parallel(animations),
    ).start(() => {
      icon.animated.setValue(0);
    });
  }

  interpolateCircularMotionOverX = (snapshot: number, radius: number) => {
    const inputRange = [];
    const outputRange = [];
    for (let i = 0; i <= snapshot * 2; ++i) {
      const value = i / snapshot;
      const move = Math.sin(value * Math.PI * 2) * radius;
      inputRange.push(value);
      outputRange.push(move);
    }
    return { inputRange, outputRange };
  }

  interpolateCircularMotionOverY = (snapshot: number, radius: number) => {
    const inputRange = [];
    const outputRange = [];
    for (let i = 0; i <= snapshot * 2; ++i) {
      const value = i / snapshot;
      const move = -Math.cos(value * Math.PI * 2) * radius;
      inputRange.push(value);
      outputRange.push(move);
    }
    return { inputRange, outputRange };
  }

  render(): JSX.Element {
    const { icon } = this.state;

    const transformIcon = [
      { translateY: icon.translateY },
      { translateX: icon.translateX },
    ];

    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
          <View style={{ flex: 1 }}>
            <Animated.Image
              source={require('./images/coins.png')}
              style={[Styles.forms.circlingIcon, { transform: transformCoins }]}
            />
          </View>
        </View>
    );
}

This has helped me by providing a flexible and reusable solution for any future instances of circular animation.

发布评论

评论列表(0)

  1. 暂无评论