Gidimotje
Gidimotje

Reputation: 477

Vue.js Vue-chart.js linear gradient background fill

I would like to have a linear gradient background on my Vue-chart.js line chart. For the love of God, I can't find any useful example and the documentation doesn't really provide either.

I loaded in the Line component from vue-chartjs and have set up a template like below:

<template>
  <Line
    :chartData="chartData"
    :chartOptions="chartOptions"
    :chartId="chartId"
    :width="width"
    :height="height"
    :cssClasses="cssClasses"
    :styles="styles"
    :plugins="plugins"
  />
</template>

With that, I have the following script:

<script>
import { Line } from 'vue-chartjs'
import {
  Chart as ChartJS,
  Title,
  Tooltip,
  Legend,
  LineElement,
  CategoryScale,
  LinearScale,
  PointElement,
  Plugin,
  Filler,
  BorderRadius
} from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, LineElement, LinearScale, CategoryScale, PointElement, Filler)

export default {
  name: 'BarChart',
  components: { Line },
  props: {
    chartId: {
      type: String,
      default: 'line-chart'
    },
    width: {
      type: Number,
      default: 400
    },
    height: {
      type: Number,
      default: 160
    },
    cssClasses: {
      default: '',
      type: String
    },
    styles: {
      type: Object,
      default: () => {}
    },
    plugins: {
      type: Array,
      default: () => []
    }
  },
  mounted () {
    const canvas = document.getElementById('line-chart').getContext('2d');
    const gradient = canvas.createLinearGradient(0,0,0,160);

    gradient.addColorStop(0, 'green');
    gradient.addColorStop(.5, 'cyan');
    gradient.addColorStop(1, 'green');

    this.gradient = gradient;

    console.log(this.gradient);

  },
  data() {
    return {
      chartData: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [
          {
            label: 'Data One',
            borderColor: '#FC2525',
            pointBackgroundColor: 'white',
            borderWidth: 1,
            radius: 0,
            fill: true,
            pointBorderColor: 'white',
            backgroundColor: this.gradient,
            tension: 0.25,
            data: [40, 39, 10, 40, 39, 80, 40]
          },{
            label: 'Data Two',
            borderColor: '#05CBE1',
            pointBackgroundColor: 'white',
            pointBorderColor: 'white',
            borderWidth: 1,
            radius: 0,
            fill: true,
            backgroundColor: this.gradient,
            tension: 0.25,
            data: [60, 55, 32, 10, 2, 12, 53]
          }
        ]
      },
      chartOptions: {
        responsive: true,
        plugins: {
          legend: {
            display: false
          }
        }
      }
    }
  },
}
</script>

And yet, this results in the default grey background.

Any help would be appreciated.

Upvotes: 1

Views: 5798

Answers (1)

LeeLenalee
LeeLenalee

Reputation: 31341

This is because when mounted gets fired the options have already been build and this.gradient was undefined at the time so it will put undefined in there. After that you never update your options.

Not sure if you can just set the options and the chart will update to the correct color.

What does work is provide a function to the background prop from which you can get the context like so:

<script>
import { Line } from 'vue-chartjs'
import {
  Chart as ChartJS,
  Title,
  Tooltip,
  Legend,
  LineElement,
  CategoryScale,
  LinearScale,
  PointElement,
  Plugin,
  Filler,
  BorderRadius
} from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, LineElement, LinearScale, CategoryScale, PointElement, Filler)

export default {
  name: 'BarChart',
  components: { Line },
  props: {
    chartId: {
      type: String,
      default: 'line-chart'
    },
    width: {
      type: Number,
      default: 400
    },
    height: {
      type: Number,
      default: 160
    },
    cssClasses: {
      default: '',
      type: String
    },
    styles: {
      type: Object,
      default: () => {}
    },
    plugins: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      chartData: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [
          {
            label: 'Data One',
            borderColor: '#FC2525',
            pointBackgroundColor: 'white',
            borderWidth: 1,
            radius: 0,
            fill: true,
            pointBorderColor: 'white',
            backgroundColor: (ctx) => {
              const canvas = ctx.chart.ctx;
              const gradient = canvas.createLinearGradient(0,0,0,160);

              gradient.addColorStop(0, 'green');
              gradient.addColorStop(.5, 'cyan');
              gradient.addColorStop(1, 'green');

              return gradient;
            },
            tension: 0.25,
            data: [40, 39, 10, 40, 39, 80, 40]
          },{
            label: 'Data Two',
            borderColor: '#05CBE1',
            pointBackgroundColor: 'white',
            pointBorderColor: 'white',
            borderWidth: 1,
            radius: 0,
            fill: true,
            backgroundColor: (ctx) => {
              const canvas = ctx.chart.ctx;
              const gradient = canvas.createLinearGradient(0,0,0,160);

              gradient.addColorStop(0, 'green');
              gradient.addColorStop(.5, 'cyan');
              gradient.addColorStop(1, 'green');

              return gradient;
            },
            tension: 0.25,
            data: [60, 55, 32, 10, 2, 12, 53]
          }
        ]
      },
      chartOptions: {
        responsive: true,
        plugins: {
          legend: {
            display: false
          }
        }
      }
    }
  },
}
</script>

Upvotes: 5

Related Questions