ReactNative:
<ScrollView style={styles.container}>
<Svg
height="100"
width="100">
<Circle
cx="50"
cy="50"
r="50"
stroke="blue"
strokeWidth="2.5"
fill="green"/>
</Svg>
</ScrollView>
I want to make Circle scale with Animated.Value. I have tried this :
let AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
let AnimatedCircle = Animated.createAnimatedComponent(Circle);
<ScrollView style={styles.container}>
<Svg
height="100"
width="100">
<AnimatedCircle
cx="50"
cy="50"
r={this.state.animator}
stroke="blue"
strokeWidth="2.5"
fill="green"/>
</Svg>
</ScrollView>
Then flash back with no error.
How can I do?
update 2016.8.24
I found a new way instead of requestAnimationFrame :
constructor:
this.state = {
animator: new Animated.Value(0),
radius: 1,
};
this.state.animator.addListener((p) => {
this.setState({
radius: p.value,
});
});
render:
<Circle
cx="50"
cy="50"
r={this.state.radius}
stroke="blue"
strokeWidth="2.5"
fill="green"/>
But here the guides gives advice using it sparingly since it might have performance implications in the future.
so what's the best way ?
In react native, we can generate/render an SVG using the react-native-svg library. A complex SVG comprises many more minor elements that could be animated individually. But here, for example, we will take only one piece, a circle. The following code will draw a circle with a radius of 50 units.
How it create SVG Animations: Select the Frame you want to animate and click on Enable SVG Export. Select a node within that Frame to set up animations such as X Position, Y Position, Scale, Rotation and Opacity. Use the built-in live-preview to tweak your animations until you're happy with the result.
SVG supports the ability to change vector graphics over time, to create animated effects. SVG content can be animated in the following ways: Using SVG's animation elements [svg-animation]. SVG document fragments can describe time-based modifications to the document's elements.
setNativeProps
for Much Better Performance.I did some more tinkering and found a more performant method that makes use of addListener
and setNativeProps
.
Constructor
constructor(props) {
super(props);
this.state = { circleRadius: new Animated.Value(50) };
this.state.circleRadius.addListener( (circleRadius) => {
this._myCircle.setNativeProps({ r: circleRadius.value.toString() });
});
setTimeout( () => {
Animated.spring( this.state.circleRadius, { toValue: 100, friction: 3 } ).start();
}, 2000)
}
Render
render() {
return(
<Svg height="400" width="400">
<AnimatedCircle ref={ ref => this._myCircle = ref } cx="250" cy="250" r="50" fill="black" />
</Svg>
)
}
Result
And this is what the animation looks like when the 2 second (2000 millisecond) timeout triggers.
So, the main thing you needed to change was using setNativeProps
instead of using setState
in your listener. This makes a native call and bypasses re-calculating the entire component, which in my case was very complex and slow to do.
Thanks for leading me towards the listener approach!
i have created a simple svg animations library based on a project by another person, for now, only Paths can be animated but more shapes and animations will be added in the future
https://www.npmjs.com/package/react-native-svg-animations
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With