I am trying to create a chart with line/border color with different color based on value, like this image, so color change above and below a certain point.
I have already went through the segment sample on chartjs docs (https://www.chartjs.org/docs/latest/samples/line/segments.html), but this is using skip and points, whereas I am trying to do this with value, which I can't figure out.
Here is my code, it's in ejs file (only diff from js is variable passed in <%- %> over ${}) :
<canvas id="LineChart" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"
integrity="sha512-asxKqQghC1oBShyhiBwA+YgotaSYKxGP1rcSYTDrB0U6DxwlJjU59B67U8+5/++uFjcuVM8Hh5cokLjZlhm3Vg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>
<script>
var ctx=document.getElementById( 'LineChart' ).getContext( "2d" );
var myChart=new Chart( ctx, {
type: 'line',
data: {
labels: <%- JSON.stringify( labels )%>,
datasets: [ {
label: ['a','b','c','d'],
data: ['1','2','3','4'],
backgroundColor:'rgba(54, 162, 235, 0.5)',
borderColor: rgb( 255, 255, 255 ),
segment: {
borderColor: function black() {
if ( <%=maxValue%> >99) {
return 'black';
}
if ( <%=minValue%> >99) {
return 'red';
}
}
},
}],
}
});
</script>
Here is the related sample code on chartjs website, (for quick reference) :
const skipped = (ctx, value) => ctx.p0.skip || ctx.p1.skip ? value : undefined;
const down = (ctx, value) => ctx.p0.parsed.y > ctx.p1.parsed.y ? value : undefined;
borderColor: ctx => skipped(ctx, 'rgb(0,0,0,0.2)') || down(ctx, 'rgb(192,75,75)')
I will be really grateful for any help! Thanks a lot.
Update: I was able to figure this out mostly (I can make a linear gradient with color stops on certain value), but the problem I am facing is in selecting x/y-axis to fetch pixel for value, as I can't select chart properly, I made this fiddle with comment where I am facing the issue, it would be great help if someone can take a look and suggest me something, here is the fiddle : jsfiddle.net/baozkrw1/1
Also, here is the fiddle code for quick view :
HTML :
<h1>Chart One</h1>
<canvas id="LineChart" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"
integrity="sha512-asxKqQghC1oBShyhiBwA+YgotaSYKxGP1rcSYTDrB0U6DxwlJjU59B67U8+5/++uFjcuVM8Hh5cokLjZlhm3Vg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>
JS :
var ctx = document.getElementById('LineChart').getContext("2d");
let width, height, gradient;
function getGradient(ctx, chartArea) {
const chartWidth = chartArea.right - chartArea.left;
const chartHeight = chartArea.bottom - chartArea.top;
if (gradient === null || width !== chartWidth || height !== chartHeight) {
width = chartWidth;
height = chartHeight;
let y = 27; // I want this to be the pixel for value I pass, instead of hard value
// but I can't select y-axis like this:
// var yaxis=y.scales[ 'y-axis-0' ];
// as it says undefined, and if I do like this :
// const { ctx, canvas, scales: { x, y } }=chart;
// var xaxis=x.scales[ 'x-axis-0' ];
// It says chart not defined, which I think is because I am not making this a function and passing chart, and I can't figure out how to do it right.
gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
gradient.addColorStop(y / chartHeight, 'black');
gradient.addColorStop(0.6, 'yellow');
gradient.addColorStop(0.9, 'red');
gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
gradient.addColorStop(y / chartHeight, 'black');
gradient.addColorStop(0.6, 'yellow');
gradient.addColorStop(0.9, 'red');
}
return gradient;
}
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['10', '20', '30', '40', '50'],
datasets: [{
label: 'Hello',
data: ['1', '2', '3', '4', '5'],
backgroundColor: 'rgba(255, 255, 78, 1)',
borderColor: function(context, options) {
const chart = context.chart;
const {
ctx,
chartArea
} = chart;
if (!chartArea) {
return null;
}
return getGradient(ctx, chartArea);
},
}]
},
});