【问题标题】:ChartJS: datalabels: show percentage value in Pie pieceChartJS:datalabels:在饼图中显示百分比值
【发布时间】:2018-08-27 17:09:46
【问题描述】:

我有一个带有四个标签的饼图:

var data = [{
    data: [50, 55, 60, 33],
    labels: ["India", "China", "US", "Canada"],
    backgroundColor: [
        "#4b77a9",
        "#5f255f",
        "#d21243",
        "#B27200"
    ],
    borderColor: "#fff"
}];

使用chartjs-plugin-datalabels 插件,我想用下面的代码在每个 Pie 中显示百分比值:

formatter: (value, ctx) => {

        let datasets = ctx.chart.data.datasets;

        if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
            let sum = 0;
            datasets.map(dataset => {
                sum += dataset.data[ctx.dataIndex];
            });
            let percentage = Math.round((value / sum) * 100) + '%';
            return percentage;
        } else {
            return percentage;
        }
    },
    color: '#fff',
}

我得到所有馅饼的 100% 价值,而不是各自的百分比。 这是 JSFiddle (https://jsfiddle.net/kingBethal/a1Lvn4eb/7/)

【问题讨论】:

  • 我知道chartjs-plugin-labels 可以实现这一点,但我更喜欢chartjs-plugin-datalabels,因为我依赖这个插件来实现其他图表功能。

标签: javascript charts chart.js


【解决方案1】:

更新了 2 位小数精度的小提琴。

您没有计算总和,而是仅将每个值的当前值存储在总和中。

这是工作小提琴:https://jsfiddle.net/a1Lvn4eb/55/

var data = [{
    data: [50, 55, 60, 33],
    labels: ["India", "China", "US", "Canada"],
    backgroundColor: [
        "#4b77a9",
        "#5f255f",
        "#d21243",
        "#B27200"
    ],
    borderColor: "#fff"
}];

var options = {
    tooltips: {
        enabled: false
    },
    plugins: {
        datalabels: {
            formatter: (value, ctx) => {
                let sum = 0;
                let dataArr = ctx.chart.data.datasets[0].data;
                dataArr.map(data => {
                    sum += data;
                });
                let percentage = (value*100 / sum).toFixed(2)+"%";
                return percentage;
            },
            color: '#fff',
        }
    }
};

var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
    type: 'pie',
    data: {
        datasets: data
    },
    options: options
});

【讨论】:

  • 不,[50, 55, 60, 33] 是数据值,我想显示总和的相应百分比。应该是[25.25%, 27.77%, 3.3%, 16.66%]
  • 对不起,我的错误,更新了答案。您还需要 2 点精度吗?
  • 已按要求更新:)
  • 如果图表上有 0% 值和任何特定标签(例如:中国),我该如何隐藏。
  • 谢谢@Hiteshdua1,但它不适用于多个数据集。在我们有折线图的情况下
【解决方案2】:

我想在接受的答案中添加一点, ctx.chart.data.datasets[0].data 始终为您提供完整数据,即使您通过单击图例过滤掉一些数据,这意味着即使您过滤掉一些国家,您也将始终获得一个国家的相同百分比。

我使用context.dataset._meta[0].total 来获得过滤后的总数。

这里是工作的 sn-p:

var data = [{
  data: [50, 55, 60, 33],
  backgroundColor: [
    "#4b77a9",
    "#5f255f",
    "#d21243",
    "#B27200"
  ],
  borderColor: "#fff"
}];

var options = {
  tooltips: {
    enabled: true
  },
  plugins: {
    datalabels: {
      formatter: (value, ctx) => {

        let sum = ctx.dataset._meta[0].total;
        let percentage = (value * 100 / sum).toFixed(2) + "%";
        return percentage;


      },
      color: '#fff',
    }
  }
};


var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
  type: 'pie',
  data: {
  labels: ['India', 'China', 'US', 'Canada'],
    datasets: data
  },
  options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@0.7.0"></script>
<canvas id="pie-chart"></canvas>

【讨论】:

  • 谢谢 - 但这实际上不需要 jquery,对吗?
  • 是的,它不需要 jquery。
  • 显然它不适用于 chartjs v3.7.0 和 chartjs-plugin-datalabels v2.0.0 版本。 _meta 不是有效变量(不再是?)。试图弄清楚还有什么可能有效。背景:我还想根据可见的百分比更新百分比。
  • 我想出了一个丑陋的猴子补丁解决方法,我将作为新答案发布,因为这个评论系统不适合。对不起。不过,我将其发布在此线程中! --> stackoverflow.com/a/71068131/6830478
【解决方案3】:

问题在于您如何计算总和。见下文。

Fiddle

 var data = [{
   data: [50, 55, 60, 33],
   labels: ["India", "China", "US", "Canada"],
   backgroundColor: [
     "#4b77a9",
     "#5f255f",
     "#d21243",
     "#B27200"
   ],
   borderColor: "#fff"
 }];

 var options = {
   tooltips: {
     enabled: false
   },
   plugins: {
     datalabels: {
       formatter: (value, ctx) => {

         let datasets = ctx.chart.data.datasets;

         if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
           let sum = datasets[0].data.reduce((a, b) => a + b, 0);
           let percentage = Math.round((value / sum) * 100) + '%';
           return percentage;
         } else {
           return percentage;
         }
       },
       color: '#fff',
     }
   }
 };


 var ctx = document.getElementById("pie-chart").getContext('2d');
 var myChart = new Chart(ctx, {
   type: 'pie',
   data: {
     datasets: data
   },
   options: options
 });

【讨论】:

  • 谢谢迈克尔,它也有效。我更喜欢@Hiteshdua1 的答案,因为它也显示 2 位小数,这是我需要的。
  • 抱歉,在最新版本的 chartjs 3.0 中它对我不起作用,我也更新了插件
【解决方案4】:

您可以使用带有 Array reducer 的工具提示来执行百分比计算并显示它。

  tooltips: {
    callbacks: {
      label: function (tooltipItem, data) {
        try {
          let label = ' ' + data.labels[tooltipItem.index] || '';

          if (label) {
            label += ': ';
          }

          const sum = data.datasets[0].data.reduce((accumulator, curValue) => {
            return accumulator + curValue;
          });
          const value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];

          label += Number((value / sum) * 100).toFixed(2) + '%';
          return label;
        } catch (error) {
          console.log(error);
        }
      }
    }
  }

【讨论】:

  • 我不得不更改reduce方法的一个小改动:return parseInt(accumulator) + parseInt(curValue);
【解决方案5】:

这是 chart.js >= 3.x 和 chartjs-plugin-datalabels >= 2.x 的更新

chartjs-plugin-datalabels插件不再自动注册 (docs)

你必须手动完成

为所有图表注册插件

Chart.register(ChartDataLabels)

或仅针对特定图表

var chart = new Chart(ctx, {
  plugins: [ChartDataLabels],
  options: {
    // ...
  }
})

下面是呈现饼图的代码

var data = [{
  data: [50, 55, 60, 33],
  backgroundColor: [
    "#4b77a9",
    "#5f255f",
    "#d21243",
    "#B27200"
  ],
  borderColor: "#fff"
}];

var options = {
  tooltips: {
    enabled: false
  },
  plugins: {
    datalabels: {
      formatter: (value, ctx) => {
        const datapoints = ctx.chart.data.datasets[0].data
         const total = datapoints.reduce((total, datapoint) => total + datapoint, 0)
        const percentage = value / total * 100
        return percentage.toFixed(2) + "%";
      },
      color: '#fff',
    }
  }
};

var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
  type: 'pie',
  data: {
  labels: ['India', 'China', 'US', 'Canada'],
    datasets: data
  },
  options: options,
  plugins: [ChartDataLabels],
});
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.2/chart.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"></script>
  <style>
.container {
width: 40%;
margin: 5px auto;
}
  </style>
  <div class="container">
<canvas id="pie-chart"></canvas>
  </div>

【讨论】:

  • 您的回答对我非常有用-但问题是我使用辅助脚本以[{"student_name":"APNET","marks":"45"},{"student_name":"ARZ","marks":"55"}] 之类的格式提供最终输出-所以我没有简单的数据:[45, 55](什么有效!)但我认为data: marks下的["45", "55"]之类的东西 - 结果计算完全错误。是否可以在 formatter: (value, ctx) =&gt; { 的开头某处 str_replace 尝试从 ["45", "55"] 中删除双重相当,我认为 data: marks 传递给 const datapoints = ctx.chart.data.datasets[0].data
【解决方案6】:

如果你使用 nodejs: 请按照以下步骤操作:

  1. npm install chartjs-plugin-datalabels
  2. 从“chartjs-plugin-datalabels”导入 ChartDataLabels;
  3. Chart.register(...registerables, ChartDataLabels);
  4. 从 over cmets 复制代码...

https://chartjs-plugin-datalabels.netlify.app/guide/#table-of-contents

【讨论】:

    【解决方案7】:

    我正在使用 ChartJS v3.7.0 和 chartjs-plugin-datalabels v2.0.0 以及这个答案:

    https://stackoverflow.com/a/59403435/6830478

    真的不适合我,而我只是想保持百分比最新,隐藏元素时也是如此。 ctx.dataset._meta 似乎不再可用。我想出了一些丑陋的猴子补丁:

    formatter: function(value, context) {
        var hiddens = context.chart._hiddenIndices;
        var total = 0;
        var datapoints = context.dataset.data;
        datapoints.forEach((val, i) => {
            if (hiddens[i] != undefined) {
                if (!hiddens[i]) {
                    total += val;
                }
            } else {
                total += val;
            }
        });
        var percentage = (value / total * 100).toFixed(2) + '%';
        var out = context.chart.data.labels[context.dataIndex] + '\n' + percentage;
        return out;
    }
    

    Hopw 这可能对任何人都有帮助。干杯。

    【讨论】:

      【解决方案8】:

      正如一些人提到的,context.dataset._meta[0].total 似乎已在 chart.js 版本 3 及更高版本中被删除并且不再工作了。相反,我使用了context.chart.getDatasetMeta(0).total,它对我有用——它在饼图中显示百分比值,当点击图例时,值会根据过滤后的总数进行更新。

            options:{ 
              plugins:{         
                datalabels: {
                  color: 'white',
                  formatter: function(value, context) {                  
                    return Math.round(value/context.chart.getDatasetMeta(0).total * 100) + "%" ;
                  }
                }
              }
            }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多