Barchart OnPress Functionality - onBarClicked
Hey @Hermanya
Just like how we have an onDataPointClick functionality, in the Linechart. Is there something similar for barcharts? That when I click on a bar, I can then show a tooltip or change the color of the bar.
Here's a screenshot for reference -

Can we just simply apply the functions and implementation done in Linechart to Barchart?
Check the below link for barchart click. https://github.com/indiespirit/react-native-chart-kit/issues/451#issuecomment-787909270
Hey @danishbutt3535 ,
I've just made a small change and made it as a package - https://www.npmjs.com/package/react-native-chart-kit-with-pressable-bar-graph
same here
Inside the node_modules/react-native-chart-kit/dist/BarChart.js file, go to the _this.renderBars function and copy the following code:
_this.renderBars = function (_a) { var data = _a.data, width = _a.width, height = _a.height, paddingTop = _a.paddingTop, paddingRight = _a.paddingRight, barRadius = _a.barRadius, withCustomBarColorFromData = _a.withCustomBarColorFromData, onDataPointClick = _a.onDataPointClick; var baseHeight = _this.calcBaseHeight(data, height); return data.map(function (x, i) { var barHeight = _this.calcHeight(x, data, height); var barWidth = 32 * _this.getBarPercentage(); const cx = paddingRight + (i * (width - paddingRight)) / data.length + barWidth / 2; const cy = ((barHeight > 0 ? baseHeight - barHeight : baseHeight) / 4) * 3 + paddingTop; var onPress = function () { if (!onDataPointClick) { return; } onDataPointClick({ index: i, value: x, dataset: data[i], x:cx, y: cy, getColor: function (opacity) { return this.getColor(data[i], opacity); } }); }; return (<Rect key={Math.random()} x={paddingRight + (i * (width - paddingRight)) / data.length + barWidth / 2} y={((barHeight > 0 ? baseHeight - barHeight : baseHeight) / 4) * 3 + paddingTop} rx={barRadius} width={barWidth} height={(Math.abs(barHeight) / 4) * 3} fill={withCustomBarColorFromData ? "url(#customColor_0" + i + ")" : "url(#fillShadowGradientFrom)"} onPress={onPress}/>); }); }; This adds the functionality to click on the bars. Then, you need to add decorator = _b.decorator, onDataPointClick = _b.onDataPointClick inside BarChart.prototype.render in the variable _b, like this:
var _b = this.props, width = _b.width, height = _b.height, data = _b.data, _c = _b.style, style = _c === void 0 ? {} : _c, _d = _b.withHorizontalLabels, withHorizontalLabels = _d === void 0 ? true : _d, _e = _b.withVerticalLabels, withVerticalLabels = _e === void 0 ? true : _e, _f = _b.verticalLabelRotation, verticalLabelRotation = _f === void 0 ? 0 : _f, _g = _b.horizontalLabelRotation, decorator = _b.decorator, onDataPointClick = _b.onDataPointClick, horizontalLabelRotation = _g === void 0 ? 0 : _g, _h = _b.withInnerLines, withInnerLines = _h === void 0 ? true : _h, _j = _b.showBarTops, showBarTops = _j === void 0 ? true : _j, _k = _b.withCustomBarColorFromData, withCustomBarColorFromData = _k === void 0 ? false : _k, _l = _b.showValuesOnTopOfBars, showValuesOnTopOfBars = _l === void 0 ? false : _l, _m = _b.flatColor, flatColor = _m === void 0 ? false : _m, _o = _b.segments, segments = _o === void 0 ? 4 : _o; Then, inside the return of the render function, add the following to display the decorator:
<G>{decorator &&
decorator(__assign(__assign({}, config), { data: data.datasets, paddingTop: paddingTop,
paddingRight: paddingRight }))}</G>
And change where it says renderBars to this:
<G>{this.renderBars(__assign(__assign({}, config), { data: data.datasets[0].data, paddingTop: paddingTop, paddingRight: paddingRight, withCustomBarColorFromData: withCustomBarColorFromData, onDataPointClick: onDataPointClick }))}</G>
Now, you can add onDataPointClick and decorator as props inside BarChart. Here is an example:
<BarChart
data={monthStatistics}
width={Dimensions.get("screen").width - 40}
height={240}
chartConfig={chartConfig}
style={{
borderRadius: 20,
paddingRight: 0.
elevation: 5.
}}
withHorizontalLabels={false}
withOuterLines={false}
decorator={() => {
return dataPoint ? (
<View
style={{
position: "absolute",
top: dataPoint.y - 50,
left: dataPoint.x + 10,
backgroundColor: colors.card,
borderColor: "#58eb34",
borderWidth: 1,
borderStyle: "solid",
borderRadius: 5.
padding: 10,
justifyContent: "center",
alignItems: "center",
rowGap: 10,
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
columnGap: 10.
}}
>
<Icon
name="wallet"
type="font-awesome-5"
iconStyle={{
color: colors.text,
fontSize: 13.
}}
></Icon>
<Text
style={{
color: colors.text,
fontSize: 13.
fontFamily: "Poppins_300Light",
}}
>
{monthData(dataPoint.index)
? monthData(dataPoint.index)?.total > 0
? $${( monthData(dataPoint.index)?.total / 1000 )?.toFixed(2)}K
: -$${( (monthData(dataPoint.index)?.total / 1000) * -1 )?.toFixed(2)}K
: $0.00K}
</Text>
</View>
<View
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
columnGap: 10.
}}
>
<Icon
name="arrow-up"
type="font-awesome"
iconStyle={[styles.profit, { fontSize: 13 }]}
></Icon>
<Text
style={{
color: colors.text,
fontSize: 13.
fontFamily: "Poppins_300Light",
}}
>
{monthData(dataPoint.index)
? `$${(
monthData(dataPoint.index)
?.totalIncome / 1000
)?.toFixed(2)}K`
: `$0.00K`}
</Text>
</View>
<View
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
columnGap: 10.
}}
>
<Icon
name="arrow-down"
type="font-awesome"
iconStyle={[styles.loss, { fontSize: 13 }]}
></Icon>
<Text
style={{
color: colors.text,
fontSize: 13.
fontFamily: "Poppins_300Light",
}}
>
{monthData(dataPoint.index)
? `-$${(
(monthData(dataPoint.index)?.totalLoss /
1000) *
-1
)?.toFixed(2)}K`
: `$0.00K`}
</Text>
</View>
</View>
) : null;
}}
onDataPointClick={(index) => {
dataPoint && index.index === dataPoint.index
? setDataPoint((prev) => null)
: setDataPoint((prev) => ({
index: index.index,
x:index.x,
y: index.y,
}));
}}
withInnerLines={false}
showBarTops={false}
/>
I hope this helps you implement the functionality you need in your bar chart.