如何在堆叠条上同时显示数据标签和总和

问题描述 投票:0回答:3

我尝试在堆叠条形图中同时显示数据标签和总和。

我使用chartjs-plugin-datalabels.js来显示数据标签或总和。

上面只是数据标签:

上面只是求和:

我希望将两者放在同一个图表中。

我使用以下技巧来求和显示:

<script>
    const totalizer = {
  id: 'totalizer',

  beforeUpdate: chart => {
    let totals = {}
    let utmost = 0

    chart.data.datasets.forEach((dataset, datasetIndex) => {
      if (chart.isDatasetVisible(datasetIndex)) {
        utmost = datasetIndex
        dataset.data.forEach((value, index) => {
          totals[index] = (totals[index] || 0) + value
        })
      }
    })

    chart.$totalizer = {
      totals: totals,
      utmost: utmost
    }
  }
}

new Chart('chart', {
  type: 'bar',
  data: {
    labels: ["Note par thème du répondant", "Note par thème sectorielle", "Note par thème générale"],
    datasets: [{
            label: 'Thème 1',
            data: [12, 19, 3],
            backgroundColor: 'rgba(255, 206, 86)'            
        },
        {
            label: 'Thème 2',
            data: [3,8,1],
            backgroundColor: 'rgba(54, 162, 235)'                        
        },
        {
            label: 'Thème 3',
            data: [ 5, 2, 3],
            backgroundColor: 'rgba(255, 255, 132)'                
        },{
            label: 'Thème 4',
            data: [ 5, 2, 3],
            backgroundColor: 'rgba(255, 99, 255)'                
        },{
            label: 'Thème 5',
            data: [ 5, 2, 3],
            backgroundColor: 'rgba(100, 250, 132)'                
        },{
            label: 'Thème 6',
            data: [ 5, 2, 3],
            backgroundColor: 'rgba(89, 99, 132)'                
        },{
            label: 'Thème 7',
            data: [ 5, 2, 3],
            backgroundColor: 'rgba(255, 0, 132)'                
        },{
            label: 'Thème 8',
            data: [ 5, 2, 3],
            backgroundColor: 'rgba(0, 150, 255)'                
        },{
            label: 'Thème 9',
            data: [ 5, 2, 3],
            backgroundColor: 'rgba(100, 100, 100)'                
        },{
            label: 'Thème 10',
            data: [ 10, 4, 7],
            backgroundColor: 'rgba(255, 255, 0)'                
        }]
  },
  options: {
    title :{
        display :true,
        text : "Mon titre"
    },
    scales: {   
      yAxes: [{
        stacked: true,
        ticks: {
          beginAtZero: true,
          suggestedMax: 100
        }
      }],
      xAxes: [{
        stacked: true
      }]
    },
    plugins: {
      datalabels: {
        formatter: (value, ctx) => {
          const total = ctx.chart.$totalizer.totals[ctx.dataIndex]
          return total.toLocaleString('fr-FR', {})
        },
        align: 'end',
        anchor: 'end',
        display: function(ctx) {
          return ctx.datasetIndex === ctx.chart.$totalizer.utmost
        }
      }
    }
  },
  plugins: [totalizer]
});
    </script>

我将不胜感激任何帮助。谢谢!

chart.js
3个回答
2
投票

好的,我找到了同时显示 Sum 和数据标签的方法。

我添加新的数据集来表示具有透明背景颜色的“总数据”,并在我的数据集中添加以下代码:Total:

        datalabels: {
            backgroundColor: function (context) {

                return 'rgba(244,50,49)';

            },
            formatter: (value, ctx) => {
                const total = ctx.chart.$totalizer.totals[ctx.dataIndex];
                return total.toLocaleString('fr-FR', {})
            },
            align: 'end',
            anchor: 'end',
            display: function (ctx) {
                return ctx.datasetIndex === ctx.chart.$totalizer.utmost
            }

完整代码如下:

<script>
    const totalizer = {
    id: 'totalizer',
    beforeUpdate: chart => {
        let totals = {}
        let utmost = 0

            chart.data.datasets.forEach((dataset, datasetIndex) => {
                if (chart.isDatasetVisible(datasetIndex)) {
                    utmost = datasetIndex
                        dataset.data.forEach((value, index) => {
                            totals[index] = (totals[index] || 0) + value
                        })
                }
            })
            chart.$totalizer = {
            totals: totals,
            utmost: utmost
        }
    }
}

new Chart('chart', {
    type: 'bar',
    data: {
        labels: ["Note par thème du répondant", "Note par thème sectorielle", "Note par thème générale"],
        datasets: [{
                label: 'Thème 1',
                data: [10, 10, 10],
                backgroundColor: 'rgba(68,114,196,0.6)'
            }, {
                label: 'Thème 2',
                data: [13, 8, 11],
                backgroundColor: 'rgba(237,125,49,0.6)'
            }, {
                label: 'Thème 3',
                data: [5, 12, 13],
                backgroundColor: 'rgba(165,165,165,0.6)'
            }, {
                label: 'Thème 4',
                data: [9, 12, 13],
                backgroundColor: 'rgba(255,192,0,0.6)'
            }, {
                label: 'Thème 5',
                data: [5, 12, 9],
                backgroundColor: 'rgba(91,155,213,0.6)'
            }, {
                label: 'Thème 6',
                data: [9, 12, 5],
                backgroundColor: 'rgba(112,173,71,0.6)'
            }, {
                label: 'Thème 7',
                data: [5, 12, 10],
                backgroundColor: 'rgba(38,68,120,0.6)'
            }, {
                label: 'Thème 8',
                data: [15, 12, 10],
                backgroundColor: 'rgba(99,99,99,0.6)'
            }, {
                label: 'Thème 9',
                data: [15, 12, 11],
                backgroundColor: 'rgba(37,94,145,0.6)'
            }, {
                label: 'Thème 10',
                data: [10, 4, 7],
                backgroundColor: 'rgba(24,91,62,0.6)'
            }, {
                label: 'Total',
                data: [0, 0, 0],
                backgroundColor: 'rgba(24,91,62,0)',
                datalabels: {
                    backgroundColor: function (context) {

                        return 'rgba(244,50,49)';

                    },
                    formatter: (value, ctx) => {
                        const total = ctx.chart.$totalizer.totals[ctx.dataIndex];
                        return total.toLocaleString('fr-FR', {})
                    },
                    align: 'end',
                    anchor: 'end',
                    display: function (ctx) {
                        return ctx.datasetIndex === ctx.chart.$totalizer.utmost
                    }
                }
            }
        ]
    },
    options: {
        title: {

            text: "Mon titre",

            display: true
        },
        scales: {
            yAxes: [{
                    stacked: true,
                    ticks: {
                        beginAtZero: true,
                        suggestedMax: 100
                    }
                }
            ],
            xAxes: [{
                    stacked: true
                }
            ]
        },
        plugins: {
            datalabels: {

                color: 'rgba(255,255,255)',

                display: function (context) {
                    return context.chart.isDatasetVisible(context.datasetIndex);
                },
                backgroundColor: function (context) {
                    return context.dataset.backgroundColor;
                },
                borderRadius: 4,
                font: {
                    weight: 'bold'
                }
            }
        }
    },
    plugins: [totalizer]
});
 </script>

2
投票

太棒了!我只是简化了没有 totilizer 的解决方案:

datasets:  {
    label: 'Total',
    data: [120, 120, 120, 120, 120, 120, 120, 120, 120, 120],
    backgroundColor: 'rgba(24,91,62,0)',
    datalabels: {
        backgroundColor: () => 'white',
        formatter: (value, ctx) => {
            let total = 0;
            let index = ctx.dataIndex;
            data.datasets.map((d, i) => {
                if (i === 2) return;
                total += d.data[index];
            });
            return total;
        },
        align: 'end',
        anchor: 'end',
        padding: 0,
    },
},

0
投票

我通过这个自定义格式化程序解决了这个问题

datalabels: {
                    anchor: 'end',
                    align: 'right',
                    formatter: (value, ctx) => {
                        const stackedValues = ctx.chart.data.datasets.map(
                          (ds) => ds.data[ctx.dataIndex]
                        );
                        const dsIdxLastVisibleNonZeroValue = stackedValues.reduce(
                          (prev, curr, i) =>
                            !!curr && !ctx.chart.getDatasetMeta(i).hidden
                              ? Math.max(prev, i)
                              : prev,
                          0
                        );
                        if (!!value && ctx.datasetIndex === dsIdxLastVisibleNonZeroValue) {
                          return stackedValues
                            .filter((ds, i) => !ctx.chart.getDatasetMeta(i).hidden)
                            .reduce((sum, v) => sum + v, 0);
                        } else {
                          return '';
                        }
                    },
                    font: {
                        weight: 'bold',
                        size: 16
                    }
                }
© www.soinside.com 2019 - 2024. All rights reserved.