import React, { FC, useRef } from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
import Svg, { G, Circle } from 'react-native-svg';
import Animated, { call, Easing, interpolate, useCode } from 'react-native-reanimated';
import { timing } from 'react-native-redash';
interface DonutChartProps {
percentage: number;
radius?: number;
strokeWidth?: number;
duration?: number;
color?: string;
delay?: number;
textColor?: string;
max?: number;
}
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
const DonutChart: FC<DonutChartProps> = ({
percentage,
radius = 40,
strokeWidth = 10,
duration = 500,
color = 'tomato',
textColor,
max = 100,
}) => {
const inputRef = useRef<TextInput>(null);
const halfCircle = radius + strokeWidth;
const circumference = 2 * Math.PI * radius;
const maxPercentage = (100 * percentage) / max;
const animation = timing({
from: 0,
to: 1,
duration,
easing: Easing.inOut(Easing.linear),
});
const strokeDashoffset = interpolate(animation, {
inputRange: [0, 1],
outputRange: [circumference, circumference - (maxPercentage * circumference) / 100],
});
const textValue = interpolate(animation, {
inputRange: [0, 1],
outputRange: [0, Math.round(percentage)],
});
useCode(
() => [
call([textValue], ([textValue]) => {
if (inputRef.current) {
inputRef.current.setNativeProps({
text: `${Math.round(textValue)}`,
});
}
}),
],
[textValue]
);
return (
<View>
<Svg width={radius * 2} height={radius * 2} viewBox={`0 0 ${halfCircle * 2} ${halfCircle * 2}`}>
<G rotation="-90" origin={`${halfCircle}, ${halfCircle}`}>
<Circle
cx="50%"
cy="50%"
stroke={color}
strokeWidth={strokeWidth}
r={radius}
fill="transparent"
strokeOpacity={0.2}
/>
<AnimatedCircle
cx="50%"
cy="50%"
stroke={color}
strokeWidth={strokeWidth}
r={radius}
fill="transparent"
strokeDasharray={circumference}
strokeDashoffset={strokeDashoffset}
strokeLinecap="round"
/>
</G>
</Svg>
<AnimatedTextInput
ref={inputRef}
underlineColorAndroid="transparent"
editable={false}
defaultValue="0"
style={[
StyleSheet.absoluteFillObject,
{ fontSize: radius / 2, color: textColor ?? color, fontWeight: '900', textAlign: 'center' },
]}
/>
</View>
);
};
export default DonutChart;