Search code examples
vue.jschartsvuejs2vue-chartjs

Vue Chart.js - simple dot/line on bar chart


I'd need to add a simple dot/vertical line on my bar chart that has a dynamical X value, and 0 for Y value. Preview of what I need (the red dot):

enter image description here

Where the green values are dynamic.

Preview of my current state:

enter image description here

Where 3.30 should be the X coordinate of the dot - [3.30, 0].

I'm using Vue chart for the charts and I tried do create a mixed one with the bar and scatter but scatter requires type: 'linear' for it's xAxis which doesn't suit my need for the bar chart.

So I tried with chartjs-plugin-annotation and it's box type which accepts "coordinates" but the problem here is that the X value must be a fixed value on the X axis (labels object). If I put for the X axis [3,0] it will work, but if there is a decimal number, like [3.5, 0], it won't work.


  // data
  options: {
    responsive: true,
    maintainAspectRatio: false,
    legend: {
      display: false
    },
    scales: {
      yAxes: [{
        ticks: {
          min: 0,
          max: 1,
          stepSize: 0.1
        }
      }]
    }
  }

  // computed 
  labels: [1, 2, 3, 4, 5, 6], // fixed value, there are always 6 bars
  datasets: [
    {
      label: 'Values',
      backgroundColor: '#f89098',
      data: this.tableInputValues // array of decimal values
    }
  ]

So, my question is how to put a "simple" dot, or a vertical line, on a Chart.js bar chart where the dot has a dynamical value for the X axis -> [dynamic value, 0].

FYI - it's about Expected value


Solution

  • As far as I understand Vue Chart works using canvas (as seen on Demo page).
    So, my suggestion here is to retrieve the canvas node representing the chart in your DOM and dynamically write the desired dot. For example:

    var c = document.getElementById("bar-chart");   //hereby assuming canvas named "bar-chart"
    var ctx = c.getContext("2d");
    ctx.fillStyle = "#ff0000";                     //red color for the dot
    ctx.beginPath();
    let yPosition = c.height - 5;                 //fixed y position
    let xPosition = 35;                          //that's the dynamic expected value
    ctx.arc(xPosition, yPosition, 2.5, 0, 2 * Math.PI);
    ctx.fill();
    

    Here you find a demo showing how to achieve that using Vue. In this scenario, you need to wrap the code to draw a dot on the canvas in a afterDraw hook. This hook needs to be attached to the chart component as a plugin, so like this:

    ...
    mounted () { 
       //adding the plugin to draw the red dot
       this.addPlugin({
        id: 'chart-plugin',
        afterDraw: function (chart) {
           var c = chart.canvas;   
           var ctx = c.getContext("2d");
           ctx.fillStyle = "#ff0000";                     
           ctx.beginPath();
           let xPosition = 742; //x positioning to be calculated according to your needs
           let yPosition = c.height - 28;                                       
           ctx.arc(xPosition, yPosition, 3, 0, 2 * Math.PI);
           ctx.fill();
        }
      });
    
      //actual chart rendering
      this.renderChart({ 
        ...
      });
    }
    ...
    

    For the sake of completeness, here you find the list of all the available hooks of Chart.js plugin API.