Reputation:
I have a line chart like below(without any color)
In this line chart,I want to give color until specific y-Axis value.When it is bigger than 0,from that value till the top,gradient should be applied like below
To achieve this here's my solution below
plugins: [
{
beforeRender: function (c, options) {
var dataset = c.data.datasets[0];
var yScale = c.scales['y-axis-0'];
var yPos = yScale.getPixelForValue(0);
let nonZeroPoint;
for (var i = 0; i < dataset.data.length; i++) {
if (dataset.data[i] != 0) {
nonZeroPoint= dataset.data[i];
break;
}
}
const newHeight = (yPos * nonZeroPoint) / Math.max(...dataset.data);
var gradientFill = c.ctx.createLinearGradient(0, yPos-newHeight, 0, 0);
gradientFill.addColorStop(0.1, "#fff");
gradientFill.addColorStop(1, "#7E0100");
var model = c.data.datasets[0]._meta[Object.keys(dataset._meta)[0]].$filler.el._model;
model.backgroundColor = gradientFill;
}
}
]
In this solution yPos is the height of chart. nonZeroPoint
is a value calculated through for loop to identify the first data value after 0.
newHeight = (yPos * nonZeroPoint) / Math.max(...dataset.data);
This formula calculates the height of nonZeroHeight according to height of top point and its value. But I couldn't get the expected result.Here it is below.How can I fix that?
Codepen:https://codepen.io/Cicek96/pen/GRZBgpN
Upvotes: 0
Views: 464
Reputation: 26150
Using the afterLayout
hook from the Plugin Core API, this could be written as follows:
plugins: [{
afterLayout: c => {
let dataset = c.data.datasets[0];
let yScale = c.scales['y-axis-0'];
let yBottom = yScale.getPixelForValue(0);
let yGradientStart = yScale.getPixelForValue(dataset.data.find(v => v > 0));
let yTop = yScale.getPixelForValue(Math.max(...dataset.data));
let gradientFill = c.ctx.createLinearGradient(0, yBottom, 0, yTop);
gradientFill.addColorStop(0, "#fff");
let offset = (yBottom - yGradientStart) / (yBottom - yTop);
gradientFill.addColorStop(offset, "#fff");
gradientFill.addColorStop(1, "#7E0100");
dataset.backgroundColor = gradientFill;
}
}],
Please take a look at below runnable code and see how it works.
new Chart("chart", {
type: 'line',
plugins: [{
afterLayout: c => {
let dataset = c.data.datasets[0];
let yScale = c.scales['y-axis-0'];
let yBottom = yScale.getPixelForValue(0);
let yGradientStart = yScale.getPixelForValue(dataset.data.find(v => v > 0));
let yTop = yScale.getPixelForValue(Math.max(...dataset.data));
let gradientFill = c.ctx.createLinearGradient(0, yBottom, 0, yTop);
gradientFill.addColorStop(0, "#fff");
let offset = (yBottom - yGradientStart) / (yBottom - yTop);
gradientFill.addColorStop(offset, "#fff");
gradientFill.addColorStop(1, "#7E0100");
dataset.backgroundColor = gradientFill;
}
}],
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
borderColor: '#7E0100',
data: [0, 120, 200, 350, 200, 120, 0]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
max: 500,
stepSize: 100
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chart" height="160"></canvas>
Upvotes: 2