UNPKG

react-native-modern-elements

Version:

A modern, customizable UI component library for React Native

73 lines (72 loc) 3.61 kB
import React, { memo, useCallback, useEffect, useRef } from "react"; import { Animated, StyleSheet, Text, View } from "react-native"; import Svg, { Circle, G } from "react-native-svg"; import { verticalScale } from "../utils/styling"; const RadialProgress = ({ percentage = 0, Radialsize = 128, strokeWidths = 4.5, percentageTextSize = verticalScale(12), percentageTextFontWeight = "400", strokeLinecap = "round", animationDuration = 700, color = { low: "#FF2F2F", medium: "#E3B61D", high: "#09CC71", veryHigh: "#008000", }, }) => { const clampedPercentage = Math.min(Math.max(percentage, 0), 100); const size = Radialsize; const strokeWidth = strokeWidths; const center = size / 2; const radius = size / 2 - strokeWidth / 2; const circumference = 2 * Math.PI * radius; const progressAnimation = useRef(new Animated.Value(clampedPercentage)).current; const progressRef = useRef(null); const getStrokeColor = useCallback((value) => { var _a, _b, _c, _d; if (value <= 60) return (_a = color === null || color === void 0 ? void 0 : color.low) !== null && _a !== void 0 ? _a : "#FF2F2F"; if (value <= 70) return (_b = color === null || color === void 0 ? void 0 : color.medium) !== null && _b !== void 0 ? _b : "#E3B61D"; if (value <= 80) return (_c = color === null || color === void 0 ? void 0 : color.high) !== null && _c !== void 0 ? _c : "#09CC71"; return (_d = color === null || color === void 0 ? void 0 : color.veryHigh) !== null && _d !== void 0 ? _d : "#008000"; }, [color]); const initialOffset = circumference - (circumference * clampedPercentage) / 100; useEffect(() => { const listener = progressAnimation.addListener(({ value }) => { var _a; const strokeDashoffset = circumference - (circumference * value) / 100; (_a = progressRef.current) === null || _a === void 0 ? void 0 : _a.setNativeProps({ strokeDashoffset, stroke: getStrokeColor(value), }); }); Animated.timing(progressAnimation, { toValue: clampedPercentage, duration: animationDuration, useNativeDriver: false, }).start(); return () => progressAnimation.removeListener(listener); }, [ clampedPercentage, circumference, progressAnimation, getStrokeColor, animationDuration, ]); return (React.createElement(View, { style: styles.container }, React.createElement(Svg, { width: size, height: size }, React.createElement(G, { rotation: "-90", origin: center }, React.createElement(Circle, { stroke: "#E6E7E8", cx: center, cy: center, r: radius, strokeWidth: strokeWidth, fill: "transparent" }), React.createElement(Circle, { ref: progressRef, stroke: getStrokeColor(clampedPercentage), cx: center, cy: center, r: radius, strokeWidth: strokeWidth, strokeDasharray: circumference, strokeDashoffset: initialOffset, strokeLinecap: strokeLinecap, fill: "transparent" }))), React.createElement(Text, { style: { position: "absolute", fontSize: percentageTextSize, fontWeight: percentageTextFontWeight, color: getStrokeColor(clampedPercentage), } }, clampedPercentage, "%"))); }; const styles = StyleSheet.create({ container: { justifyContent: "center", alignItems: "center", }, }); export default memo(RadialProgress);