问题
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
calledrotateAnim
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 therotateAnim
animated value, which will update all of its dependent mappings (in this case, just thetransform
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