user6084102
user6084102

Reputation:

How to paint specific area of chartJs?

I have a line chart like below(without any color) enter image description here

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 enter image description here

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?

enter image description here

Codepen:https://codepen.io/Cicek96/pen/GRZBgpN

Upvotes: 0

Views: 464

Answers (1)

uminder
uminder

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

Related Questions