0
votes

I'm using chartjs with vue-chart to display some data in my application and actually what I would like to achieve is to have a Bar chart with a background color from red to green.

The chart has dynamic min and max values but it cannot be less than 0 and greater than 5. Similar to a 5 star rating.

In order to show differences in the displayed data I'm not fixing the chart min/max from 0 to 5.

Currently this is the code to show my chart:

Options:

  • min is -0.2 than minimum value but not less than 0;

  • max is +0.2 than maximum value but not greater than 5;

    return {
      legend: {
        display: false
      },
      scales: {
        yAxes: [
          {
            ticks: {
              beginAtZero: true,
              min,
              max,
              stepSize: 0.5
            }
          }
        ]
      }
    }
    

Bar chart data:

  return {
    labels: this.labels,
    datasets: [
      {
        label: 'Evaluation',
        data: [
          this.photo.composition,
          this.photo.technique,
          this.photo.creativity,
          this.photo.content,
          this.photo.lighting
        ],
        borderWidth: 1
      }
    ]
  }

Render chart:

  const gradient = this.$refs.canvas
    .getContext('2d')
    .createLinearGradient(0, 300, 0, 0)
  gradient.addColorStop(0, '#FF5722')
  gradient.addColorStop(0.5, '#FFC107')
  gradient.addColorStop(1, '#8BC34A')

  this.data.datasets[0].backgroundColor = gradient
  this.renderChart(this.data, this.options)

The result is pretty close to what I'm looking for:

enter image description here

Unfortunately what I would like to see is the red color on 0 and green on 5 so the gradient should not reach the green if maximum value is 2.5 (here I would expect the orange) and the same for lower values... I hope it make sense. Can someone point me to the right direction? Thanks!

1

1 Answers

1
votes

The Plugin Core API offers a range of hooks that may be used for performing custom code. You can use the afterLayout hook for creating a gradient for the y-axis that spreads that desired area (values 0 to 5).

let yAxis = chart.scales["y-axis-0"];
let yBottom = yAxis.getPixelForValue(0);
let yTop = yAxis.getPixelForValue(5);          
let gradient = ctx.createLinearGradient(0, yBottom, 0, yTop);  

Please take a look at below sample and see how it works.

const data = [2, 2.25, 3.3];

new Chart(document.getElementById("chart"), {
  type: "bar",
  plugins: [{
    afterLayout: chart => {
      let ctx = chart.chart.ctx;
      ctx.save();
      let yAxis = chart.scales["y-axis-0"];
      let yBottom = yAxis.getPixelForValue(0);
      let yTop = yAxis.getPixelForValue(5);          
      let gradient = ctx.createLinearGradient(0, yBottom, 0, yTop);   
      gradient.addColorStop(0, '#FF5722');           
      gradient.addColorStop(0.5, '#FFC107'); 
      gradient.addColorStop(1, '#8BC34A');           
      chart.data.datasets[0].backgroundColor = gradient;
      ctx.restore();
    }
  }],
  data: {
    labels: ["A", "B", "C"],
    datasets: [{
      label: "Evaluation",
      data: data
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          min: Math.min(...data) - 0.2,
          max: Math.max(...data) + 0.2,
          stepSize: 0.5
        }
      }]
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="chart" height="80"></canvas>