在chart.js的堆叠条形图中展示百分比和总数

6
我正在使用chart.js制作堆叠柱状图。 我需要在每个柱子中间显示标签,以百分比和总和的形式在堆叠在一起的柱子上方显示。目前,我能够在搜索代码后显示它们的百分比。但是这些百分比在数学上不正确。我已经将该代码添加到js fiddle中。希望我可以得到一些帮助。我只是对js很弱。
https://jsfiddle.net/n4nish/hca3wdgq/4/

HTML -

  var data = [{
     label: 'New',
     backgroundColor: '#1d3f74',
     data: [6310, 5742, 4044, 5564]
        }, {
     label: 'Repeat',
     backgroundColor: '#6c92c8',
     data: [11542, 12400, 12510, 11450]
        }];


 var options = {
     maintainAspectRatio: false,
     spanGaps: false,
     responsive: true,
     legend: {
         display: true,
         position: 'bottom',
         labels: {
             fontColor: "#fff",
             boxWidth: 14,
             fontFamily: 'proximanova'
         }
     },
     tooltips: {
         mode: 'label',
         callbacks: {
             label: function (tooltipItem, data) {
                 var type = data.datasets[tooltipItem.datasetIndex].label;
                 var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
                 var total = 0;
                 for (var i = 0; i < data.datasets.length; i++)
                     total += data.datasets[i].data[tooltipItem.index];
                 if (tooltipItem.datasetIndex !== data.datasets.length - 1) {
                     return type + " : " + value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, '1,');
                 } else {
                     return [type + " : " + value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, '1,'), "Overall : " + total];
                 }
             }
         }
     },
     plugins: {
         datalabels: {
             formatter: function (value, ctx) {
                 let sum = 0;
                 let dataArr = ctx.chart.data.datasets[0].data;
                 dataArr.map(data => {
                     sum += data;
                 });
                 let percentage = (value * 100 / sum).toFixed(0) + "%";
                 return percentage;
             },
             font: {
                 weight: "normal"
             },
             color: "#fff"
         }
     },
     scales: {
         xAxes: [{
             stacked: true,
             gridLines: {
                 display: false
             },
             ticks: {
                 fontColor: "#fff"
             }
                }],
         yAxes: [{
             stacked: true,
             display: false,
             ticks: {
                 fontColor: "#fff"
             }
                }]
     }

 };

 var ctx = document.getElementById("mychart").getContext('2d');

 var myChart = new Chart(ctx, {
     type: 'bar',
     data: {
         labels: ["Jun", "July", "Aug", "Sept"],
         datasets: data
     },
     options: options
 });

你想在深蓝色部分显示总和,在浅蓝色部分显示百分比吗? - ksav
嗨,不,实际上我想在浅蓝色和深蓝色中都显示百分比。总数应该在其上方。您可以看到百分比已经存在,但是它给出了错误的结果。 - Nishant Sharma
1个回答

8
您可以设置以下选项,这些选项将适用于:
图表中的所有标签: options.plugins.datalabels.* 仅适用于单个数据集: dataset.datalabels.*

// Label formatter function
const formatter = (value, ctx) => {
  const otherDatasetIndex = ctx.datasetIndex === 0 ? 1 : 0;
  const total =
    ctx.chart.data.datasets[otherDatasetIndex].data[ctx.dataIndex] + value;

  return `${(value / total * 100).toFixed(0)}%`;
};

const data = [{
    // stack: 'test',
    label: "New",
    backgroundColor: "#1d3f74",
    data: [6310, 5742, 4044, 5564],
    // Change options only for labels of THIS DATASET
    datalabels: {
      color: "white",
      formatter: formatter
    }
  },
  {
    // stack: 'test',
    label: "Repeat",
    backgroundColor: "#6c92c8",
    data: [11542, 12400, 12510, 11450],
    // Change options only for labels of THIS DATASET
    datalabels: {
      color: "yellow",
      formatter: formatter
    }
  }
];

const options = {
  maintainAspectRatio: false,
  spanGaps: false,
  responsive: true,
  legend: {
    display: true,
    position: "bottom",
    labels: {
      fontColor: "#fff",
      boxWidth: 14,
      fontFamily: "proximanova"
    }
  },
  tooltips: {
    mode: "label",
    callbacks: {
      label: function(tooltipItem, data) {
        const type = data.datasets[tooltipItem.datasetIndex].label;
        const value =
          data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
        let total = 0;
        for (let i = 0; i < data.datasets.length; i++)
          total += data.datasets[i].data[tooltipItem.index];
        if (tooltipItem.datasetIndex !== data.datasets.length - 1) {
          return (
            type + " : " + value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, "1,")
          );
        } else {
          return [
            type +
            " : " +
            value.toFixed(0).replace(/(\d)(?=(\d{3})+\.)/g, "1,"),
            "Overall : " + total
          ];
        }
      }
    }
  },
  plugins: {
    // Change options for ALL labels of THIS CHART
    datalabels: {
      color: "#white",
      align: "center"
    }
  },
  scales: {

    xAxes: [{
        stacked: true,
        gridLines: {
          display: false
        },
        ticks: {
          fontColor: "#fff"
        }
      },
      {
        type: 'category',
        offset: true,
        position: 'top',
        ticks: {
          fontColor: "#fff",
          callback: function(value, index, values) {
            return data[0].data[index] + data[1].data[index]
          }
        }
      }
    ],
    yAxes: [{
      stacked: true,
      display: false,
      ticks: {
        fontColor: "#fff"
      }
    }]
  }
};

const ctx = document.getElementById("mychart").getContext("2d");

new Chart(ctx, {
  type: "bar",
  data: {
    labels: ["Jun", "July", "Aug", "Sept"],
    datasets: data
  },
  options: options
});
body {
  background: #20262e;
  font-family: Helvetica;
  padding-top: 50px;
}

#mychart {
  height: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@0.4.0/dist/chartjs-plugin-datalabels.min.js"></script>

<canvas id="mychart"></canvas>

Codepen


嗨,谢谢你的回答。实际上这不是我想要的。 我正在尝试,在第一个柱状图中,比如说, 我想显示百分之几。底部的一个显示了29%,上面的应该显示71%。总用户数将显示在顶部。 我也在尝试自己做。如果我找到了什么,我也会在这里发布代码。 - Nishant Sharma
我对格式化程序进行了小修改。如果这正是你想要的,请告诉我。 - ksav
你好,非常感谢您的帮助。如果可以的话还有一件事。 我们能把“总计”反映在条形图的顶部吗?我的问题是我对它的语法不熟悉。如果您可以在浅色条上方显示总值,然后将其向上移动,那么可能会更好? - Nishant Sharma
谢谢你提供这张图片。我已经进行了另一次编辑。如果可以的话,下次请从一开始就添加这样的图片 :) - ksav
非常感谢您的解决。 :) 是的,下次我会记住提供图像的事情。 :) 如果可能的话,还有一件小事。我们如何删除x轴下面的那些水平线?这对于月份和总数都是共同的。我通过gridLines:{display false}删除了垂直线 - Nishant Sharma
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接