You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Chart.js条形图图例及堆叠条形图X轴标签中添加图片?

在Chart.js中用图片替代X轴标签及图例插入图片的实现方法

一、用图片替代X轴数字标签

你遇到的问题很典型——Chart.js的默认ticks.callback只能返回文本,直接塞HTML标签肯定会被当成字符串渲染,根本不会解析。要实现图片标签,得用自定义绘制逻辑,结合Chart.js的钩子函数来手动在Canvas上绘制图片,步骤如下:

  1. 提前加载图片资源
    先把要用作标签的图片加载好,确保图片加载完成后再初始化图表,不然会出现空白:

    // 示例:加载两张图标
    const icon1 = new Image();
    const icon2 = new Image();
    const iconsLoaded = Promise.all([
      new Promise(resolve => { icon1.src = 'path/to/icon1.png'; icon1.onload = resolve; }),
      new Promise(resolve => { icon2.src = 'path/to/icon2.png'; icon2.onload = resolve; })
    ]);
    
  2. 配置图表,关闭默认X轴标签,添加afterDraw钩子
    在图表配置里,先把X轴的默认标签隐藏,然后通过plugins.afterDraw钩子,在X轴对应的位置绘制图片:

    iconsLoaded.then(() => {
      const chart = new Chart(document.getElementById('myChart'), {
        type: 'bar',
        data: {
          labels: ['1', '2'], // 这里的标签只是占位,实际会被图片替代
          datasets: [{
            label: '数据集1',
            data: [10, 20],
            backgroundColor: 'rgba(255, 99, 132, 0.2)',
          }]
        },
        options: {
          indexAxis: 'x', // 确保是条形图(垂直柱状图可省略)
          scales: {
            x: {
              ticks: {
                display: false // 隐藏默认数字标签
              }
            }
          },
          plugins: {
            afterDraw: (chart) => {
              const { ctx, scales } = chart;
              const xScale = scales.x;
              // 遍历每个X轴刻度位置,绘制对应图片
              xScale.ticks.forEach((tick, index) => {
                const xPos = xScale.getPixelForTick(index);
                const yPos = chart.height - 10; // 调整图片在X轴下方的位置
                // 根据索引选择对应的图标,这里示例用icon1和icon2
                const icon = index === 0 ? icon1 : icon2;
                // 绘制图片,可调整宽高
                ctx.drawImage(icon, xPos - 15, yPos, 30, 30);
              });
            }
          }
        }
      });
    });
    

    这里的关键是通过getPixelForTick拿到每个X轴刻度的位置,然后用Canvas的drawImage把图片画上去,调整坐标和尺寸就能让图片完美替代原来的数字标签。

二、在条形图图例中插入图片

如果要给图例项添加图片,有两种实用方案:

方案1:自定义Canvas图例(推荐)

利用legend.labels.generateLabels自定义图例项的内容,结合legend.labels.drawCustom来绘制图片:

options: {
  plugins: {
    legend: {
      labels: {
        // 自定义图例项内容,绑定对应图片
        generateLabels: (chart) => {
          return chart.data.datasets.map((dataset, index) => ({
            datasetIndex: index,
            text: dataset.label,
            icon: index === 0 ? icon1 : icon2
          }));
        },
        // 手动绘制图例标记(用图片代替默认方块)
        drawCustom: (chart, args) => {
          const { ctx, legendItems } = args;
          legendItems.forEach((item) => {
            // 绘制图片作为图例标记
            ctx.drawImage(item.icon, item.x, item.y, 20, 20);
            // 绘制图例文本
            ctx.fillText(item.text, item.x + 25, item.y + 15);
          });
        },
        // 关闭默认图例标记绘制
        usePointStyle: false,
        boxWidth: 0
      }
    }
  }
}

方案2:HTML自定义图例

如果更熟悉HTML操作,可以关闭Chart.js的默认图例,自己手动创建HTML图例,这样可以直接用<img>标签:

options: {
  plugins: {
    legend: {
      display: false // 关闭默认图例
    }
  }
}

然后在页面中添加HTML图例:

<div class="custom-legend">
  <div class="legend-item">
    <img src="path/to/icon1.png" alt="数据集1">
    <span>数据集1</span>
  </div>
  <div class="legend-item">
    <img src="path/to/icon2.png" alt="数据集2">
    <span>数据集2</span>
  </div>
</div>

再给图例项绑定点击事件,实现和默认图例一样的显示/隐藏数据集功能:

document.querySelectorAll('.legend-item').forEach((item, index) => {
  item.addEventListener('click', () => {
    const dataset = chart.data.datasets[index];
    dataset.hidden = !dataset.hidden;
    chart.update();
  });
});

注意事项

  • 确保图片路径正确,跨域图片需要配置crossOrigin属性(比如icon1.crossOrigin = 'anonymous'),否则Canvas绘制会报错。
  • 调整图片的位置和尺寸时,要结合图表的实际布局,避免和图表内容重叠。

内容的提问来源于stack exchange,提问作者Aasim Azam

火山引擎 最新活动