0👍
With your scriptable borderColor: function(context, opts)
you extracted, chart
, the chart instance, and the chartArea
and
the canvas 2d context as:
const chart = context.chart;
const {ctx, chartArea} = chart;
You can also find the following:
- the id of the y axis used by this dataset:
const yScaleId = opts._proxy.scales.y.id;
This is the rigorous approach, for a chart with multiple y axes; in practice you probably know the id, and in this case, where there;s just the default axis, the id is
y
- the actual y scale object
chart.scales[yScaleId]
and its
min
andmax
values,scaleMin
andscaleMax
- the data array of this dataset:
context.dataset.data
and from it the minimum and maximum values of the data,
dataMin
anddataMax
. - With the extreme values for the axis and for the data, it is a simple
linear relation that would give:const fracStart = (dataMin - scaleMin)/(scaleMax - scaleMin), fracEnd = (dataMax - scaleMin)/(scaleMax - scaleMin);
These are the numbers that should replace
0
and1
in the definition of the linear vertical gradient, so that the first color corresponds to the minimum value and the final color corresponds to the maximum value.
Full code from your codepen:
const ctx = document.getElementById('myChart');
let width, height, gradient;
function getGradient(ctx, chartArea, fracStart = 0, fracEnd = 1) {
const chartWidth = chartArea.right - chartArea.left;
const chartHeight = chartArea.bottom - chartArea.top;
if (!gradient || width !== chartWidth || height !== chartHeight) {
// Create the gradient because this is either the first render
// or the size of the chart has changed
width = chartWidth;
height = chartHeight;
gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
const fracMid = (fracStart + fracEnd) / 2;
gradient.addColorStop(fracStart, 'green');
gradient.addColorStop(fracMid, 'yellow');
gradient.addColorStop(fracEnd, 'red');
}
return gradient;
}
new Chart(ctx, {
type: 'line',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [31, 27, 30, 51, 28, 32],
stepped: true,
borderWidth: 4,
borderColor: function(context, opts) {
const chart = context.chart;
const {ctx, chartArea} = chart;
// the id of the y scale of this dataset:
const yScaleId = opts._proxy.scales.y.id;
const scaleMin = chart.scales[yScaleId].min,
scaleMax = chart.scales[yScaleId].max;
const dataMin = Math.min(...context.dataset?.data ?? [scaleMin]),
dataMax = Math.max(...context.dataset?.data ?? [scaleMax]);
const fracStart = (dataMin - scaleMin)/(scaleMax - scaleMin),
fracEnd = (dataMax - scaleMin)/(scaleMax - scaleMin);
if (!chartArea) {
// This case happens on initial chart load
return;
}
return getGradient(ctx, chartArea, fracStart, fracEnd);
},
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
and codepen fork.
- Chartjs-Refresh data in Chart.js when data added in Angular
- Chartjs-ChartJS keeps resizing canvas to the default size
Source:stackexchange.com