Skip to content
Advertisement

How to add images to chart labels with vue-chartjs?

I want to add flag icons under the country code labels but am completely stuck.

Image of the chart with my current code

The images are named BR.svg, FR.svg and MX.svg and are located under @/assets/icons/flags/

I am using vue@2.6.12 and vue-chartjs@3.5.1 in my project. This is my Chart.vue component:

<script>
import { Bar } from 'vue-chartjs'

export default {
  extends: Bar,
  data: () => ({
    chartdata: {
      labels: ['BR', 'FR', 'MX'],
      datasets: [
        {
          label: 'Lorem ipsum',
          backgroundColor: '#AF78D2',
          data: [39, 30, 30],
        }
      ]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      legend: {
        display: false,
      },
      tooltips: {
        "enabled": false
      },
      scales : {
        xAxes : [ {
            gridLines : {
                display : false
            }
        } ],
        yAxes: [{
          ticks: {
            beginAtZero: true,
            suggestedMin: 0,
            suggestedMax: 40,
            stepSize: 5,
          }
        }]
      },
      "hover": {
        "animationDuration": 0
      },
      "animation": {
        "duration": 1,
        "onComplete": function() {
          var chartInstance = this.chart,
          ctx = chartInstance.ctx;

          ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
          ctx.textAlign = 'center';
          ctx.textBaseline = 'bottom';

          this.data.datasets.forEach(function(dataset, i) {
            var meta = chartInstance.controller.getDatasetMeta(i);
            meta.data.forEach(function(bar, index) {
              var data = dataset.data[index] + '%';
              ctx.fillText(data, bar._model.x, bar._model.y - 5);
            });
          });
        }
      },
    }
  }),
  mounted () {
    this.renderChart(this.chartdata, this.options)
  }
}
</script>

This runnable code below is the closest to a solution I have come by hours of searching. But it still won’t do the trick because I don’t know how to integrate it with what I have.

const labels = ['Red Vans', 'Blue Vans', 'Green Vans', 'Gray Vans'];
const images = ['https://i.stack.imgur.com/2RAv2.png', 'https://i.stack.imgur.com/Tq5DA.png', 'https://i.stack.imgur.com/3KRtW.png', 'https://i.stack.imgur.com/iLyVi.png'];
const values = [48, 56, 33, 44];

new Chart(document.getElementById("myChart"), {
  type: "bar",
  plugins: [{
    afterDraw: chart => {      
      var ctx = chart.chart.ctx; 
      var xAxis = chart.scales['x-axis-0'];
      var yAxis = chart.scales['y-axis-0'];
      xAxis.ticks.forEach((value, index) => {  
        var x = xAxis.getPixelForTick(index);      
        var image = new Image();
        image.src = images[index],
        ctx.drawImage(image, x - 12, yAxis.bottom + 10);
      });      
    }
  }],
  data: {
    labels: labels,
    datasets: [{
      label: 'My Dataset',
      data: values,
      backgroundColor: ['red', 'blue', 'green', 'lightgray']
    }]
  },
  options: {
    responsive: true,
    legend: {
      display: false
    },    
    scales: {
      yAxes: [{ 
        ticks: {
          beginAtZero: true
        }
      }],
      xAxes: [{
        ticks: {
          padding: 30
        }   
      }],
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="90"></canvas>

When I have added the plugin code into my own code I get an error message saying ‘plugins’ is already defined in props, but I can’t manage to use it somehow.

Anyone who knows how to implement this afterDraw plugin into my code? I appreciate any input.

Thanks a lot in advance! 🙂

Advertisement

Answer

In the mounted of your vue component you can call the addPlugin (has to be done before the renderChart method) like this:

this.addPlugin({
  id: 'image-label',
  afterDraw: (chart) => {      
      var ctx = chart.chart.ctx; 
      var xAxis = chart.scales['x-axis-0'];
      var yAxis = chart.scales['y-axis-0'];
      xAxis.ticks.forEach((value, index) => {  
        var x = xAxis.getPixelForTick(index);      
        var image = new Image();
        image.src = images[index],
        ctx.drawImage(image, x - 12, yAxis.bottom + 10);
      });      
    }
})

Documentation: https://vue-chartjs.org/api/#addplugin

Advertisement