如何使用 chart.js 将图像作为标签添加到 Canvas 图表

How to add images as labels to Canvas Charts using chart.js

我正在生成 chart.js canvas 条形图。我想要做的是,在标签数组内部,添加每个标签附带的图像,而不是仅仅添加文本标签本身。这是图表的代码:我从中获取数据的 json 对象有一个图像 url,我想用它来显示图片:

$.ajax({
method: "get",
url: "http://localhost:3000/admin/stats/show",
dataType: "json",
error: function() {
  console.log("Sorry, something went wrong");
},
success: function(response) {
  console.log(response)
  var objectToUse = response.top_dogs
  var updateLabels = [];
  var updateData = [];
  for (var i = 0; i < objectToUse.length; i+=1) {
    updateData.push(objectToUse[i].win_percentage * 100);
    updateLabels.push(objectToUse[i].title);
  }
  var data = {
    labels: updateLabels,
    datasets: [
      {
        label: "Top Winners Overall",
        fillColor: get_random_color(),
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: get_random_color(),
        highlightStroke: "rgba(220,220,220,1)",
        data: updateData
      }
    ]
  };

  var options = {
    //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
    scaleBeginAtZero : true,

    //Boolean - Whether grid lines are shown across the chart
    scaleShowGridLines : true,

    //String - Colour of the grid lines
    scaleGridLineColor : "rgba(0,0,0,.05)",

    //Number - Width of the grid lines
    scaleGridLineWidth : 1,

    //Boolean - Whether to show horizontal lines (except X axis)
    scaleShowHorizontalLines: true,

    //Boolean - Whether to show vertical lines (except Y axis)
    scaleShowVerticalLines: true,

    //Boolean - If there is a stroke on each bar
    barShowStroke : true,

    //Number - Pixel width of the bar stroke
    barStrokeWidth : 2,

    //Number - Spacing between each of the X value sets
    barValueSpacing : 5,

    //Number - Spacing between data sets within X values
    barDatasetSpacing : 2,
  };

  var loadNewChart = new Chart(barChart).Bar(data, options);
  }    

});

如果有人有解决方案,将不胜感激!

我知道这是一个旧的 post,但由于它已经被查看了很多次,我将描述一个适用于当前 Chart.js 版本 2.9.3 的解决方案。

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

标签的位置必须通过 xAxes.ticks.padding 定义如下:

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

请查看以下可运行代码片段。

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>

Chart.js饼图、圆环图和极坐标图的v3+解决方案

有了 Chart.js 的第 3 版和 chart.js-plugin-labels 的更新版本,这现在非常简单。

options.plugins.labels 中,添加 render: image 和包含属性 srcwidthheight 的对象的嵌套数组 images

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>