I have a line chart in chart js. I want to give it a different background on the y axis say, 0-40 is red,40-70 is yellow and 70-100 is green. The limit for the y axis will always be 100.
var scatterChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: ' Dataset',
data: [{
x: 1,
y: 10
}, {
x: 2,
y: 50
}, {
x: 3,
y: 88
}, {
x: 4,
y: 5
}]
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'bottom'
}]
}
}
});
How do i set the background?
There is not a built in option, but we can achieve the result with some code.
var ctx = document.getElementById("chart").getContext("2d");
var scatterChart = new Chart(ctx, {
type: "line",
data: {
datasets: [{
label: " Dataset",
data: [{
x: 1,
y: 10
},
{
x: 2,
y: 50
},
{
x: 3,
y: 88
},
{
x: 4,
y: 5
}
]
}]
},
options: {
backgroundRules: [{
backgroundColor: "red",
yAxisSegement: 40
},
{
backgroundColor: "yellow",
yAxisSegement: 70
},
{
backgroundColor: "green",
yAxisSegement: Infinity
}
],
scales: {
xAxes: [{
type: "linear",
position: "bottom"
}],
yAxes: [{
color: ["#123456", "#234567"]
}]
}
},
plugins: [{
beforeDraw: function(chart) {
var ctx = chart.chart.ctx;
var ruleIndex = 0;
var rules = chart.chart.options.backgroundRules;
var yaxis = chart.chart.scales["y-axis-0"];
var xaxis = chart.chart.scales["x-axis-0"];
var partPercentage = 1 / (yaxis.ticksAsNumbers.length - 1);
for (var i = yaxis.ticksAsNumbers.length - 1; i > 0; i--) {
if (yaxis.ticksAsNumbers[i] < rules[ruleIndex].yAxisSegement) {
ctx.fillStyle = rules[ruleIndex].backgroundColor;
ctx.fillRect(xaxis.left, yaxis.top + (i - 1) * (yaxis.height * partPercentage), xaxis.width, yaxis.height * partPercentage);
} else {
ruleIndex++;
i++;
}
}
}
}]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
<div class="container">
<canvas id="chart"></canvas>
</div>
Let me present a generic approach that works with any such chart aslong as its dataset contains zero or positive values only.
The background colors together with the upper values can simply be defined inside the dataset as follows:
bgColors: [
{ color: 'red', upTo: 40 },
{ color: 'yellow', upTo: 70 },
{ color: 'green', upTo: 100 }
]
Then you could extend an existing line chart (i.e. 'lineDiffBgColors') and overwrite its update
function. In there, you would create a linear CanvasGradient
and add color stops that correspond to the definitions of bgColors
mentioned above. At the end, the linear gradient needs to be assigned to the backgroundColor
option of your dataset
.
this.chart.data.datasets[0].backgroundColor = gradient;
Please have a look at your enhanced code below.
Chart.defaults.lineDiffBgColors = Chart.defaults.line;
Chart.controllers.lineDiffBgColors = Chart.controllers.line.extend({
update: function(reset) {
var yAxis = this.chart.scales['y-axis-0'];
var bgColors = this.chart.data.datasets[0].bgColors.slice().reverse();
var max = Math.max.apply(null, bgColors.map(o => o.upTo));
var min = yAxis.getValueForPixel(yAxis.bottom);
var yTop = yAxis.getPixelForValue(max);
var gradient = this.chart.chart.ctx.createLinearGradient(0, yTop, 0, yAxis.bottom);
let offset = 0;
bgColors.forEach((bgc, i) => {
gradient.addColorStop(offset, bgc.color);
if (i + 1 == bgColors.length) {
offset = 1;
} else {
offset = (max - bgColors[i + 1].upTo) / (max - min);
}
gradient.addColorStop(offset, bgc.color);
});
this.chart.data.datasets[0].backgroundColor = gradient;
return Chart.controllers.line.prototype.update.apply(this, arguments);
}
});
new Chart('myChart', {
type: 'lineDiffBgColors',
data: {
datasets: [{
label: 'Dataset',
data: [
{ x: 1, y: 10 },
{ x: 2, y: 50 },
{ x: 3, y: 88 },
{ x: 4, y: 5 }
],
bgColors: [
{ color: 'red', upTo: 40 },
{ color: 'yellow', upTo: 70 },
{ color: 'green', upTo: 100 }
]
}]
},
options: {
scales: {
xAxes: [{
type: 'linear'
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="myChart" height="100"></canvas>
In case you prefer kind of smooth gradient, you could change the
bgColors.forEach
loop inside theupdate
function as follows.
bgColors.forEach((bgc, i) => {
gradient.addColorStop(offset == 0 ? 0 : offset + 0.05, bgc.color);
if (i + 1 == bgColors.length) {
offset = 1;
} else {
offset = (max - bgColors[i + 1].upTo) / (max - min);
}
gradient.addColorStop(offset == 1 ? 1 : offset - 0.05, bgc.color);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With