饼图图例 - Chart.js

Pie Chart Legend - Chart.js

我需要帮助将饼图的数字放入图例中

Chart Image

如果我将鼠标悬停在图表上,我可以看到与每个项目相关的数字

我也想在图例中显示它

到目前为止的重要代码:

var tempData = {
    labels: Status,
    datasets: [
        {
            label: "Status",
            data: Qtd,
            backgroundColor: randColor
        },

    ]
};

var ctx = $("#pieStatus").get(0).getContext("2d");
var chartInstance = new Chart(ctx, {
    type: 'pie',
    data: tempData,
    options: {
         title: {
            display: true,
            fontsize: 14,
            text: 'Total de Pedidos por Situação'
        },
        legend: {
            display: true,
            position: 'bottom',

        },
        responsive: false
    }

});

"Qtd","randColor" are "var" already with values

您需要在选项中编辑 generateLabels 属性 :

options: {
    legend: {
        labels: {
            generateLabels: function(chart) {
                 // Here
            }
        }
    }
}


因为自己创建一个很棒的模板是一件很麻烦的事情。我建议使用与 the source code 中相同的功能,然后编辑需要的内容。

这是一个 small jsFiddle,您可以在其中查看它的工作原理(编辑的行 - 来自 38 - 已注释),及其结果:

我想让用户 select 来自 100 多个数据集,而不是 adding/removing 他们来自我的 图表 我决定设置 showLine: false 在我想隐藏的任何数据集上。不幸的是,默认的 legend 会显示全部 100+。所以在我的解决方案中,我手动生成图例,过滤掉任何具有 showLine: false.

的数据集

您的设置将是这样的:

legend: {
  labels: {
    generateLabels: (a) => {
      return a.data.labels
    }
  }

您将使用辅助函数生成自己的标签:

function updateAllLabels() {
  const myNewLabels = [];

  myChart.data.datasets.forEach((element) => {
    if (element.showLine) {
      myNewLabels.push(generateLabel(element));
    }
  });

  myChart.data.labels = myNewLabels;
}

您将使用另一个函数生成标签:

function generateLabel(data) {
  return {
    fillStyle: data.borderColor,
    lineWidth: 1,
    strokeStyle: data.borderColor,
    text: data.countyName, // I attach countryName to my datasets for convenience
  }
}

现在请不要忘记在更新图表时调用该函数:

updateAllLabels();
myChart.update();

快乐的制图!

根据 tektiv 的回答,我针对我的 linter 需要的 ES6 修改了它;

options: {
  legend: {
    labels: {
      generateLabels: (chart) => {
        const { data } = chart;
        if (data.labels.length && data.datasets.length) {
          return data.labels.map((label, i) => {
            const meta = chart.getDatasetMeta(0);
            const ds = data.datasets[0];
            const arc = meta.data[i];
            const custom = (arc && arc.custom) || {};
            const { getValueAtIndexOrDefault } = Chart.helpers;
            const arcOpts = chart.options.elements.arc;
            const fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
            const stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
            const bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
            const value = chart.config.data.datasets[arc._datasetIndex].data[arc._index];

            return {
              text: `${label}: ${value}`,
              fillStyle: fill,
              strokeStyle: stroke,
              lineWidth: bw,
              hidden: Number.isNaN(ds.data[i]) || meta.data[i].hidden,
              index: i,
            };
          });
        }
        return [];
      },
    },
  },
},

也许这是一个 hacky 解决方案,但对我来说似乎更简单。

filter参数

ChartJS legend options 有一个 filter 参数。这是为每个图例项调用的函数,并且 returns true/false 是否要在图例中显示此项目。

filter 有 2 个参数:

  • legendItem : show/omit 的图例项。其属性描述为 here
  • data : 传递给图表的数据对象。

黑客

由于 JS 通过引用传递对象,并且为每个图例项调用 filter,因此您可以改变 legendItem 对象以显示您想要的文本。

legend : {
  labels: {
    filter: (legendItem, data) => {
      // First, retrieve the data corresponding to that label
      const label = legendItem.text
      const labelIndex = _.findIndex(data.labels, (labelName) => labelName === label) // I'm using lodash here
      const qtd = data.datasets[0].data[labelIndex]
      
      // Second, mutate the legendItem to include the new text
      legendItem.text = `${legendItem.text} : ${qtd}`
      
      // Third, the filter method expects a bool, so return true to show the modified legendItem in the legend
      return true
    }
  }
}