Here, by animating SVG, I mean to change the property of SVG elements dynamically, which will look live-like.
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.
<Svg width={200} height={200}>
<Circle cx="55" cy="55" r="50" stroke="black" strokeWidth={5} />
</Svg>
Suppose we want to animate it to become large and small. To achieve this, I will use React Native Reanimated. To learn more about it, you can check out its documentation.
Logically, I am trying to increase or decrease the radius.
Since the radius value is a prop, I will use useAnimatedProps
. But, first of all, convert Circle to an animated component.
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
Now, I can re-write component as
<Svg width={200} height={200}>
<AnimatedCircle cx="55" cy="55" r="50" stroke="black" strokeWidth={5} />
</Svg>
Next step is to store the stroke width and radius. width can be stored in a simple constat, but for the radius we will use useSharedValue
, so that it can be used by woklet to animate.
export default ()=>{
const radius = useSharedValue(50);
const strokeWidth = 5;
return (
<Svg width={200} height={200}>
<AnimatedCircle
cx={`${radius.value + strokeWidth}`}
cy={`${radius.value + strokeWidth}`}
r={`${radius.value}`}
stroke="black"
strokeWidth={strokeWidth}
/>
</Svg>
)
}
Here, I need some event or action to trigger the radius change. I’ll use a button press. (withSpring is default provided animation which is not necessary to use but this looks cool 🤞)
<Button mode="contained" onPress={() => {
if(radius.value < 80) {
radius.value = withSpring(80)
}else{
radius.value = withSpring(50)
}
}}>
Press
</Button>
You’ll notice that even after pressing the button, nothing happens. It is because change of sharedValue doesn’t trigger re-render of the react component. finally animated props comes into the picture. Instead of passing prop directly, we will pass it using animated prop.
const animatedProps = useAnimatedProps(() => ({
cx: `${radius.value + strokeWidth}`,
cy: `${radius.value + strokeWidth}`,
r:`${radius.value}`
}));
<Svg width={200} height={200}>
<AnimatedCircle
animatedProps={animatedProps}
stroke="black"
strokeWidth={strokeWidth}
/>
</Svg>
Result, is something like this.
This is a relatively simple example, but I hope I successfully demonstrated the possibilities. Here is the link of complete code of the result if you are interested.
Top comments (0)