I am using Chart.js grouped bar chart. I want to show my bars with gradient colors. Grouped Bar Currently it show as shown in below image. Any help will be greatly appreciated.
How to create a vertical grouped Bar chart(negative & positve bars) with vertical gradient from top to bottom of each bar bases on its height?
I found a very close solution here, but it sets the createLinearGradient for the whole graph, not for individual bars.
import { Chart, Chart as ChartJS, registerables } from "chart.js";
import {
getAxesTitle,
getGridConfig,
getLegendsConfig,
getTooltipConfig,
getZoomPanConfig,
numDifferentiation
} from "./ChartJsConfig";
import React, { useEffect, useRef } from "react";
import annotationPlugin from "chartjs-plugin-annotation";
import { BarChartProps } from "types/Interfaces";
import { styleVariable } from "utils/UtilityFunc";
import zoomPlugin from "chartjs-plugin-zoom";
ChartJS.register(
zoomPlugin,
annotationPlugin,
...registerables
);
const BarChart = (props: BarChartProps) => {
const { isShowGrid, isShowLegends, isShowTooltip, isZoomPan,
isStacked, dataSet, zoomConfig, panConfig, annotation, titleInfo } = props;
const chartContainer = useRef(null);
function getScales() {
return {
x: {
stacked: isStacked,
ticks: {
color: styleVariable("--chart-scale"),
font: {
size: 11,
weight: "normal",
family: "NxtOption-Medium"
},
"callback": function (value: string | number) {
const newThis = this as any;
return newThis.getLabelForValue(value);
}
},
border: {
color: styleVariable("--chart-scale"),
},
title: getAxesTitle(titleInfo.x),
grid: getGridConfig(isShowGrid)
},
y: {
stacked: isStacked,
ticks: {
color: styleVariable("--chart-scale"),
font: {
size: 11,
weight: "normal",
family: "NxtOption-Medium"
},
"callback": function (label: number) {
return numDifferentiation(label);
}
},
border: {
color: styleVariable("--chart-scale"),
},
title: getAxesTitle(titleInfo.y),
grid: getGridConfig(isShowGrid)
}
};
}
function updateGradientColors(ctx: any, chartArea: any) {
const redGradient = ctx && ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
if (redGradient) {
redGradient.addColorStop(0.2, styleVariable("--bar-chart-red-top-color"));
redGradient.addColorStop(1, styleVariable("--bar-chart-red-bottom-color"));
}
const greenGradient = ctx && ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
if (greenGradient) {
greenGradient.addColorStop(0.2, styleVariable("--bar-chart-green-top-color"));
greenGradient.addColorStop(1, styleVariable("--bar-chart-green-bottom-color"));
}
const gradientColors = [
redGradient, greenGradient
];
return gradientColors;
}
function getGradientColors() {
if (chartContainer && chartContainer.current) {
const normalColors = [
styleVariable("--chart-call-oi-area-color"),
styleVariable("--chart-put-oi-area-color")
];
return dataSet.datasets.map((dataset, idx) => {
return {
...dataset,
backgroundColor: function(context: any) {
const chart = context.chart;
const { ctx, chartArea } = chart;
if (!chartArea) return null;
const colors = updateGradientColors(ctx, chartArea);
if (colors.length)
return colors[ idx ];
return normalColors[ idx ];
}
};
});
}
return {};
}
useEffect(() => {
if (chartContainer && chartContainer.current) {
const configData = {
type: "bar",
"data": { ...dataSet, datasets: getGradientColors() },
options: {
responsive: true,
animation: false,
maintainAspectRatio: false,
interaction: {
mode: "index",
},
scales: getScales(),
plugins: {
legend: getLegendsConfig(isShowLegends),
zoom: getZoomPanConfig(isZoomPan, zoomConfig, panConfig),
tooltip: getTooltipConfig(isShowTooltip),
annotation: annotation ?? ""
},
layout: {
autoPadding: false,
padding: {
top: 50,
bottom: 10,
left: 20,
right: 20
},
}
}
};
const newChartInstance = new Chart(
chartContainer.current,
configData as any
);
return () => {
newChartInstance.destroy();
};
}
return () => {
return "";
};
}, [
chartContainer, dataSet
]);
return (
<div className="chartjs-container">
<canvas ref={chartContainer} className="canvas-tag" />
</div>
);
};
export default BarChart;
Thanks in Advance.