react-native-modern-elements
Version:
A modern, customizable UI component library for React Native
73 lines (72 loc) • 3.61 kB
JavaScript
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);