简体   繁体   中英

ChartJS: datalabels: show percentage value in Pie piece

I have a piechart with four labels:

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

Using chartjs-plugin-datalabels plugin I wanted to show percentage value in each Pie piece with below code:

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',
}

I am getting 100% value for all the pie pieces, instead of respective percentages. Here is the JSFiddle ( https://jsfiddle.net/kingBethal/a1Lvn4eb/7/ )

I have a piechart with four labels:

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

Using chartjs-plugin-datalabels plugin I wanted to show percentage value in each Pie piece with below code:

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',
}

I am getting 100% value for all the pie pieces, instead of respective percentages. Here is the JSFiddle ( https://jsfiddle.net/kingBethal/a1Lvn4eb/7/ )

I have a piechart with four labels:

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

Using chartjs-plugin-datalabels plugin I wanted to show percentage value in each Pie piece with below code:

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',
}

I am getting 100% value for all the pie pieces, instead of respective percentages. Here is the JSFiddle ( https://jsfiddle.net/kingBethal/a1Lvn4eb/7/ )

I have a piechart with four labels:

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

Using chartjs-plugin-datalabels plugin I wanted to show percentage value in each Pie piece with below code:

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',
}

I am getting 100% value for all the pie pieces, instead of respective percentages. Here is the JSFiddle ( https://jsfiddle.net/kingBethal/a1Lvn4eb/7/ )

I have a piechart with four labels:

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

Using chartjs-plugin-datalabels plugin I wanted to show percentage value in each Pie piece with below code:

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',
}

I am getting 100% value for all the pie pieces, instead of respective percentages. Here is the JSFiddle ( https://jsfiddle.net/kingBethal/a1Lvn4eb/7/ )

I am using ChartJS v3.7.0 and chartjs-plugin-datalabels v2.0.0 and this answer:

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

does not really work for me, while I just wanted to keep the percentages up to date, also when hiding elements. It seems that ctx.dataset._meta is not available anymore. I came up with some ugly monkey patch:

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 this might help anybody. Cheers.

Apparently, ChartDataLabels is now exported from another package chartjs-plugin-datalabels . I installed the package using npm i chartjs-plugin-datalabels and then modified my code as below.

import React from "react";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import { Pie } from "react-chartjs-2";

ChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);

export default function PieChart() {
  return (
    <>
      <Pie
        options={{
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: { display: false },
            tooltip: false,
            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",
            },
          },
          onHover: function (e) {
            e.native.target.style.cursor = "pointer";
          },
          rotation: 270,
          events: ["click"],
          onClick: function (event, element) {
            console.log(element[0].index);
          },
        }}
        data={{
          labels: ["Above 60%", "Below 60%"],
          datasets: [
            {
              data: [20, 10],
              backgroundColor: ["#3A925D", "#FD7E14"],
              borderWidth: 0,
            },
          ],
        }}
      />
    </>
  );
}

Result在此处输入图像描述

This is update for chart.js >= 3.x and chartjs-plugin-datalabels >= 2.x

chartjs-plugin-datalabels plugin no longer registers itself automatically ( docs )

You have to do it manually

Register plugin for all charts

Chart.register(ChartDataLabels)

or only to specific charts

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

And here's the code below to render the pie chart

 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>

if you use nodejs: follow the steps:

  1. npm install chartjs-plugin-datalabels
  2. import ChartDataLabels from 'chartjs-plugin-datalabels';
  3. Chart.register(...registerables, ChartDataLabels);
  4. copy the code from the over comments...

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

As some people mentioned, context.dataset._meta[0].total seem to have been removed in chart.js version 3 and above and didn't work anymore. Instead, I used context.chart.getDatasetMeta(0).total and it worked for me - it shows percentage values in pie chart and value gets updated based on the filtered total when the legends are clicked.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM