UNPKG

react-native-bar-graph

Version:
175 lines (165 loc) 4.8 kB
import React, { useEffect, useRef } from "react"; import { View, Text, StyleSheet, Animated, TouchableOpacity, Dimensions, ScrollView, } from "react-native"; const Bargraph = ({ data = [], height = 200, width = Dimensions.get("window").width - 40, barWidth = 22, spacing = 20, numOfYAxisLabels = 4, showGrid = true, onPresscnt = () => {}, style = {}, valueKey = "", // ✅ key for Y-axis value labelKey = "", // ✅ key for X-axis label }) => { const maxValue = Math.max(...data.map((item) => item?.[valueKey] || 0)); const animatedValue = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.timing(animatedValue, { toValue: 1, duration: 800, useNativeDriver: false, }).start(); }, []); const chartContentWidth = data.length * (barWidth + spacing) + 20; return ( <View style={{ width }}> <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ width: chartContentWidth }} > <View> <View style={[styles.wrapper, { height }]}> <View style={[styles.wrapper, { height: height + 20 }]}> {showGrid && Array.from({ length: numOfYAxisLabels + 1 }, (_, i) => ( <View key={i} style={[ styles.gridLine, { top: (i * height) / numOfYAxisLabels, width: chartContentWidth, }, ]} /> ))} <View style={[styles.chartContainer, { height }]}> {data.map((item, index) => { const safeMax = maxValue === 0 ? 1 : maxValue; const value = item?.[valueKey] || 0; const label = item?.[labelKey] || ""; const barHeight = animatedValue.interpolate({ inputRange: [0, 1], outputRange: [0, (value / safeMax) * height], }); const isMaxTarget = value === maxValue; return ( <View key={index} style={[styles.barItem, { width: barWidth + spacing }]} > <Animated.Text style={styles.countValue}> {value} </Animated.Text> <TouchableOpacity onPress={() => onPresscnt(item)}> <Animated.View style={[ styles.cntStyle, { height: barHeight, width: barWidth, }, ]} > {isMaxTarget && value > 0 && ( <Text style={styles.countAboveBar}>{value}</Text> )} </Animated.View> </TouchableOpacity> </View> ); })} </View> </View> </View> <View style={[styles.xAxisLabels]}> {data.map((item, index) => ( <View key={index} style={[styles.dtWrapper, { width: barWidth + spacing }]} > <Text style={styles.dtStyles}>{item?.[labelKey]}</Text> </View> ))} </View> </View> </ScrollView> </View> ); }; export default Bargraph; const styles = StyleSheet.create({ wrapper: { flexDirection: "row", paddingHorizontal: 10, }, gridLine: { position: "absolute", height: 1, backgroundColor: "#ddd", }, chartContainer: { flexDirection: "row", alignItems: "flex-end", }, barItem: { alignItems: "center", justifyContent: "flex-end", }, xAxisLabels: { flexDirection: "row", justifyContent: "flex-start", paddingHorizontal: 10, paddingVertical: 6, marginLeft: 20, }, countValue: { fontSize: 10, marginBottom: 4, fontFamily: "Poppins-SemiBold", }, countAboveBar: { fontSize: 10, marginBottom: 10, color: "#fff", fontFamily: "Poppins-SemiBold", textAlign: "center", transform: [{ rotate: "-65deg" }], }, cntStyle: { backgroundColor: "green", borderTopLeftRadius: 4, borderTopRightRadius: 4, }, dtWrapper: { height: 50, alignItems: "center", justifyContent: "flex-start", transform: [{ rotate: "-70deg" }], }, dtStyles: { fontSize: 10, fontFamily: "Poppins-Medium", }, });