Lightweight Progress Circles in React Native
I decided to create my own React Native component to display progress circles. It’s called react-native-progress-circle and you can easily use it in your React Native app. I didn’t use an existing component, because I wanted it to be small and lightweight. It does not depend on react-native-svg or ART, it’s done purely in CSS.
How it works
It uses two circles and two half-circles and positions them in a smart way such that they look like the progress circles you see above. (Inspired by react-native-percentage-circle.) It’s done in four steps:
1. Render an outer background circle with the shadow border color.
It’s just a styled View:
<View
style={[styles.outerCircle, {
width: radius * 2,
height: radius * 2,
borderRadius: radius,
backgroundColor: shadowColor,
}]}
/>2. Render a half-circle and position it according to the percentage
Now we style a View to the size of a rectangle and set the borderRadius property of only two of the four corners. This creates a half-circle.
<View
style={[styles.outerCircle, {
width: radius,
height: radius * 2,
backgroundColor: color,
borderRadius: radius,
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
transform: [ { rotate: /* rotate it according to percentage */ } ],
}]}
/>3. Render another half-circle and position it according to the percentage
If the percentage is greater than 50%, we need another half-circle and then rotate it. It will overlay the first half-circle to some degree.
4. Render a smaller inner circle with the original background color
Now just put a smaller white circle in the center:
const radiusMinusBorder = this.props.radius - this.props.borderWidth
// ...
<View
style={[styles.innerCircle, {
width: radiusMinusBorder * 2,
height: radiusMinusBorder * 2,
borderRadius: radiusMinusBorder,
backgroundColor: this.props.bgColor,
}]}
>
{
this.props.children
}
</View>Rotation Issues
Two half-circles are enough to cover all percentages from 0 to 100, however you need to be a bit smart about it:
1. More than 50%:
This is the easy case. The first half-circle will always have a rotation value of 180deg, spanning the right side of the circle.
The second one is computed easily by converting the percent to degrees:
function percentToDegrees(percent) {
return percent * 3.6
}2. Less than 50%:
We do the same rotation conversion here, but the problem is that we display the full half-circle instead of only the part on the right circle side.
The solution is use the second half-circle as an overlay for the left side. We render it there (0deg) in the color of the outer circle.
Further Usage with Animated Library
An advantage of only using the built-in CSS features is that we can use the Animated library that provides smooth animations with hardware acceleration. We can then create a simple Countdown Circle with the same concepts.

