Animate a Circle around another circle

孤人 提交于 2020-03-26 03:37:33

问题


I'm using react-native-svg. I'd like to animate a small circle around another bigger circle. This question is similar to this one. The animation is not tied to any gesture but time. The rotation should take a predefined delay in seconds to complete and should be as smooth as possible. Is it possible to do that with react-native-svg?

To be complete, I have to say that there are other small circles that are plotted every seconds. This is already working by mutating the state every second. But of course I won't animate by mutating the state, will I?

So here is the JSX code I have so far in render():

<Svg style={{ alignContent: 'center' }}
  height="200"
  width="200">
  <Circle 
    cx="100"
    cy="100"
    r="56"
    stroke="black"
    strokeWidth="2"
    strokeOpacity="1"
    fillOpacity="0" 
  />
  { 
    /* Bubules (little circles) goes here*/                                                            
    this.bubbles() 
  }
</Svg>

and the typescript bubbles() method:

bubbles(): React.ReactNode {
    var elements = [];
    for (let tuple of this.state.lorenzPlotData) {
        let color = tuple === this.state.lorenzPlotData.tail ? "red" : "black";
        // We need to normalize data 
        elements.push(<Circle key={tuple[0]} cx={this.normalizePlot(tuple[1])} cy={this.normalizePlot(tuple[2])} r="4" fill={color} fillOpacity="1" />);
    }
    return elements;
}

Any help appreciated.


回答1:


as explained in the following article, demonstrated in the following example and suggested from Nishant Nair you need to use transform property to rotate the svg around the other object.

CSS animation example

the code is included in line 51 of file transition-circle-keyframes.css and it uses transform on every @keyframes to move the object.

@-webkit-keyframes orbit {
    from {  -webkit-transform: rotate(0deg) translateX(400px) rotate(0deg); }
    to   {  -webkit-transform: rotate(360deg) translateX(400px) rotate(-360deg); }
}

Transforms in react-native

transform

transform accepts an array of transformation objects. Each object specifies the property that will be transformed as the key, and the value to use in the transformation. Objects should not be combined. Use a single key/value pair per object.

The rotate transformations require a string so that the transform may be expressed in degrees (deg) or radians (rad). For example:

The corresponding from field should be set as

transform([{ rotateX: '0deg' }, { translateX: 400}, { rotateX: '0deg' }])

the to field should be set as

transform([{ rotateX: '360deg' }, { translateX: 400}, { rotateX: '-360deg' }])

Triggering the animation

you can use the Animated api to change the state over time. On every keyframe you need to change the View transform property from rotateX: '0deg' to rotateX: '360deg'. You can pass the SVG as child of the rotateInView component:

render() {
  return (
    <rotateInView>
      <Svg />
    </rotateInView>
  );
}

the rotateInView component will save the transform as state, Animated.timing() function will trigger the state update

In the rotateInView constructor, a new Animated.Value called rotateAnim is initialized as part of state. The transform property on the View is mapped to this animated value. Behind the scenes, the numeric value is extracted and used to set transform property.

When the component mounts, the opacity is set to [{ rotateX: '0deg' }, { translateX: 400}, { rotateX: '0deg' }]. Then, an easing animation is started on the rotateAnim animated value, which will update all of its dependent mappings (in this case, just the transform property) on each frame as the value animates to the final value of [{ rotateX: '360deg' }, { translateX: 400}, { rotateX: '-360deg' }].

This is done in an optimized way that is faster than calling setState and re-rendering. Because the entire configuration is declarative, we will be able to implement further optimizations that serialize the configuration and runs the animation on a high-priority thread.

import React from 'react';
import { Animated, Text, View } from 'react-native';
class rotateInView extends React.Component {
  state = {
    rotateAnim: new Animated.Value(transform([{ rotateX: '0deg' }, { translateX: 400}, { rotateX: '0deg' }])),
  }

  componentDidMount() {
    Animated.timing(                  // Animate over time
      this.state.rotateAnim,            // The animated value to drive
      {
        toValue: transform([{ rotateX: '360deg' }, { translateX: 400}, { rotateX: '-360deg' }]), // Change to the new value
        duration: 10000,              // Make it take a while
      }
    ).start();                        // Starts the animation
  }

  render() {
    let { rotateAnim } = this.state;

    return (
      <Animated.View                 // Special Animated View
        style={{
          ...this.props.style,
          transform: rotateAnim,         
        }}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}


来源:https://stackoverflow.com/questions/55667722/animate-a-circle-around-another-circle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!