如何在React Native中实现每月含预订、营收的双柱状图表?
React Native 双柱状图表实现方案
针对每个月份展示「预订(booking)」和「营收(earning)」双柱状条的需求,提供两种可行实现方式:
一、基于现有图表库改造
1. 使用 react-native-chart-kit
该库的BarChart原生支持多系列数据,只需配置对应结构即可实现双柱子效果:
import { BarChart } from 'react-native-chart-kit'; import { View } from 'react-native'; const chartData = { labels: ['1月', '2月', '3月', '4月'], // 月份数组 datasets: [ { data: [20, 45, 28, 60], // 预订数据 color: (opacity = 1) => `rgba(54, 162, 235, ${opacity})`, // 预订柱子颜色 label: '预订' }, { data: [1500, 3200, 2100, 4800], // 营收数据 color: (opacity = 1) => `rgba(75, 192, 192, ${opacity})`, // 营收柱子颜色 label: '营收' } ] }; const chartConfig = { backgroundColor: '#ffffff', decimalPlaces: 0, color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`, labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`, style: { borderRadius: 16 }, propsForDots: { r: '0' } // 隐藏点标记 }; export default function DoubleBarChart() { return ( <View> <BarChart data={chartData} width={350} height={250} chartConfig={chartConfig} showValuesOnTopOfBars fromZero barRadius={4} barPercentage={0.6} // 控制柱子宽度,留出双柱子间距 /> </View> ); }
2. 使用 victory-native
victory-native的VictoryBar支持分组柱状图,通过参数控制双柱子布局:
import { VictoryChart, VictoryBar, VictoryAxis, VictoryTheme } from 'victory-native'; import { View } from 'react-native'; const chartData = [ { month: '1月', booking: 20, earning: 1500 }, { month: '2月', booking: 45, earning: 3200 }, { month: '3月', booking: 28, earning: 2100 }, { month: '4月', booking: 60, earning: 4800 }, ]; export default function GroupedBarChart() { return ( <View> <VictoryChart theme={VictoryTheme.material} domainPadding={{ x: 20 }} categorySpacing={50} // 月份组之间的间距 > <VictoryAxis tickValues={['1月', '2月', '3月', '4月']} tickFormat={(month) => month} /> <VictoryAxis dependentAxis /> <VictoryBar data={chartData} x="month" y="booking" barWidth={20} style={{ data: { fill: '#36a2eb' } }} /> <VictoryBar data={chartData} x="month" y="earning" barWidth={20} style={{ data: { fill: '#4bc0c0' } }} /> </VictoryChart> </View> ); }
二、自定义双柱状组件(高度定制场景)
如果现有库无法满足UI细节需求,可使用React Native基础组件手动实现:
import { View, Text, StyleSheet } from 'react-native'; // 模拟数据 const monthData = [ { month: '1月', booking: 20, earning: 1500 }, { month: '2月', booking: 45, earning: 3200 }, { month: '3月', booking: 28, earning: 2100 }, { month: '4月', booking: 60, earning: 4800 }, ]; // 计算最大值用于归一化柱子高度 const maxBooking = Math.max(...monthData.map(item => item.booking)); const maxEarning = Math.max(...monthData.map(item => item.earning)); export default function CustomDoubleBarChart() { return ( <View style={styles.container}> {monthData.map((item, index) => ( <View key={index} style={styles.monthGroup}> <Text style={styles.monthText}>{item.month}</Text> <View style={styles.barsContainer}> {/* 预订柱子 */} <View style={[ styles.bar, { height: (item.booking / maxBooking) * 180, backgroundColor: '#36a2eb' } ]}> <Text style={styles.barValue}>{item.booking}</Text> </View> {/* 营收柱子 */} <View style={[ styles.bar, { height: (item.earning / maxEarning) * 180, backgroundColor: '#4bc0c0' } ]}> <Text style={styles.barValue}>{item.earning}</Text> </View> </View> </View> ))} </View> ); } const styles = StyleSheet.create({ container: { flexDirection: 'row', justifyContent: 'space-around', paddingHorizontal: 10, paddingVertical: 20, alignItems: 'flex-end', height: 300, }, monthGroup: { alignItems: 'center', flex: 1, }, monthText: { fontSize: 12, marginBottom: 8, }, barsContainer: { flexDirection: 'row', justifyContent: 'space-around', width: '80%', alignItems: 'flex-end', }, bar: { width: 25, borderRadius: 4, justifyContent: 'flex-end', paddingBottom: 4, alignItems: 'center', }, barValue: { fontSize: 10, color: '#fff', fontWeight: 'bold', }, });
注意事项
- 数据归一化:自定义实现时需将不同量级的数据(如预订数和营收额)分别归一化,避免柱子高度差异过大
- 适配:可通过
Dimensions获取屏幕宽度,动态调整容器和柱子尺寸 - 交互:如需点击效果,可给柱子添加
TouchableOpacity组件扩展交互逻辑
内容的提问来源于stack exchange,提问作者Zeeshan Ansari
相关产品推荐
相关产品推荐

