[Chartjs]-How to add images as labels to Canvas Charts using chart.js

14๐Ÿ‘

โœ…

Iโ€™m aware that this is an old post but since it has been viewed so many times, Iโ€™ll describe a solution that works with the current Chart.js version 2.9.3.

The Plugin Core API offers a range of hooks that may be used for performing custom code. You can use the afterDraw hook to draw images (icons) directly on the canvas using CanvasRenderingContext2D.

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);   
      ctx.drawImage(images[index], x - 12, yAxis.bottom + 10);
    });      
  }
}],

The position of the labels will have to be defined through the xAxes.ticks.padding as follows:

xAxes: [{
  ticks: {
    padding: 30
  }   
}],

Please have a look at the following runnable code snippet.

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']
  .map(png => {
    const image = new Image();
    image.src = png;
    return image;
  });
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);   
        ctx.drawImage(images[index], 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>

0๐Ÿ‘

Chart.js v3+ solution to pie, doughnut and polar charts

With version 3 of Chart.js and the updated version of chart.js-plugin-labels, this is now incredbly simple.

in options.plugins.labels, add render: image and the nested array images with objects containing the properties src, width and height.

const data = {
  labels: ['Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5', 'Label 6', 'Label 7', 'Label 8'],
  datasets: [{
    label: 'Image labels',

    // Making each element take up full width, equally divided
    data: [100, 100, 100, 100, 100, 100, 100, 100],
    backgroundColor: [
      'rgba(255, 26, 104, 0.2)',
      'rgba(54, 162, 235, 0.2)',
      'rgba(255, 206, 86, 0.2)',
      'rgba(75, 192, 192, 0.2)',
      'rgba(153, 102, 255, 0.2)',
      'rgba(255, 159, 64, 0.2)',
      'rgba(0, 0, 0, 0.2)',
      'rgba(20, 43, 152, 0.2)'
    ]
  }]
};

const config = {
  type: 'doughnut',
  data,
  options: {
    plugins: {
      // Accessing labels and making them images
      labels: {
        render: 'image',
        images: [{
            src: 'https://cdn0.iconfinder.com/data/icons/google-material-design-3-0/48/ic_book_48px-256.png',
            height: 25,
            width: 25
          },
          {
            src: 'https://cdn3.iconfinder.com/data/icons/glypho-free/64/pen-checkbox-256.png',
            height: 25,
            width: 25
          },
          {
            src: 'https://cdn1.iconfinder.com/data/icons/jumpicon-basic-ui-glyph-1/32/-_Home-House--256.png',
            height: 25,
            width: 25
          },
          {
            src: 'https://cdn1.iconfinder.com/data/icons/social-media-vol-3/24/_google_chrome-256.png',
            height: 25,
            width: 25
          },
          {
            src: 'https://cdn0.iconfinder.com/data/icons/google-material-design-3-0/48/ic_book_48px-256.png',
            height: 25,
            width: 25
          },
          {
            src: 'https://cdn3.iconfinder.com/data/icons/glypho-free/64/pen-checkbox-256.png',
            height: 25,
            width: 25
          },
          {
            src: 'https://cdn1.iconfinder.com/data/icons/jumpicon-basic-ui-glyph-1/32/-_Home-House--256.png',
            height: 25,
            width: 25
          },
          {
            src: 'https://cdn1.iconfinder.com/data/icons/social-media-vol-3/24/_google_chrome-256.png',
            height: 25,
            width: 25
          },
        ]
      }
    }
  }
};

// render init block
const myChart = new Chart(
  document.getElementById('myChart').getContext('2d'),
  config
);
.chartCard {
  width: 100vw;
  height: 500px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chartBox {
  width: 600px;
  padding: 20px;
}
<div class="chartCard">
  <div class="chartBox">
    <canvas id="myChart"></canvas>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://unpkg.com/chart.js-plugin-labels-dv@3.0.5/dist/chartjs-plugin-labels.min.js"></script>

Leave a comment