Chart JS flicker when new data is added to chart (Vue)

Viewed 380

I have a Nuxt JS project utilising Chart JS and the Vue Chart JS wrapper. My chart is on the page and visible to the user and new data is added to the chart each time, but old data is never removed (that's labels and data for context)

When I update my chart, I initially call the update() method, but also do some cloning to get the chart to update correctly.

However, for some reason, each time the chart updates, lines on the chart as part of my datasets seem to flicker and quickly move down and back up again when new data is added and I don't know why, am I missing an option?

The <canvas> element that is in the page never gets removed, just updated with new data.

Since I can't attach a video here, I'll attach my Chart JS plugin with configuration and a scerenshot for context.

import { Line, mixins } from 'vue-chartjs'
import _ from 'lodash';
const { reactiveProp } = mixins

export default {
  extends: Line,
  mixins: [reactiveProp],
  data () {
    return {
      options: {
        responsive: true,
        maintainAspectRatio: false,
        legend: {
          display: false
        },
        scales: {
          yAxes: [{
            gridLines: {
              display: true,
              color: '#eceaea'
            },
          }],
          xAxes: [{
            gridLines: {
              display: false
            },
            ticks: {
              autoSkip: true,
              maxTicksLimit: window.innerWidth < 575 ? 2.1 : 4.1,
              maxRotation: 0,
              minRotation: 0
            }
          }]
        },
        elements: {
          point: {
            radius: 0,
            hitRadius: 35
          }
        }
      }
    }
  },
  mounted () {
    this.renderLineChart()
  },
  methods: {

    /*
    ** Get chart options
    */
    getChartOptions () {
      return this.options
    },

    /*
    ** Render a line chart
    */
    renderLineChart () {
      const options = this.getChartOptions()

      // this.chartdata is created in the mixin.
      // If you want to pass options please create a local options object
      this.renderChart(this.localData, options)
    }

  },
  computed: {
    localData: function() {
      return this.chartData
    }
  },
  watch: {
    chartData: {
      handler: function (val, oldVal) {
        const options = this.getChartOptions()
        const clone = _.cloneDeep(this.localData)
        this._data._chart.update()
        this.renderChart(clone, options)
      },
      deep: true
    }
  }
}

And how my chart looks:

chart

UPDATE

Here's a link to the animation and behaviour I'm talking about: https://www.loom.com/share/a0049ed4a6c54367a82f18452b147903

2 Answers

Seems like you try to call the update method and the renderChart method of the vue wrapper, this makes the chart first try and update and thus will start animating but then you call render so it will render from scratch, try to only call the update method because if you give new values to chart.js and call the update it handles it internally to render the chart again.

I used

this.myChart.destroy()
this.drawchart() 

as a workaround in the past. (instead of this.myChart.update() )

destroy() come form the library itself and drawchart() was my own written function.

Part of my chart function, btw. i didn't used any vue implemtation, i used the chart.js barebone, maybe your problem is the package itselfe?

drawchart() {
                this.ctx = this.$refs['myCanvas'].getContext("2d");
                Chart.defaults.global.defaultColor = "rgba(0, 1, 0, 0.1)"
                this.myChart = new Chart(this.ctx, {
                        type: 'bar',
                        data: {
                  
                            labels: this.modelarr,
                            datasets: [{
                                data: this.placeholderData[this.picked]
                            }]
                        },
                        options: {
                            showTooltips: false,
                            scales: {
                                yAxes: [{
                                    ticks: {
                                        min: 0
                                    }
                                }]
                            },                         
                            responsive: true
                        }
                    }),
             
            },

    }
Related