围绕另一个圆圈制作一个圆圈

Animate a Circle around another circle

我正在使用 react-native-svg。 我想围绕另一个更大的圆圈制作一个小圆圈的动画。这个问题类似于。 动画不依赖于任何手势,而是时间。旋转应该以秒为单位的预定义延迟完成,并且应该尽可能平滑。是否可以使用 react-native-svg 做到这一点?

为了完整起见,我不得不说每秒钟都绘制了其他小圆圈。这已经通过每秒改变状态来工作。但是我当然不会通过改变状态来制作动画,对吗?

这是我目前在 render() 中的 JSX 代码:

<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>

和 typescript bubbles() 方法:

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

感谢任何帮助。

正如所解释的 in the following article, demonstrated in the following example and suggested from Nishant Nair 你需要使用变换 属性 来围绕另一个对象旋转 svg

CSS动画示例

包含代码 in line 51 of file transition-circle-keyframes.css 并且它在每个 @keyframes 上使用 transform 来移动对象。

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

Transformsreact-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:

对应的from字段应该设置为

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

收件人字段应设置为

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

触发动画

您可以使用 Animated api 随着时间的推移更改 state。 在每个 keyframe 上,您需要将视图 transform 属性 从 rotateX: '0deg' 更改为 rotateX: '360deg'。您可以将 SVG 作为 rotateInView 组件的子项传递:

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

rotateInView组件会将transform保存为状态,Animated.timing()函数会触发状态更新

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