Skip to content

Instantly share code, notes, and snippets.

@anastely
Last active December 29, 2020 20:27
Show Gist options
  • Save anastely/a391226c60b59b054f4d706735bd4731 to your computer and use it in GitHub Desktop.
Save anastely/a391226c60b59b054f4d706735bd4731 to your computer and use it in GitHub Desktop.
import React, {useEffect} from 'react';
import {View, Button, StyleSheet} from 'react-native';
import Animated, {
Easing,
useAnimatedProps,
useDerivedValue,
useSharedValue,
withSpring,
withTiming,
} from 'react-native-reanimated';
import {TextInput} from 'react-native-gesture-handler';
import Svg, {G, Circle} from 'react-native-svg';
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
const CircleProgress = ({
percentage = 30,
radius = 200,
strokeWidth = 25,
color = 'tomato',
textColor,
max = 100,
}) => {
const circleRef = React.useRef();
const inputRef = React.useRef();
const halfCircle = radius + strokeWidth;
const circumference = 2 * Math.PI * radius; //Formula
const animatedValue = useSharedValue(0);
const animatedPropsCircle = useAnimatedProps(() => ({
strokeDashoffset: withTiming(animatedValue.value, {
duration: 2000,
easing: Easing.out(Easing.ease),
}),
}));
const animatedPropsText = useAnimatedProps(() => {
return {
text: String(withTiming(animatedValue.value, {duration: 8000})),
};
});
const stepText = useDerivedValue(() => {
return String(Math.ceil(animatedValue.value));
});
useEffect(() => {
const maxPerc = (100 * animatedValue.value) / max;
const strokeDashoffset = circumference - (circumference * maxPerc) / 100;
animatedValue.value = strokeDashoffset;
console.log('strokeDashoffset', strokeDashoffset);
}, [animatedValue]);
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Svg
width={radius * 2}
height={radius * 2}
viewBox={`0 0 ${halfCircle * 2} ${halfCircle * 2}`}>
<G rotation="-90" origin={`${halfCircle}, ${halfCircle}`}>
<AnimatedCircle
animatedProps={animatedPropsCircle}
ref={circleRef}
cx="50%"
cy="50%"
stroke={color}
strokeWidth={strokeWidth}
r={radius}
fill="transparent"
strokeLinecap="round"
strokeDasharray={circumference}
/>
<Circle
cx="50%"
cy="50%"
stroke={color}
strokeWidth={strokeWidth}
r={radius}
fill="transparent"
strokeOpacity={0.2}
/>
</G>
</Svg>
<AnimatedTextInput
underlineColorAndroid="transparent"
editable={false}
animatedProps={animatedPropsText}
value={stepText.value}
ref={inputRef}
style={[
StyleSheet.absoluteFillObject,
{
fontSize: radius / 3,
color: textColor ?? color,
fontWeight: '900',
textAlign: 'center',
bottom: 30,
},
]}
/>
<Button
title="toggle Circle"
onPress={() => {
animatedValue.value = Math.floor(Math.random() * 50);
}}
/>
</View>
);
};
export default CircleProgress;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment