UNPKG

react-native-animated-progress-chz

Version:

Animated progressBar for react-native with custom modules

146 lines (133 loc) 3.2 kB
import React, { useEffect, useState, useCallback } from "react"; import { Animated, StyleSheet, View } from "react-native"; const ProgressBar = (props) => { const { height, progress, animated, indeterminate, progressDuration, indeterminateDuration, onCompletion, backgroundColor, trackColor = "#A6A6A6", value, radius, } = props; const [timer] = useState(new Animated.Value(0)); const [width] = useState(new Animated.Value(0)); const indeterminateAnimation = Animated.timing(timer, { duration: indeterminateDuration, toValue: 1, useNativeDriver: true, isInteraction: false, }); useEffect(() => { if (indeterminate || typeof progress === "number") { startAnimation(); } else { stopAnimation(); } }, [indeterminate, progress, startAnimation, stopAnimation]); const startAnimation = useCallback(() => { if (indeterminate) { timer.setValue(0); Animated.loop(indeterminateAnimation).start(); } else { Animated.timing(width, { duration: animated ? progressDuration : 0, toValue: progress, useNativeDriver: false, }).start(() => { onCompletion(); }); } }, [ animated, indeterminate, indeterminateAnimation, onCompletion, progress, progressDuration, timer, width, ]); const stopAnimation = useCallback(() => { if (indeterminateAnimation) indeterminateAnimation.stop(); Animated.timing(width, { duration: 200, toValue: 0, useNativeDriver: true, isInteraction: false, }).start(); }, [indeterminateAnimation, width]); const styleAnimation = () => { return indeterminate ? { transform: [ { translateX: timer.interpolate({ inputRange: [0, 0.5, 1], outputRange: [-0.6 * 320, -0.5 * 0.8 * 320, 0.7 * 320], }), }, { scaleX: timer.interpolate({ inputRange: [0, 0.5, 1], outputRange: [0.0001, 0.8, 0.0001], }), }, ], } : { width: width.interpolate({ inputRange: [0, value], outputRange: ["0%", "100%"], }), }; }; const styles = StyleSheet.create({ container: { width: "100%", height, overflow: "hidden", borderRadius: 4, }, progressBar: { flex: 1, borderRadius: height / 2, }, }); return ( <View> <Animated.View style={[ styles.container, { backgroundColor: trackColor, borderRadius: radius }, ]} > <Animated.View style={[ styles.progressBar, { backgroundColor, ...styleAnimation(), }, ]} /> </Animated.View> </View> ); }; ProgressBar.defaultProps = { state: "black", height: 2, progress: 0, animated: true, indeterminate: false, indeterminateDuration: 1100, progressDuration: 1100, value: 100, onCompletion: () => {}, }; export default ProgressBar;